update issue panel
This commit is contained in:
Generated
+68
-68
@@ -1268,7 +1268,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collections"
|
name = "collections"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui_util",
|
"gpui_util",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -1551,9 +1551,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
checksum = "8498c871161e1742aaa9d52551b2d6ebdd4c3d45a3be423e3728f33b955be550"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -1734,7 +1734,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_refineable"
|
name = "derive_refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2256,9 +2256,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "font-types"
|
name = "font-types"
|
||||||
version = "0.12.3"
|
version = "0.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75382bc7392ef10aad10935f92fc3db36d2d4dad0e5d96d8d65e04f89a07ec39"
|
checksum = "e64eb721ca85a34323425f4041adc5d82704d3782d5f8f03793bc012419dce23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
@@ -2798,9 +2798,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-features"
|
name = "gix-features"
|
||||||
version = "0.49.0"
|
version = "0.49.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20aa09e83a48dc02c5f5f08578aa79d3ab1bab4618b8c362f88684645a02bdcc"
|
checksum = "39c0e59d9d253dcccc38c3a46b91bfb9b46bd63eed54fe1a719e12194884d52a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
@@ -2838,9 +2838,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-fs"
|
name = "gix-fs"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "865cf13fcaf5455220546cb9607c416bd1be9a6caafd143655a362fdeab64e80"
|
checksum = "ebcfa9fd253f25350a3b21b3dd74034a446098e373c6123d4cee3519894f12ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"gix-features",
|
"gix-features",
|
||||||
@@ -2851,9 +2851,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-glob"
|
name = "gix-glob"
|
||||||
version = "0.27.0"
|
version = "0.27.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "421e92a711554fa5827d1b0599d3389acdd0f6729e97a8c5a57d79af1e50bf36"
|
checksum = "b417cf515fd8c91468b578071f76d6cba716f8a1eccd853906bff4908b2c1413"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"bstr",
|
"bstr",
|
||||||
@@ -2863,9 +2863,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-hash"
|
name = "gix-hash"
|
||||||
version = "0.26.0"
|
version = "0.26.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13adaa73415fd6c902310923f68d0b98e8cecf14b33ea58c02cc387cee56f54e"
|
checksum = "caf125eae66b7d6e4395511a06c0d43a3c34eac96c8641fb98b22078faee65b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"faster-hex",
|
"faster-hex",
|
||||||
"gix-features",
|
"gix-features",
|
||||||
@@ -2886,9 +2886,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-ignore"
|
name = "gix-ignore"
|
||||||
version = "0.22.0"
|
version = "0.22.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "12cff8e8aa125e39377456073e63df3334d9e5741372ddcc226198015076dda2"
|
checksum = "65859a2f7de5e159d4344a5486ebf53b6bac22d5ec6afa836e47c10ae88a7f0f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"gix-glob",
|
"gix-glob",
|
||||||
@@ -2899,9 +2899,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-imara-diff"
|
name = "gix-imara-diff"
|
||||||
version = "0.2.4"
|
version = "0.2.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a791e6620676a875f362f3156ed213e73ca099a09bf992c18812abe65cc37b1"
|
checksum = "1c91d8cffac8849493a82233811bd02b2b183b8cf39bf704de0fa0841b737595"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
@@ -3037,9 +3037,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-path"
|
name = "gix-path"
|
||||||
version = "0.12.4"
|
version = "0.12.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "751d6bd162106f8c1e7e9aaccb5bbdd605267e91a930a17a4560c46e33a9100c"
|
checksum = "2b075e730586bba7341304d6fc1b4efc1d10cf64532622521c0e07f30e661046"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"gix-trace",
|
"gix-trace",
|
||||||
@@ -3295,9 +3295,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-utils"
|
name = "gix-utils"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1795bd2a970ca8b2185318c2abb97d955c71992f1cf28de73ad3b593a9f3ce8"
|
checksum = "0da1c46491b49458a446cc76f0085860f8164c2290742e0aa8c653ce67240a97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
@@ -3307,9 +3307,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gix-validate"
|
name = "gix-validate"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a034e84d1e04e1b1f20f51f12491da230b6ac8b925d0c8e1b89bcd87a7c5ccc"
|
checksum = "4dae8780f63ed8a803b8bdabbd7aa5f5c5d74592c8b50eed875c1bb4f6545a6a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
]
|
]
|
||||||
@@ -3489,7 +3489,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -3562,7 +3562,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui-base"
|
name = "gpui-base"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "git+https://github.com/longbridge/gpui-component#14359a0cdd00657eb68fa946bfd99cd83c26e002"
|
source = "git+https://github.com/longbridge/gpui-component#9e6d5000b4020e7849e167faa1f3ee8932480ff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -3594,7 +3594,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui-component"
|
name = "gpui-component"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "git+https://github.com/longbridge/gpui-component#14359a0cdd00657eb68fa946bfd99cd83c26e002"
|
source = "git+https://github.com/longbridge/gpui-component#9e6d5000b4020e7849e167faa1f3ee8932480ff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -3674,7 +3674,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui-component-assets"
|
name = "gpui-component-assets"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "git+https://github.com/longbridge/gpui-component#14359a0cdd00657eb68fa946bfd99cd83c26e002"
|
source = "git+https://github.com/longbridge/gpui-component#9e6d5000b4020e7849e167faa1f3ee8932480ff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -3688,7 +3688,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui-component-macros"
|
name = "gpui-component-macros"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "git+https://github.com/longbridge/gpui-component#14359a0cdd00657eb68fa946bfd99cd83c26e002"
|
source = "git+https://github.com/longbridge/gpui-component#9e6d5000b4020e7849e167faa1f3ee8932480ff6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3698,7 +3698,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_apple"
|
name = "gpui_apple"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"block",
|
"block",
|
||||||
@@ -3721,7 +3721,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_linux"
|
name = "gpui_linux"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_unix",
|
"accesskit_unix",
|
||||||
@@ -3767,7 +3767,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_macos"
|
name = "gpui_macos"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_macos",
|
"accesskit_macos",
|
||||||
@@ -3813,7 +3813,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_macros"
|
name = "gpui_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -3824,7 +3824,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_platform"
|
name = "gpui_platform"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -3837,7 +3837,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_shared_string"
|
name = "gpui_shared_string"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3847,7 +3847,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_util"
|
name = "gpui_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"log",
|
"log",
|
||||||
@@ -3857,7 +3857,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_web"
|
name = "gpui_web"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
@@ -3881,7 +3881,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_wgpu"
|
name = "gpui_wgpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
@@ -3907,7 +3907,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_windows"
|
name = "gpui_windows"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_windows",
|
"accesskit_windows",
|
||||||
@@ -4234,7 +4234,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "http_client"
|
name = "http_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@@ -4254,7 +4254,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "http_client_tls"
|
name = "http_client_tls"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-platform-verifier 0.5.3",
|
"rustls-platform-verifier 0.5.3",
|
||||||
@@ -5039,9 +5039,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.33"
|
version = "0.4.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
"value-bag",
|
"value-bag",
|
||||||
@@ -5230,7 +5230,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "media"
|
name = "media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
@@ -5445,7 +5445,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr"
|
name = "nostr"
|
||||||
version = "0.45.3"
|
version = "0.45.3"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -5471,7 +5471,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-connect"
|
name = "nostr-connect"
|
||||||
version = "0.45.1"
|
version = "0.45.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -5485,7 +5485,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-database"
|
name = "nostr-database"
|
||||||
version = "0.45.1"
|
version = "0.45.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nostr",
|
"nostr",
|
||||||
"opaquerr",
|
"opaquerr",
|
||||||
@@ -5494,7 +5494,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-gossip"
|
name = "nostr-gossip"
|
||||||
version = "0.45.0"
|
version = "0.45.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nostr",
|
"nostr",
|
||||||
"opaquerr",
|
"opaquerr",
|
||||||
@@ -5503,7 +5503,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-gossip-memory"
|
name = "nostr-gossip-memory"
|
||||||
version = "0.45.0"
|
version = "0.45.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lru",
|
"lru",
|
||||||
@@ -5515,7 +5515,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-lmdb"
|
name = "nostr-lmdb"
|
||||||
version = "0.45.2"
|
version = "0.45.2"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
@@ -5530,7 +5530,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-memory"
|
name = "nostr-memory"
|
||||||
version = "0.45.1"
|
version = "0.45.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"btreecap",
|
"btreecap",
|
||||||
"nostr",
|
"nostr",
|
||||||
@@ -5541,7 +5541,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-sdk"
|
name = "nostr-sdk"
|
||||||
version = "0.45.2"
|
version = "0.45.2"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#4dcf307d6102e598f3a4172b8ba5a7a779fa1630"
|
source = "git+https://github.com/rust-nostr/nostr#ea38c0e3b2fc2717a4a55d019560a5574baf8cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"async-wsocket",
|
"async-wsocket",
|
||||||
@@ -6154,9 +6154,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "5.3.0"
|
version = "5.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e"
|
checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@@ -6277,7 +6277,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "perf"
|
name = "perf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collections",
|
"collections",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -7021,7 +7021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709"
|
checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"font-types 0.12.3",
|
"font-types 0.12.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7074,7 +7074,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "refineable"
|
name = "refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_refineable",
|
"derive_refineable",
|
||||||
]
|
]
|
||||||
@@ -7157,7 +7157,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest_client"
|
name = "reqwest_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -7486,9 +7486,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.103.14"
|
version = "0.103.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0527518605e68109d875e248ea259b6758801cf165e4b2c2733ae3b51f12535a"
|
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"ring",
|
"ring",
|
||||||
@@ -7569,7 +7569,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "scheduler"
|
name = "scheduler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-task",
|
"async-task",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -8296,7 +8296,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sum_tree"
|
name = "sum_tree"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapless 0.9.3",
|
"heapless 0.9.3",
|
||||||
"log",
|
"log",
|
||||||
@@ -9669,7 +9669,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util_macros"
|
name = "util_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"perf",
|
"perf",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -9685,9 +9685,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.24.1"
|
version = "1.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9"
|
checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -11467,7 +11467,7 @@ checksum = "34b31d188d9d685a4f9c7b46d6e36631b07058d2cfe190267adce54dc230bf12"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "zlog"
|
name = "zlog"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -11484,7 +11484,7 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing"
|
name = "ztracing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -11495,7 +11495,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing_macro"
|
name = "ztracing_macro"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#ec18126b1dbd32b089e51d7edee1e20b3bd53637"
|
source = "git+https://github.com/zed-industries/zed#d9ad6aff67e47de43abb270d22de75dd950f1b48"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
|
|||||||
@@ -59,6 +59,32 @@ pub fn grasp_list(public_key: PublicKey) -> Filter {
|
|||||||
.author(public_key)
|
.author(public_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NIP-22 comments (kind `1111`) referencing any of the given root events
|
||||||
|
/// (issues, patches, PRs).
|
||||||
|
///
|
||||||
|
/// Comments are not addressed to the repository — they carry no `a` tag with
|
||||||
|
/// the repo coordinate — so they must be fetched by their root reference
|
||||||
|
/// instead. NIP-22 defines the uppercase `E` tag as the root of the thread
|
||||||
|
/// (used by ngit) while some clients (including Signed itself) reference the
|
||||||
|
/// root with a lowercase `e` tag, so both are matched.
|
||||||
|
///
|
||||||
|
/// Returns two filters because `#E` and `#e` conditions would be ANDed if
|
||||||
|
/// combined into one.
|
||||||
|
pub fn comments_for(roots: impl IntoIterator<Item = EventId>) -> Vec<Filter> {
|
||||||
|
let roots: Vec<String> = roots.into_iter().map(|id| id.to_hex()).collect();
|
||||||
|
if roots.is_empty() {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
vec![
|
||||||
|
Filter::new()
|
||||||
|
.kind(Kind::Comment)
|
||||||
|
.custom_tags(SingleLetterTag::UPPERCASE_E, roots.clone()),
|
||||||
|
Filter::new()
|
||||||
|
.kind(Kind::Comment)
|
||||||
|
.custom_tags(SingleLetterTag::LOWERCASE_E, roots),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
/// All repositories announced by an author.
|
/// All repositories announced by an author.
|
||||||
pub fn announcements_by(public_key: PublicKey) -> Filter {
|
pub fn announcements_by(public_key: PublicKey) -> Filter {
|
||||||
Filter::new()
|
Filter::new()
|
||||||
|
|||||||
@@ -30,9 +30,15 @@ impl RepoStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether a status event references the given root event via an `e` tag.
|
/// Check whether an event references the given root event via an `e` or `E`
|
||||||
|
/// tag. NIP-10 / NIP-34 use the lowercase `e` tag; NIP-22 comments (kind
|
||||||
|
/// `1111`) use the uppercase `E` tag for the root of the thread.
|
||||||
pub fn references_root(event: &Event, root: &EventId) -> bool {
|
pub fn references_root(event: &Event, root: &EventId) -> bool {
|
||||||
event.tags.event_ids().any(|id| id == *root)
|
let root = root.to_hex();
|
||||||
|
event
|
||||||
|
.tags
|
||||||
|
.iter()
|
||||||
|
.any(|tag| matches!(tag.kind(), "e" | "E") && tag.content() == Some(root.as_str()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolve the status of a root event per NIP-34:
|
/// Resolve the status of a root event per NIP-34:
|
||||||
@@ -96,6 +102,23 @@ mod tests {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn references_root_matches_uppercase_e_tag() {
|
||||||
|
let root = root_event_id();
|
||||||
|
let event = EventBuilder::new(Kind::Comment, "")
|
||||||
|
.tags([Tag::parse(["E", ROOT_ID_HEX]).expect("valid E tag")])
|
||||||
|
.finalize(&keys_from_hex(
|
||||||
|
"0000000000000000000000000000000000000000000000000000000000000001",
|
||||||
|
))
|
||||||
|
.expect("signed event");
|
||||||
|
|
||||||
|
assert!(references_root(&event, &root));
|
||||||
|
assert!(!references_root(
|
||||||
|
&event,
|
||||||
|
&EventId::from_hex(OTHER_ID_HEX).expect("valid id")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn references_root_false_without_e_tags() {
|
fn references_root_false_without_e_tags() {
|
||||||
let event = EventBuilder::new(Kind::GitStatusOpen, "")
|
let event = EventBuilder::new(Kind::GitStatusOpen, "")
|
||||||
|
|||||||
@@ -670,6 +670,30 @@ impl Backend {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Connect to relays announced by a repository (NIP-34 `relays` tag) and
|
||||||
|
/// fetch its events from them: a one-shot auto-closing subscription for
|
||||||
|
/// `filters`, plus a negentropy sync so issues, patches and PRs stored
|
||||||
|
/// only on those relays are not missed.
|
||||||
|
///
|
||||||
|
/// Best-effort: failures are logged, not surfaced, because the bootstrap
|
||||||
|
/// relays already cover the repository. The relays stay in the pool, so
|
||||||
|
/// events the user publishes for this repository also reach them.
|
||||||
|
pub fn connect_repo_relays(
|
||||||
|
&mut self,
|
||||||
|
relays: Vec<RelayUrl>,
|
||||||
|
filters: Vec<Filter>,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
let client = self.client.clone();
|
||||||
|
|
||||||
|
self.tasks.push(cx.spawn(async move |_this, _cx| {
|
||||||
|
if let Err(e) = connect_repo_relays_only(&client, relays, filters).await {
|
||||||
|
log::warn!("repo relay fetch failed: {e}");
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/// Start a one-shot subscription targeted only at the bootstrap relays,
|
/// Start a one-shot subscription targeted only at the bootstrap relays,
|
||||||
/// auto-closing after EOSE or a short timeout. Matching events are stored
|
/// auto-closing after EOSE or a short timeout. Matching events are stored
|
||||||
/// in the database and surface as [`BackendEvent::NostrUpdate`] while the
|
/// in the database and surface as [`BackendEvent::NostrUpdate`] while the
|
||||||
@@ -832,6 +856,50 @@ impl Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add the given relays, connect to them, and fetch the filters: a one-shot
|
||||||
|
/// subscription (auto-closing after EOSE) plus a negentropy sync per filter
|
||||||
|
/// as a second pass, so events that race with the subscription or relays
|
||||||
|
/// with flaky EOSE behavior can't be missed. Relays without NEG-XX support
|
||||||
|
/// just fail the sync step; the subscription already covered them.
|
||||||
|
async fn connect_repo_relays_only(
|
||||||
|
client: &Client,
|
||||||
|
relays: Vec<RelayUrl>,
|
||||||
|
filters: Vec<Filter>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
if relays.is_empty() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
for url in &relays {
|
||||||
|
client.add_relay(url).await?;
|
||||||
|
}
|
||||||
|
client.connect().await;
|
||||||
|
|
||||||
|
let opts = SubscribeAutoCloseOptions::default()
|
||||||
|
.exit_policy(ReqExitPolicy::ExitOnEOSE)
|
||||||
|
.timeout(Some(Duration::from_secs(10)));
|
||||||
|
|
||||||
|
let target: HashMap<&str, Vec<Filter>> = relays
|
||||||
|
.iter()
|
||||||
|
.map(|url| (url.as_str(), filters.clone()))
|
||||||
|
.collect();
|
||||||
|
client.subscribe(target).close_on(opts).await?;
|
||||||
|
|
||||||
|
for filter in filters {
|
||||||
|
let sync_opts = SyncOptions::default().initial_timeout(Duration::from_secs(5));
|
||||||
|
if let Err(e) = client
|
||||||
|
.sync(filter)
|
||||||
|
.with(relays.iter())
|
||||||
|
.opts(sync_opts)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
log::warn!("repo relay negentropy sync failed: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Subscribe only on the bootstrap relays, auto-closing after EOSE or a
|
/// Subscribe only on the bootstrap relays, auto-closing after EOSE or a
|
||||||
/// short timeout. Use for one-shot data fetches (repo events, profiles)
|
/// short timeout. Use for one-shot data fetches (repo events, profiles)
|
||||||
/// instead of persistent gossip-routed subscriptions.
|
/// instead of persistent gossip-routed subscriptions.
|
||||||
|
|||||||
+110
-11
@@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
@@ -32,6 +33,13 @@ pub struct RepoStore {
|
|||||||
statuses: Vec<Event>,
|
statuses: Vec<Event>,
|
||||||
/// Error of the last action initiated from this store, if any.
|
/// Error of the last action initiated from this store, if any.
|
||||||
pub last_error: Option<String>,
|
pub last_error: Option<String>,
|
||||||
|
/// Relays announced by this repository (NIP-34 `relays` tag) that we
|
||||||
|
/// have already been asked to connect to and fetch from, to avoid
|
||||||
|
/// re-subscribing on every refresh.
|
||||||
|
repo_relays: HashSet<RelayUrl>,
|
||||||
|
/// Root events (issues, patches, PRs) for which a NIP-22 comment fetch
|
||||||
|
/// has already been requested, to avoid re-fetching on every refresh.
|
||||||
|
comment_roots: HashSet<EventId>,
|
||||||
refreshing: bool,
|
refreshing: bool,
|
||||||
refresh_dirty: bool,
|
refresh_dirty: bool,
|
||||||
/// A refresh is waiting out [`REFRESH_DEBOUNCE`].
|
/// A refresh is waiting out [`REFRESH_DEBOUNCE`].
|
||||||
@@ -41,7 +49,7 @@ pub struct RepoStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RepoStore {
|
impl RepoStore {
|
||||||
pub fn new(addr: RepoAddr, cx: &mut Context<Self>) -> Self {
|
pub fn new(addr: RepoAddr, announced_relays: Vec<RelayUrl>, cx: &mut Context<Self>) -> Self {
|
||||||
let backend = Backend::global(cx);
|
let backend = Backend::global(cx);
|
||||||
|
|
||||||
let subscription = cx.subscribe(&backend, |this, _backend, event, cx| {
|
let subscription = cx.subscribe(&backend, |this, _backend, event, cx| {
|
||||||
@@ -53,8 +61,12 @@ impl RepoStore {
|
|||||||
let coordinate = update.coordinate.as_ref() == Some(&this.addr);
|
let coordinate = update.coordinate.as_ref() == Some(&this.addr);
|
||||||
let author = update.author == this.addr.public_key;
|
let author = update.author == this.addr.public_key;
|
||||||
let kind = update.kind == Kind::GitRepoAnnouncement;
|
let kind = update.kind == Kind::GitRepoAnnouncement;
|
||||||
|
// NIP-22 comments carry no `a` tag, so they can't be
|
||||||
|
// matched by coordinate; any comment may reference this
|
||||||
|
// repository's roots.
|
||||||
|
let comment = update.kind == Kind::Comment;
|
||||||
|
|
||||||
deletion || coordinate || (author && kind)
|
deletion || coordinate || (author && kind) || comment
|
||||||
}
|
}
|
||||||
BackendEvent::Published(event) => {
|
BackendEvent::Published(event) => {
|
||||||
let kind = event.kind == Kind::GitRepoAnnouncement;
|
let kind = event.kind == Kind::GitRepoAnnouncement;
|
||||||
@@ -82,6 +94,8 @@ impl RepoStore {
|
|||||||
comments: Vec::new(),
|
comments: Vec::new(),
|
||||||
statuses: Vec::new(),
|
statuses: Vec::new(),
|
||||||
last_error: None,
|
last_error: None,
|
||||||
|
repo_relays: HashSet::new(),
|
||||||
|
comment_roots: HashSet::new(),
|
||||||
refreshing: false,
|
refreshing: false,
|
||||||
refresh_dirty: false,
|
refresh_dirty: false,
|
||||||
debouncing: false,
|
debouncing: false,
|
||||||
@@ -90,6 +104,10 @@ impl RepoStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
store.subscribe_remote(cx);
|
store.subscribe_remote(cx);
|
||||||
|
// The announcement we opened the repo from may already list its
|
||||||
|
// relays; connect to them right away instead of waiting for the
|
||||||
|
// bootstrap fetch to return the same event.
|
||||||
|
store.connect_announced_relays(&announced_relays, cx);
|
||||||
store.refresh(cx);
|
store.refresh(cx);
|
||||||
store
|
store
|
||||||
}
|
}
|
||||||
@@ -98,6 +116,42 @@ impl RepoStore {
|
|||||||
&self.addr
|
&self.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Filters that make up a repository: announcement, state, activity and
|
||||||
|
/// deletions targeting it.
|
||||||
|
fn repo_filters(addr: &RepoAddr) -> Vec<Filter> {
|
||||||
|
let mut filters = vec![
|
||||||
|
filters::announcement(addr),
|
||||||
|
filters::state(addr),
|
||||||
|
filters::activity(addr),
|
||||||
|
];
|
||||||
|
// Deletion requests (NIP-09/62) must be known before any event of
|
||||||
|
// this repository can be shown.
|
||||||
|
filters.extend(filters::deletions_for_repo(addr));
|
||||||
|
filters
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch this repository's events from the relays announced in its
|
||||||
|
/// NIP-34 `relays` tag. Deduplicated: each relay is only contacted once
|
||||||
|
/// per store, so refreshes after the first are no-ops unless the
|
||||||
|
/// announcement lists new relays.
|
||||||
|
fn connect_announced_relays(&mut self, relays: &[RelayUrl], cx: &mut Context<Self>) {
|
||||||
|
let new: Vec<RelayUrl> = relays
|
||||||
|
.iter()
|
||||||
|
.filter(|url| !self.repo_relays.contains(*url))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
if new.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.repo_relays.extend(new.iter().cloned());
|
||||||
|
|
||||||
|
let backend = Backend::global(cx);
|
||||||
|
let addr = self.addr.clone();
|
||||||
|
backend.update(cx, |backend, cx| {
|
||||||
|
backend.connect_repo_relays(new, Self::repo_filters(&addr), cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch this repository's events from the bootstrap relays (one-shot,
|
/// Fetch this repository's events from the bootstrap relays (one-shot,
|
||||||
/// auto-closing subscription).
|
/// auto-closing subscription).
|
||||||
fn subscribe_remote(&mut self, cx: &mut Context<Self>) {
|
fn subscribe_remote(&mut self, cx: &mut Context<Self>) {
|
||||||
@@ -105,15 +159,7 @@ impl RepoStore {
|
|||||||
let addr = self.addr.clone();
|
let addr = self.addr.clone();
|
||||||
|
|
||||||
backend.update(cx, |backend, cx| {
|
backend.update(cx, |backend, cx| {
|
||||||
let mut repo_filters = vec![
|
backend.subscribe_bootstrap(Self::repo_filters(&addr), cx);
|
||||||
filters::announcement(&addr),
|
|
||||||
filters::state(&addr),
|
|
||||||
filters::activity(&addr),
|
|
||||||
];
|
|
||||||
// Deletion requests (NIP-09/62) must be known before any
|
|
||||||
// event of this repository can be shown.
|
|
||||||
repo_filters.extend(filters::deletions_for_repo(&addr));
|
|
||||||
backend.subscribe_bootstrap(repo_filters, cx);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,6 +242,24 @@ impl RepoStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NIP-22 comments reference their root via an `E`/`e` tag rather
|
||||||
|
// than the repository's `a` tag, so query them by the root events
|
||||||
|
// of this repository.
|
||||||
|
let db = client.database();
|
||||||
|
let mut seen_comments: HashSet<EventId> = comments.iter().map(|e| e.id).collect();
|
||||||
|
let roots = issues
|
||||||
|
.iter()
|
||||||
|
.chain(&patches)
|
||||||
|
.chain(&pull_requests)
|
||||||
|
.map(|e| e.id);
|
||||||
|
for filter in filters::comments_for(roots) {
|
||||||
|
for event in db.query(filter).await? {
|
||||||
|
if seen_comments.insert(event.id) {
|
||||||
|
comments.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sort_newest_first(&mut issues);
|
sort_newest_first(&mut issues);
|
||||||
sort_newest_first(&mut patches);
|
sort_newest_first(&mut patches);
|
||||||
sort_newest_first(&mut pull_requests);
|
sort_newest_first(&mut pull_requests);
|
||||||
@@ -230,6 +294,15 @@ impl RepoStore {
|
|||||||
let again = this.update(cx, |this, cx| {
|
let again = this.update(cx, |this, cx| {
|
||||||
this.announcement = announcement;
|
this.announcement = announcement;
|
||||||
|
|
||||||
|
// The announcement may list relays for this repository's
|
||||||
|
// activity; connect to any we haven't fetched from yet.
|
||||||
|
let relays = this
|
||||||
|
.announcement
|
||||||
|
.as_ref()
|
||||||
|
.map(|a| a.relays.clone())
|
||||||
|
.unwrap_or_default();
|
||||||
|
this.connect_announced_relays(&relays, cx);
|
||||||
|
|
||||||
if let Some((refs, head)) = state {
|
if let Some((refs, head)) = state {
|
||||||
this.refs = refs;
|
this.refs = refs;
|
||||||
this.head = head;
|
this.head = head;
|
||||||
@@ -241,6 +314,32 @@ impl RepoStore {
|
|||||||
this.comments = comments;
|
this.comments = comments;
|
||||||
this.statuses = statuses;
|
this.statuses = statuses;
|
||||||
|
|
||||||
|
// Comments are not addressed to the repository, so fetch
|
||||||
|
// them by the root events they reference, on the bootstrap
|
||||||
|
// relays and on the relays this repository announced.
|
||||||
|
let roots = this
|
||||||
|
.issues
|
||||||
|
.iter()
|
||||||
|
.chain(&this.patches)
|
||||||
|
.chain(&this.pull_requests)
|
||||||
|
.map(|e| e.id)
|
||||||
|
.collect::<HashSet<EventId>>();
|
||||||
|
let new_roots: Vec<EventId> = roots
|
||||||
|
.iter()
|
||||||
|
.filter(|id| !this.comment_roots.contains(id))
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
if !new_roots.is_empty() {
|
||||||
|
this.comment_roots.extend(new_roots.iter().copied());
|
||||||
|
let comment_filters = filters::comments_for(new_roots);
|
||||||
|
let announced: Vec<RelayUrl> = this.repo_relays.iter().cloned().collect();
|
||||||
|
let backend = Backend::global(cx);
|
||||||
|
backend.update(cx, |backend, cx| {
|
||||||
|
backend.subscribe_bootstrap(comment_filters.clone(), cx);
|
||||||
|
backend.connect_repo_relays(announced, comment_filters, cx);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
|
|
||||||
this.refreshing = false;
|
this.refreshing = false;
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ pub(super) fn placeholder(message: &str, cx: &App) -> AnyElement {
|
|||||||
pub(super) fn status_badge(status: RepoStatus, cx: &App) -> AnyElement {
|
pub(super) fn status_badge(status: RepoStatus, cx: &App) -> AnyElement {
|
||||||
let (icon, label, tooltip, bg, fg) = match status {
|
let (icon, label, tooltip, bg, fg) = match status {
|
||||||
RepoStatus::Open => (
|
RepoStatus::Open => (
|
||||||
CustomIconName::GitIssueOpen,
|
CustomIconName::GitIssueDone,
|
||||||
"open",
|
"open",
|
||||||
"Issue is open",
|
"Issue is open",
|
||||||
cx.theme().primary,
|
cx.theme().primary,
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
use dock::{BasePanel, Panel, PanelEvent};
|
use dock::{BasePanel, Panel, PanelEvent};
|
||||||
use gpui::prelude::*;
|
use gpui::prelude::*;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
App, Context, Entity, EventEmitter, FocusHandle, Focusable, Render, SharedString, Window, div,
|
AnyElement, App, Context, Entity, EventEmitter, FocusHandle, Focusable, Render, SharedString,
|
||||||
px,
|
Window, div, px, relative,
|
||||||
};
|
};
|
||||||
use gpui_component::avatar::Avatar;
|
use gpui_component::avatar::Avatar;
|
||||||
use gpui_component::button::{Button, ButtonVariants};
|
use gpui_component::button::{Button, ButtonVariants};
|
||||||
use gpui_component::input::{Textarea, TextareaState};
|
use gpui_component::input::{Textarea, TextareaState};
|
||||||
|
use gpui_component::scroll::ScrollableElement;
|
||||||
|
use gpui_component::tag::Tag;
|
||||||
use gpui_component::{ActiveTheme, Sizable, StyledExt, h_flex, v_flex};
|
use gpui_component::{ActiveTheme, Sizable, StyledExt, h_flex, v_flex};
|
||||||
use nostr::prelude::{Event, EventId};
|
use nostr::prelude::{Event, EventId, PublicKey};
|
||||||
use signed_core::activity_subject;
|
use signed_core::activity_subject;
|
||||||
use signed_state::{ProfileStore, RepoStore};
|
use signed_state::{ProfileStore, RepoStore};
|
||||||
use utils::relative_time;
|
use utils::relative_time;
|
||||||
@@ -46,6 +48,88 @@ impl IssueDetailView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_sidebar(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
let profile_store = ProfileStore::global(cx);
|
||||||
|
let store = self.store.read(cx);
|
||||||
|
|
||||||
|
let Some(issue) = store.issues.iter().find(|issue| issue.id == self.issue_id) else {
|
||||||
|
// `render` already bails out when the issue is missing.
|
||||||
|
return div().into_any_element();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Participants: the issue author plus everyone who commented.
|
||||||
|
let mut participants: Vec<PublicKey> = vec![issue.pubkey];
|
||||||
|
participants.extend(store.comments_of(&issue.id).map(|comment| comment.pubkey));
|
||||||
|
participants.sort_by_key(PublicKey::to_hex);
|
||||||
|
participants.dedup();
|
||||||
|
|
||||||
|
// Issue labels are NIP-34 `t` hashtag tags on the event.
|
||||||
|
let labels: Vec<String> = issue.tags.hashtags().map(|tag| tag.to_string()).collect();
|
||||||
|
|
||||||
|
v_flex()
|
||||||
|
.w(px(240.))
|
||||||
|
.h_full()
|
||||||
|
.flex_none()
|
||||||
|
.px_4()
|
||||||
|
.gap_4()
|
||||||
|
.border_l(px(1.))
|
||||||
|
.border_color(cx.theme().sidebar_border)
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(sidebar_title("Participants", cx))
|
||||||
|
.children(participants.iter().map(|pubkey| {
|
||||||
|
let profile = profile_store.read(cx).get(pubkey);
|
||||||
|
let name = profile.name();
|
||||||
|
let picture = profile.picture();
|
||||||
|
|
||||||
|
h_flex()
|
||||||
|
.gap_2()
|
||||||
|
.items_center()
|
||||||
|
.child(
|
||||||
|
Avatar::new()
|
||||||
|
.name(name.clone())
|
||||||
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
|
.small(),
|
||||||
|
)
|
||||||
|
.child(div().text_sm().truncate().text_ellipsis().child(name))
|
||||||
|
.into_any_element()
|
||||||
|
})),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.gap_2()
|
||||||
|
.child(sidebar_title("Labels", cx))
|
||||||
|
.map(|this| {
|
||||||
|
if labels.is_empty() {
|
||||||
|
this.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.text_color(cx.theme().muted_foreground)
|
||||||
|
.child("No labels"),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
this.child(h_flex().gap_1().children({
|
||||||
|
let mut items = vec![];
|
||||||
|
|
||||||
|
for label in labels.iter() {
|
||||||
|
items.push(
|
||||||
|
Tag::secondary()
|
||||||
|
.outline()
|
||||||
|
.xsmall()
|
||||||
|
.child(SharedString::from(label)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
items
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
fn render_comments(&mut self, id: &EventId, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render_comments(&mut self, id: &EventId, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
let store = self.store.read(cx);
|
let store = self.store.read(cx);
|
||||||
let comments: Vec<&Event> = store.comments_of(id).collect();
|
let comments: Vec<&Event> = store.comments_of(id).collect();
|
||||||
@@ -71,6 +155,7 @@ impl IssueDetailView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.xsmall(),
|
.xsmall(),
|
||||||
)
|
)
|
||||||
.child(author),
|
.child(author),
|
||||||
@@ -165,14 +250,16 @@ impl Focusable for IssueDetailView {
|
|||||||
|
|
||||||
impl Render for IssueDetailView {
|
impl Render for IssueDetailView {
|
||||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
// Extract everything owned first: the store borrow must end before
|
|
||||||
// the markdown state is (re)built below.
|
|
||||||
let (title, author, picture, status, age, issue_id, content) = {
|
|
||||||
let store = self.store.read(cx);
|
let store = self.store.read(cx);
|
||||||
|
|
||||||
let Some(issue) = store.issues.iter().find(|issue| issue.id == self.issue_id) else {
|
let Some(issue) = store.issues.iter().find(|issue| issue.id == self.issue_id) else {
|
||||||
return placeholder("Issue not found", cx);
|
return placeholder("Issue not found", cx);
|
||||||
};
|
};
|
||||||
let profile = ProfileStore::global(cx).read(cx).get(&issue.pubkey);
|
|
||||||
|
let (title, author, picture, status, age, issue_id, content) = {
|
||||||
|
let profile_store = ProfileStore::global(cx);
|
||||||
|
let profile = profile_store.read(cx).get(&issue.pubkey);
|
||||||
|
|
||||||
(
|
(
|
||||||
activity_subject(issue),
|
activity_subject(issue),
|
||||||
profile.name(),
|
profile.name(),
|
||||||
@@ -184,18 +271,30 @@ impl Render for IssueDetailView {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
v_flex()
|
h_flex()
|
||||||
.id("issue-detail")
|
.id("issue-detail")
|
||||||
.size_full()
|
.size_full()
|
||||||
.overflow_y_scroll()
|
.child(
|
||||||
.gap_6()
|
v_flex()
|
||||||
.px_4()
|
.px_4()
|
||||||
|
.pb_4()
|
||||||
|
.gap_6()
|
||||||
|
.size_full()
|
||||||
|
.min_w_0()
|
||||||
|
.overflow_y_scrollbar()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
.min_h_16()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.items_center()
|
|
||||||
.child(status_badge(status, cx))
|
.child(status_badge(status, cx))
|
||||||
.child(div().font_semibold().child(title)),
|
.child(
|
||||||
|
div()
|
||||||
|
.flex_1()
|
||||||
|
.min_w_0()
|
||||||
|
.font_semibold()
|
||||||
|
.line_height(relative(1.2))
|
||||||
|
.child(title),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -203,7 +302,7 @@ impl Render for IssueDetailView {
|
|||||||
.gap_8()
|
.gap_8()
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_4()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
@@ -213,8 +312,11 @@ impl Render for IssueDetailView {
|
|||||||
.gap_1()
|
.gap_1()
|
||||||
.child(
|
.child(
|
||||||
Avatar::new()
|
Avatar::new()
|
||||||
|
.when_some(picture, |this, url| {
|
||||||
|
this.src(url)
|
||||||
|
})
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(author),
|
.child(author),
|
||||||
@@ -234,7 +336,18 @@ impl Render for IssueDetailView {
|
|||||||
)
|
)
|
||||||
.child(self.render_comments(&issue_id, cx))
|
.child(self.render_comments(&issue_id, cx))
|
||||||
.child(self.render_form(&issue_id, cx)),
|
.child(self.render_form(&issue_id, cx)),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
.child(self.render_sidebar(cx))
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sidebar_title(text: &str, cx: &App) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(cx.theme().muted_foreground)
|
||||||
|
.child(text.to_string())
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ impl IssuesView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(div().child(author)),
|
.child(div().child(author)),
|
||||||
|
|||||||
@@ -149,7 +149,10 @@ impl RepoDetailView {
|
|||||||
// cache until the panel closes; free them then.
|
// cache until the panel closes; free them then.
|
||||||
crate::image_cache::clear_on_release(&cx.entity(), window, cx);
|
crate::image_cache::clear_on_release(&cx.entity(), window, cx);
|
||||||
|
|
||||||
let store = cx.new(|cx| RepoStore::new(initial.addr(), cx));
|
// The announcement we opened from already carries the repository's
|
||||||
|
// NIP-34 `relays` tag, so the store can connect to those relays
|
||||||
|
// immediately instead of waiting for the bootstrap fetch.
|
||||||
|
let store = cx.new(|cx| RepoStore::new(initial.addr(), initial.relays.clone(), cx));
|
||||||
let tree_state = cx.new(|cx| TreeState::new(cx));
|
let tree_state = cx.new(|cx| TreeState::new(cx));
|
||||||
|
|
||||||
// Empty until the clone completes; populated with the local refs.
|
// Empty until the clone completes; populated with the local refs.
|
||||||
@@ -1184,6 +1187,7 @@ impl RepoDetailView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(owner_name.clone())
|
.name(owner_name.clone())
|
||||||
.when_some(owner_picture, |this, url| this.src(url))
|
.when_some(owner_picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(div().text_xs().whitespace_nowrap().child(owner_name)),
|
.child(div().text_xs().whitespace_nowrap().child(owner_name)),
|
||||||
@@ -1195,6 +1199,7 @@ impl RepoDetailView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(profile.name())
|
.name(profile.name())
|
||||||
.when_some(profile.picture(), |this, url| this.src(url))
|
.when_some(profile.picture(), |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -555,6 +555,7 @@ impl PullRequestDetailView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(author),
|
.child(author),
|
||||||
@@ -684,6 +685,7 @@ impl PullRequestDetailView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.xsmall(),
|
.xsmall(),
|
||||||
)
|
)
|
||||||
.child(author),
|
.child(author),
|
||||||
|
|||||||
@@ -180,6 +180,7 @@ impl PullRequestsView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(author.clone())
|
.name(author.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(div().child(author)),
|
.child(div().child(author)),
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ impl RepoListView {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(owner.name())
|
.name(owner.name())
|
||||||
.when_some(owner.picture(), |this, url| this.src(url))
|
.when_some(owner.picture(), |this, url| this.src(url))
|
||||||
|
.rounded(cx.theme().radius)
|
||||||
.small(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ impl SidebarPanel {
|
|||||||
Avatar::new()
|
Avatar::new()
|
||||||
.name(name.clone())
|
.name(name.clone())
|
||||||
.when_some(picture, |this, url| this.src(url))
|
.when_some(picture, |this, url| this.src(url))
|
||||||
.small()
|
.rounded(cx.theme().radius)
|
||||||
.border_0(),
|
.small(),
|
||||||
)
|
)
|
||||||
.child(div().text_xs().font_semibold().child(name)),
|
.child(div().text_xs().font_semibold().child(name)),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user