3 Commits
Author SHA1 Message Date
reya 273ddabde5 clean up the sidebar 2026-09-23 14:54:34 +07:00
reya 7ba289440b refactor panel open flow 2026-09-23 08:53:20 +07:00
reya 6510e45e4e update deps 2026-09-23 08:21:37 +07:00
14 changed files with 829 additions and 1024 deletions
Generated
+194 -105
View File
@@ -987,9 +987,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.4.6" version = "1.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4" checksum = "54413ede23c2daf518f35156dfde027feb2374004d63bd497f983c8db9c0e313"
dependencies = [ dependencies = [
"find-msvc-tools", "find-msvc-tools",
"jobserver", "jobserver",
@@ -1339,7 +1339,7 @@ dependencies = [
"hmac 0.12.1", "hmac 0.12.1",
"nostr", "nostr",
"nostr-sdk", "nostr-sdk",
"rand 0.10.2", "rand 0.10.3",
"serde", "serde",
"serde_json", "serde_json",
"sha2 0.10.9", "sha2 0.10.9",
@@ -2190,9 +2190,9 @@ dependencies = [
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.12" version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" checksum = "ef25905e51abafe4dcea6c15fec58c57b601cdbd0ee53d22ea1d3016c587d39b"
[[package]] [[package]]
name = "fixedbitset" name = "fixedbitset"
@@ -2711,14 +2711,16 @@ dependencies = [
[[package]] [[package]]
name = "gpui-base" name = "gpui-base"
version = "0.6.1" version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d45dcaaeac889bf1e7757db1beb26c9043c8ea3156651facc11c6be56bb6722" checksum = "c9e904ee0d351f4e85b967e26ae986d3aa195a8d9d35fcd18184a2c40989694e"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"anyhow", "anyhow",
"ashpd",
"async-channel", "async-channel",
"chrono", "chrono",
"data-url",
"futures", "futures",
"gpui-pre", "gpui-pre",
"gpui-pre-macros", "gpui-pre-macros",
@@ -2742,13 +2744,14 @@ dependencies = [
"tracing", "tracing",
"unicode-segmentation", "unicode-segmentation",
"web-time", "web-time",
"windows 0.58.0",
] ]
[[package]] [[package]]
name = "gpui-pre" name = "gpui-pre"
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 = "2a9ca98fdcad06276de623c2f48ebd710f1e7724eebef2f2673c583e85dc8335" checksum = "a0437c0b83e636a92bd1a39fa1d05fb632ae671289537497b35871ffbe231b84"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"anyhow", "anyhow",
@@ -2774,7 +2777,6 @@ dependencies = [
"gpui-pre-sum-tree", "gpui-pre-sum-tree",
"gpui-pre-util", "gpui-pre-util",
"gpui-pre-util-macros", "gpui-pre-util-macros",
"gpui-pre-ztracing",
"heapless 0.9.3", "heapless 0.9.3",
"image", "image",
"inventory", "inventory",
@@ -2782,6 +2784,8 @@ dependencies = [
"log", "log",
"lyon", "lyon",
"num_cpus", "num_cpus",
"objc2-core-foundation",
"objc2-core-video",
"parking", "parking",
"parking_lot", "parking_lot",
"pin-project", "pin-project",
@@ -2802,7 +2806,6 @@ dependencies = [
"strum", "strum",
"taffy", "taffy",
"thiserror 2.0.20", "thiserror 2.0.20",
"tracing",
"ttf-parser", "ttf-parser",
"url", "url",
"usvg", "usvg",
@@ -2816,9 +2819,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-apple" name = "gpui-pre-apple"
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 = "d3fc4da82c5c2dbb25443655cfbc4305a2e2d1380bc0b815e80664fdfbf4cfdb" checksum = "3af534f0746eb9e014114bcc0ee00dc250c4b8d75df2e437180c403aa65649c1"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"block", "block",
@@ -2830,7 +2833,6 @@ dependencies = [
"etagere", "etagere",
"foreign-types", "foreign-types",
"gpui-pre", "gpui-pre",
"gpui-pre-collections",
"image", "image",
"log", "log",
"metal", "metal",
@@ -2841,9 +2843,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-collections" name = "gpui-pre-collections"
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 = "626a09f683ff6f3b2f708341bdcea9d479af5b14a6a2fccec9cff935ec0751b7" checksum = "15e7a65204039187d1f4b3d4c2e0233eeac54d4acb0b13f9dc1a3b5adad26c1f"
dependencies = [ dependencies = [
"gpui-pre-util", "gpui-pre-util",
"indexmap", "indexmap",
@@ -2852,9 +2854,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-derive-refineable" name = "gpui-pre-derive-refineable"
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 = "56d06116a2b857588f6ea7bfb447b3554ba985e780b5995ae47780252da152f3" checksum = "79dfb4a05f3cd9893d7768dbf5dba1bbbe99cab7394e89b360ccb3b2bcb6b34e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2863,9 +2865,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-http-client" name = "gpui-pre-http-client"
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 = "b0d2071c582c1a0f71b8c7c00607a3b9cd18f81fb3510d41845db3447b2a11c9" checksum = "cfd5a7542c77887a5aff997d78c95884119c8463409569b63fcf060956da1682"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-compression", "async-compression",
@@ -2884,9 +2886,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-http-client-tls" name = "gpui-pre-http-client-tls"
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 = "6b6f3936802580259d5af9bcb2ab37fb0d7002caeed449eaabb007c62aea7341" checksum = "72aed510adb5e7723f8f57b9751007e3451d46a84edb59b92227178cf59cc19c"
dependencies = [ dependencies = [
"log", "log",
"rustls", "rustls",
@@ -2896,9 +2898,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-linux" name = "gpui-pre-linux"
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 = "f6b427589681ec1fed27951fd82edc70a7e288bb2487ede26dbbd07c2ce23d4f" checksum = "aab655cda1d6dcd549ac869e8678babc84cf573ab6794a1fe1a39c6c70c60b48"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_unix", "accesskit_unix",
@@ -2943,15 +2945,14 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-macos" name = "gpui-pre-macos"
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 = "806eac0cb5c0eebc0b032c6450c11d283264f9ac05754dda83fc80d0b86b4ee8" checksum = "951d17e41a72067ad2d35c60e08a62e8ad7fa9400b41c802e26cfb459f6c05da"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_macos", "accesskit_macos",
"anyhow", "anyhow",
"async-task", "async-task",
"block",
"block2 0.6.2", "block2 0.6.2",
"cocoa 0.26.1", "cocoa 0.26.1",
"core-foundation 0.10.1", "core-foundation 0.10.1",
@@ -2965,17 +2966,17 @@ dependencies = [
"gpui-pre", "gpui-pre",
"gpui-pre-apple", "gpui-pre-apple",
"gpui-pre-collections", "gpui-pre-collections",
"gpui-pre-media",
"gpui-pre-util", "gpui-pre-util",
"image", "image",
"itertools 0.14.0", "itertools 0.14.0",
"libc", "libc",
"log", "log",
"mach2", "mach2",
"metal",
"objc", "objc",
"objc2 0.6.4", "objc2 0.6.4",
"objc2-app-kit 0.3.2", "objc2-app-kit 0.3.2",
"objc2-core-graphics",
"objc2-core-media",
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
"objc2-screen-capture-kit", "objc2-screen-capture-kit",
"objc2-user-notifications", "objc2-user-notifications",
@@ -2991,9 +2992,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-macros" name = "gpui-pre-macros"
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 = "c06139051bf1db51949bfbb4ee338208bd64b4c35340d8c1a6a8200744e28fe1" checksum = "6324092b40ea8ec7c327a4a28427e366a489b4d5d23b5d1bd0243fc2f4ca7a9e"
dependencies = [ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro-crate", "proc-macro-crate",
@@ -3002,26 +3003,11 @@ dependencies = [
"syn 2.0.119", "syn 2.0.119",
] ]
[[package]]
name = "gpui-pre-media"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500acb13f818ff234021c1b9eae8592b0cbe017a64e26908c736b7421b1c6213"
dependencies = [
"anyhow",
"bindgen",
"core-foundation 0.10.1",
"core-video",
"foreign-types",
"metal",
"objc",
]
[[package]] [[package]]
name = "gpui-pre-perf" name = "gpui-pre-perf"
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 = "b0973bbb02bf46940ac0861d9dce0fc03a3109634172b69108d1bc13fa29d76c" checksum = "b94bff26ccd8105f6206144f8dab16a2dc02e7a68f39dada02cdf492f0afd940"
dependencies = [ dependencies = [
"gpui-pre-collections", "gpui-pre-collections",
"serde", "serde",
@@ -3030,9 +3016,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-platform" name = "gpui-pre-platform"
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 = "b613512e29f1e7b825bfa7e50a447388ff1347044350a475e4c98a892a985c8d" checksum = "8423d1e0a693d2f9f16c0326bb01b5e81ec0531854d596a18476934ac6880478"
dependencies = [ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"gpui-pre", "gpui-pre",
@@ -3044,9 +3030,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-refineable" name = "gpui-pre-refineable"
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 = "428f23703ead5601618ffea73c137897b98a94ce8d30e257f22be947732dfbf9" checksum = "93b4b0a8d296a3ee5beb1136bc48f8167a6028eb1e243b56851dcd8c9fc6d7a1"
dependencies = [ dependencies = [
"gpui-pre-derive-refineable", "gpui-pre-derive-refineable",
] ]
@@ -3103,9 +3089,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-reqwest-client" name = "gpui-pre-reqwest-client"
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 = "d05d4e3d2eb2ab777597879e46047247447b9d93cef568e63d545c9deb1b3e57" checksum = "8f32ccea5d1a7c8d2868d7b346c2c1f76aa3f86ec9e0575c4e7340af3afd9e9d"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -3121,9 +3107,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-scheduler" name = "gpui-pre-scheduler"
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 = "6dd1b7ff2e7bf43302ae982cd786a22c16c52e16682e67b66cfbe2cb2bc3a72d" checksum = "ff7b10b3d2fc3fda24847a04436eca9531612c8414874a37ddc005f20e521e12"
dependencies = [ dependencies = [
"async-task", "async-task",
"backtrace", "backtrace",
@@ -3138,9 +3124,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-shared-string" name = "gpui-pre-shared-string"
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 = "424a4dd6a570473d57acf1df2bfb9f3028d4b568abcaeb9252e0f13047b50c03" checksum = "fe17f81bd98a0253140ea79f7f76442d7499bd8d17db302861af8e46c11d38df"
dependencies = [ dependencies = [
"schemars", "schemars",
"serde", "serde",
@@ -3149,9 +3135,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-sum-tree" name = "gpui-pre-sum-tree"
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 = "4855718e82630d29198b515d2b027361ef63dd19b6021cefe945789dcff82372" checksum = "0a6d35e998a51d24248dad731de1f09d386cbbf46a04edde3b67f469b2ce3f16"
dependencies = [ dependencies = [
"gpui-pre-ztracing", "gpui-pre-ztracing",
"heapless 0.9.3", "heapless 0.9.3",
@@ -3162,9 +3148,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-util" name = "gpui-pre-util"
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 = "e973148165346c0f9b3f5072b321d7c2f33807c93daea67fe298c005c0e0c2a8" checksum = "6a026a30c578930d20974fd8c3d77de36223ac7ba193bd4259e7238929bc8806"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"log", "log",
@@ -3173,9 +3159,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-util-macros" name = "gpui-pre-util-macros"
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 = "4f71f6212d3772a70988c7d64627c7284dec73c17992ac4f9f0cdfdd46cbb677" checksum = "5cbf79627a6afc626d4e887dad9d2d92bb069413e8cc692ba3e90bff219eb7a9"
dependencies = [ dependencies = [
"gpui-pre-perf", "gpui-pre-perf",
"quote", "quote",
@@ -3184,9 +3170,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-web" name = "gpui-pre-web"
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 = "4f0daada903f106be946d87e25f5bc85ad6cf60d6d82cb8f8aed945417a9c1a3" checksum = "34be433b9fcb370b1fe9a1c7fe911f0eb6058791ef8167dcf6c5a5deb624975c"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"console_error_panic_hook", "console_error_panic_hook",
@@ -3213,9 +3199,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-wgpu" name = "gpui-pre-wgpu"
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 = "640b666a16ddf9504e2eb3e7a997acb2b2adfaa7859925bdd36fc3acfd8f30a7" checksum = "05515b32799b1767d69300921c1b562cd53104965211a0e8905acdc7aa18e693"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytemuck", "bytemuck",
@@ -3240,9 +3226,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-windows" name = "gpui-pre-windows"
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 = "c12c7d84ec422feb2f064117d572447998381e5c219fcad69fe19f10d0b7aaea" checksum = "27662e65bfcf4445d2cccfad91f1570ec07f4b1b5de98400a9f207fd19c464cf"
dependencies = [ dependencies = [
"accesskit", "accesskit",
"accesskit_windows", "accesskit_windows",
@@ -3269,9 +3255,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-zlog" name = "gpui-pre-zlog"
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 = "98352858fac3d4d05b46d6014ad04bad313652a691d4e21dc55fa96fb4acb7cf" checksum = "f3a5af0b734a391a84872eb770b3ee9830091ec2487b79d06371fe14eefb2b5d"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@@ -3281,9 +3267,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-ztracing" name = "gpui-pre-ztracing"
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 = "5d63a3c7276875b4d7e6d3961e92a138e9233e86a591bf318f2e54df4ad58102" checksum = "a24cb19f78c5bc3aab8ddf1e8e0bd6b402fbcb9c7f112f64ddbedef8f8768a59"
dependencies = [ dependencies = [
"gpui-pre-zlog", "gpui-pre-zlog",
"gpui-pre-ztracing-macro", "gpui-pre-ztracing-macro",
@@ -3293,9 +3279,9 @@ dependencies = [
[[package]] [[package]]
name = "gpui-pre-ztracing-macro" name = "gpui-pre-ztracing-macro"
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 = "84e2a5ff79002223edfcfa76c6f9f79f4f60f6ec545ccc27832f12bd46348b39" checksum = "a1bb25850ad31b88bbdef454afb93ec4cdb81f5e200ba5b3f1a0368111780d2c"
[[package]] [[package]]
name = "gpui-updater-core" name = "gpui-updater-core"
@@ -3621,9 +3607,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.27.9" version = "0.27.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" checksum = "dfa8e654703247911e29c23fbeaa261834bd9bb74efba2f9acddc37bfb127f53"
dependencies = [ dependencies = [
"http", "http",
"hyper", "hyper",
@@ -4131,9 +4117,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.24" version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6480ccc157a1389bb2e4891b24751b0f798ba640d22386f23143fbcc89da195a" checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d"
dependencies = [ dependencies = [
"libc", "libc",
] ]
@@ -4617,8 +4603,8 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]] [[package]]
name = "nostr" name = "nostr"
version = "0.45.4" version = "0.45.5"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"aes", "aes",
"base64 0.22.1", "base64 0.22.1",
@@ -4630,7 +4616,7 @@ dependencies = [
"chacha20poly1305", "chacha20poly1305",
"faster-hex", "faster-hex",
"opaquerr 0.2.0", "opaquerr 0.2.0",
"rand 0.10.2", "rand 0.10.3",
"scrypt", "scrypt",
"secp256k1", "secp256k1",
"serde", "serde",
@@ -4643,8 +4629,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-blossom" name = "nostr-blossom"
version = "0.45.0" version = "0.45.1"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bitcoin_hashes 1.2.0", "bitcoin_hashes 1.2.0",
@@ -4656,8 +4642,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-connect" name = "nostr-connect"
version = "0.45.1" version = "0.45.2"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"futures-core", "futures-core",
@@ -4670,8 +4656,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-database" name = "nostr-database"
version = "0.45.1" version = "0.45.2"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"nostr", "nostr",
"opaquerr 0.2.0", "opaquerr 0.2.0",
@@ -4679,8 +4665,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-gossip" name = "nostr-gossip"
version = "0.45.0" version = "0.45.1"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"nostr", "nostr",
"opaquerr 0.2.0", "opaquerr 0.2.0",
@@ -4688,8 +4674,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-gossip-memory" name = "nostr-gossip-memory"
version = "0.45.0" version = "0.45.1"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"lru", "lru",
@@ -4700,8 +4686,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-lmdb" name = "nostr-lmdb"
version = "0.45.2" version = "0.45.3"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"flatbuffers", "flatbuffers",
@@ -4715,8 +4701,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-memory" name = "nostr-memory"
version = "0.45.1" version = "0.45.2"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"btreecap", "btreecap",
"nostr", "nostr",
@@ -4726,8 +4712,8 @@ dependencies = [
[[package]] [[package]]
name = "nostr-sdk" name = "nostr-sdk"
version = "0.45.2" version = "0.45.4"
source = "git+https://github.com/rust-nostr/nostr#b230cecf9dbb38e0228e6fff4544ed9d261326fc" source = "git+https://github.com/rust-nostr/nostr#01f1950c671b35f3d1186ca907373dd86ee3b336"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"async-wsocket", "async-wsocket",
@@ -4739,7 +4725,7 @@ dependencies = [
"nostr-database", "nostr-database",
"nostr-gossip", "nostr-gossip",
"opaquerr 0.2.0", "opaquerr 0.2.0",
"rand 0.10.2", "rand 0.10.3",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tracing", "tracing",
@@ -4990,6 +4976,28 @@ dependencies = [
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
] ]
[[package]]
name = "objc2-core-audio"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1eebcea8b0dbff5f7c8504f3107c68fc061a3eb44932051c8cf8a68d969c3b2"
dependencies = [
"dispatch2",
"objc2 0.6.4",
"objc2-core-audio-types",
"objc2-core-foundation",
]
[[package]]
name = "objc2-core-audio-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a89f2ec274a0cf4a32642b2991e8b351a404d290da87bb6a9a9d8632490bd1c"
dependencies = [
"bitflags 2.13.2",
"objc2 0.6.4",
]
[[package]] [[package]]
name = "objc2-core-data" name = "objc2-core-data"
version = "0.2.2" version = "0.2.2"
@@ -5069,6 +5077,21 @@ dependencies = [
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
] ]
[[package]]
name = "objc2-core-media"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05ec576860167a15dd9fce7fbee7512beb4e31f532159d3482d1f9c6caedf31d"
dependencies = [
"bitflags 2.13.2",
"dispatch2",
"objc2 0.6.4",
"objc2-core-audio",
"objc2-core-audio-types",
"objc2-core-foundation",
"objc2-core-video",
]
[[package]] [[package]]
name = "objc2-core-text" name = "objc2-core-text"
version = "0.3.2" version = "0.3.2"
@@ -5193,8 +5216,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74b7c5390f477482f001bc354d6571a70db7e4f8d5288e860c45521fbce11394" checksum = "74b7c5390f477482f001bc354d6571a70db7e4f8d5288e860c45521fbce11394"
dependencies = [ dependencies = [
"block2 0.6.2", "block2 0.6.2",
"dispatch2",
"objc2 0.6.4", "objc2 0.6.4",
"objc2-core-graphics", "objc2-core-graphics",
"objc2-core-media",
"objc2-foundation 0.3.2", "objc2-foundation 0.3.2",
] ]
@@ -5902,7 +5927,7 @@ dependencies = [
"bytes", "bytes",
"getrandom 0.4.3", "getrandom 0.4.3",
"lru-slab", "lru-slab",
"rand 0.10.2", "rand 0.10.3",
"rand_pcg", "rand_pcg",
"ring", "ring",
"rustc-hash 2.1.3", "rustc-hash 2.1.3",
@@ -5973,9 +5998,9 @@ dependencies = [
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.10.2" version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af"
dependencies = [ dependencies = [
"chacha20 0.10.2", "chacha20 0.10.2",
"getrandom 0.4.3", "getrandom 0.4.3",
@@ -8004,9 +8029,9 @@ checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e"
[[package]] [[package]]
name = "unicode-id" name = "unicode-id"
version = "0.3.6" version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ba288e709927c043cbe476718d37be306be53fb1fafecd0dbe36d072be2580" checksum = "65dd75ab2d9d379dbe86d4059e91d8b5a6e7054865eaba1ddbfc7a817ff96392"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
@@ -8790,6 +8815,16 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
"windows-core 0.58.0",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows" name = "windows"
version = "0.61.3" version = "0.61.3"
@@ -8858,6 +8893,19 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-core"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
"windows-implement 0.58.0",
"windows-interface 0.58.0",
"windows-result 0.2.0",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.61.2" version = "0.61.2"
@@ -8917,6 +8965,17 @@ dependencies = [
"syn 2.0.119", "syn 2.0.119",
] ]
[[package]]
name = "windows-implement"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]] [[package]]
name = "windows-implement" name = "windows-implement"
version = "0.60.2" version = "0.60.2"
@@ -8939,6 +8998,17 @@ dependencies = [
"syn 2.0.119", "syn 2.0.119",
] ]
[[package]]
name = "windows-interface"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]] [[package]]
name = "windows-interface" name = "windows-interface"
version = "0.59.3" version = "0.59.3"
@@ -9013,6 +9083,15 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-result" name = "windows-result"
version = "0.3.4" version = "0.3.4"
@@ -9031,6 +9110,16 @@ dependencies = [
"windows-link 0.2.1", "windows-link 0.2.1",
] ]
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
"windows-result 0.2.0",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-strings" name = "windows-strings"
version = "0.3.1" version = "0.3.1"
+3
View File
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none">
<path d="M2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M15.25 13L12 16.25L8.75 13" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 7.75V15.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 571 B

+5 -30
View File
@@ -9,7 +9,7 @@ use fuzzy_matcher::FuzzyMatcher;
use fuzzy_matcher::skim::SkimMatcherV2; use fuzzy_matcher::skim::SkimMatcherV2;
use gpui::{ use gpui::{
App, AppContext, Context, Entity, EventEmitter, Global, SharedString, Subscription, Task, App, AppContext, Context, Entity, EventEmitter, Global, SharedString, Subscription, Task,
WeakEntity, Window, WeakEntity,
}; };
use instant::Duration; use instant::Duration;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
@@ -37,15 +37,8 @@ impl Global for GlobalChatRegistry {}
/// Chat event. /// Chat event.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum ChatEvent { pub enum ChatEvent {
/// An event to open a room by its ID
OpenRoom(u64),
/// An event to close a room by its ID
CloseRoom(u64),
/// An event to notify UI about a new chat request
Ping, Ping,
/// No Inbox Relays found, the app is not ready to subscribe messages
InboxRelayNotFound, InboxRelayNotFound,
/// An error occurred
Error(String), Error(String),
} }
@@ -543,34 +536,16 @@ impl ChatRegistry {
cx.notify(); cx.notify();
} }
/// Emit an open room event. /// Track a room so it is listed and can be looked up by id.
/// pub fn track_room(&mut self, room: &Entity<Room>, cx: &mut Context<Self>) {
/// If the room is new, add it to the registry.
pub fn emit_room(&mut self, room: &Entity<Room>, window: &mut Window, cx: &mut Context<Self>) {
// Get the room's ID.
let id = room.read(cx).id; let id = room.read(cx).id;
// If the room is new, add it to the registry and index.
if let hash_map::Entry::Vacant(e) = self.room_index.entry(id) { if let hash_map::Entry::Vacant(e) = self.room_index.entry(id) {
let entity = room.to_owned(); let entity = room.to_owned();
e.insert(entity.clone()); e.insert(entity.clone());
self.rooms.insert(0, entity); self.rooms.insert(0, entity);
} cx.notify();
// Emit the open room event deferred to avoid re-entrant reads
cx.defer_in(window, move |_this, _window, cx| {
cx.emit(ChatEvent::OpenRoom(id));
});
}
/// Close a room.
pub fn close_room(&mut self, id: u64, window: &mut Window, cx: &mut Context<Self>) {
if self.room_index.contains_key(&id) {
self.room_index.remove(&id);
self.rooms.retain(|r| r.read(cx).id != id);
cx.defer_in(window, move |_this, _window, cx| {
cx.emit(ChatEvent::CloseRoom(id));
});
} }
} }
-2
View File
@@ -107,8 +107,6 @@ impl SubscriptionKey {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum CommunityEvent { pub enum CommunityEvent {
Updated(CommunityId), Updated(CommunityId),
Open(CommunityId),
Close(CommunityId),
Channel(CommunityId, ChannelId), Channel(CommunityId, ChannelId),
/// History exists here that no held key can open. /// History exists here that no held key can open.
Unreadable(CommunityId), Unreadable(CommunityId),
+1 -22
View File
@@ -7,7 +7,7 @@ pub use concord::cord03::{ChatMessage, ReplyRef};
use concord::state::CommunityState; use concord::state::CommunityState;
pub use concord::{ChannelId, CommunityId, Epoch}; pub use concord::{ChannelId, CommunityId, Epoch};
use futures::future::{Either, select}; use futures::future::{Either, select};
use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Subscription, Task, Window}; use gpui::{App, AppContext, Context, Entity, EventEmitter, Global, Subscription, Task};
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use state::NostrRegistry; use state::NostrRegistry;
@@ -225,27 +225,6 @@ impl CommunityRegistry {
self.index.get(id).cloned() self.index.get(id).cloned()
} }
/// Ask the workspace to open a community's panel.
pub fn emit_community(
&mut self,
community: &Entity<Community>,
window: &mut Window,
cx: &mut Context<Self>,
) {
let id = community.read(cx).id();
cx.defer_in(window, move |_this, _window, cx| {
cx.emit(CommunityEvent::Open(id));
});
}
/// Ask the workspace to close a community's panel.
pub fn emit_close(&mut self, id: CommunityId, window: &mut Window, cx: &mut Context<Self>) {
cx.defer_in(window, move |_this, _window, cx| {
cx.emit(CommunityEvent::Close(id));
});
}
/// Create a community owned by the current account and begin tracking it. /// Create a community owned by the current account and begin tracking it.
pub fn create(&mut self, metadata: CommunityMetadata, cx: &mut Context<Self>) { pub fn create(&mut self, metadata: CommunityMetadata, cx: &mut Context<Self>) {
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
+9 -11
View File
@@ -145,21 +145,19 @@ impl CommunityPanel {
window, window,
|_this, _community, event, window, cx| { |_this, _community, event, window, cx| {
match event { match event {
CommunityEvent::Updated(_)
| CommunityEvent::Unreadable(_)
| CommunityEvent::Failed(_) => {
cx.defer_in(window, |this, window, cx| this.reload(window, cx));
}
CommunityEvent::Channel(..) => { CommunityEvent::Channel(..) => {
cx.defer_in(window, |this, window, cx| this.load(window, cx)); cx.defer_in(window, |this, window, cx| {
this.load(window, cx);
});
} }
CommunityEvent::Error(error) => { CommunityEvent::Error(error) => {
window.push_notification( window.push_notification(Notification::error(error.clone()), cx);
Notification::error(error.clone()).autohide(false), }
cx, _ => {
); cx.defer_in(window, |this, window, cx| {
this.reload(window, cx);
});
} }
CommunityEvent::Open(_) | CommunityEvent::Close(_) => {}
}; };
}, },
)); ));
+14 -15
View File
@@ -14,7 +14,7 @@ use gpui::{
pub use gpui_base::dock::{DockArea, DockLayout, DockPlacement}; pub use gpui_base::dock::{DockArea, DockLayout, DockPlacement};
use gpui_base::dock::{ use gpui_base::dock::{
DockAreaRenderer, DockContext, DragPanel, DropIndicator, InsertTarget, NodeId, PaneNode, DockAreaRenderer, DockContext, DragPanel, DropIndicator, InsertTarget, NodeId, PaneNode,
PaneRef, PanelId, TabGroupContext, TabGroupRenderer, TileContext, TilesRenderer, PaneRef, PanelId, TabGroupContext, TabGroupRenderer,
}; };
use gpui_base::{Placement, ResizeHandleContext, Side}; use gpui_base::{Placement, ResizeHandleContext, Side};
use theme::{ActiveTheme, TABBAR_HEIGHT}; use theme::{ActiveTheme, TABBAR_HEIGHT};
@@ -95,6 +95,19 @@ pub fn add_panel(
area.add_panel_view(Arc::new(panel), placement, None, window, cx); area.add_panel_view(Arc::new(panel), placement, None, window, cx);
} }
/// Add a panel to a dock reached through a weak handle.
pub fn add_panel_to(
dock: &WeakEntity<DockArea>,
panel: PanelHandle,
placement: DockPlacement,
window: &mut Window,
cx: &mut App,
) {
let _ = dock.update(cx, |area, cx| {
add_panel(area, panel, placement, window, cx);
});
}
/// The panel in any region of `area` whose logical id is `key`. /// The panel in any region of `area` whose logical id is `key`.
fn find_panel(area: &DockArea, key: &SharedString, cx: &App) -> Option<(PanelId, NodeId, usize)> { fn find_panel(area: &DockArea, key: &SharedString, cx: &App) -> Option<(PanelId, NodeId, usize)> {
let placements = [ let placements = [
@@ -167,7 +180,6 @@ fn left_top_group(node: &PaneNode) -> Option<NodeId> {
match node.kind() { match node.kind() {
PaneRef::Tabs { .. } => Some(node.id()), PaneRef::Tabs { .. } => Some(node.id()),
PaneRef::Split { children, .. } => children.first().and_then(left_top_group), PaneRef::Split { children, .. } => children.first().and_then(left_top_group),
PaneRef::Tiles { .. } => None,
} }
} }
@@ -182,7 +194,6 @@ fn right_top_group(node: &PaneNode) -> Option<NodeId> {
}; };
child.and_then(right_top_group) child.and_then(right_top_group)
} }
PaneRef::Tiles { .. } => None,
} }
} }
@@ -263,18 +274,6 @@ impl DockAreaRenderer for DockSkin {
fn tab_group_renderer(&self) -> Rc<dyn TabGroupRenderer> { fn tab_group_renderer(&self) -> Rc<dyn TabGroupRenderer> {
Rc::new(TabGroupSkin::new(self.shared.clone())) Rc::new(TabGroupSkin::new(self.shared.clone()))
} }
fn tiles_renderer(&self) -> Rc<dyn TilesRenderer> {
Rc::new(NoTiles)
}
}
struct NoTiles;
impl TilesRenderer for NoTiles {
fn render_drag_bar(&self, _: &TileContext, _: &mut Window, _: &mut App) -> AnyElement {
Empty.into_any_element()
}
} }
/// The payload a dock's resize handle drags; the handle is the affordance. /// The payload a dock's resize handle drags; the handle is the affordance.
-3
View File
@@ -19,9 +19,6 @@ pub enum PanelEvent {
pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable { pub trait Panel: EventEmitter<PanelEvent> + Render + Focusable {
/// The name of the panel used to serialize, deserialize and identify the panel. /// The name of the panel used to serialize, deserialize and identify the panel.
///
/// This is used to identify the panel when deserializing the panel.
/// Once you have defined a panel id, this must not be changed.
fn panel_id(&self) -> SharedString; fn panel_id(&self) -> SharedString;
/// The title of the panel /// The title of the panel
+2
View File
@@ -22,6 +22,7 @@ impl<T: IconNamed> From<T> for Icon {
pub enum IconName { pub enum IconName {
ArrowLeft, ArrowLeft,
ArrowRight, ArrowRight,
ArrowDownCircle,
Boom, Boom,
Book, Book,
ChevronDown, ChevronDown,
@@ -99,6 +100,7 @@ impl IconNamed for IconName {
match self { match self {
Self::ArrowLeft => "icons/arrow-left.svg", Self::ArrowLeft => "icons/arrow-left.svg",
Self::ArrowRight => "icons/arrow-right.svg", Self::ArrowRight => "icons/arrow-right.svg",
Self::ArrowDownCircle => "icons/arrow-down-circle.svg",
Self::Boom => "icons/boom.svg", Self::Boom => "icons/boom.svg",
Self::Book => "icons/book.svg", Self::Book => "icons/book.svg",
Self::ChevronDown => "icons/chevron-down.svg", Self::ChevronDown => "icons/chevron-down.svg",
+22 -7
View File
@@ -2,17 +2,18 @@ use chat::{ChatRegistry, Room, RoomKind};
use gpui::prelude::FluentBuilder; use gpui::prelude::FluentBuilder;
use gpui::{ use gpui::{
App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled, App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
Subscription, Window, div, px, Subscription, WeakEntity, Window, div, px,
}; };
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use state::NostrRegistry; use state::NostrRegistry;
use theme::ActiveTheme; use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants}; use ui::button::{Button, ButtonVariants};
use ui::dock::{DockArea, DockPlacement, PanelHandle};
use ui::input::{Input, InputEvent, InputState}; use ui::input::{Input, InputEvent, InputState};
use ui::{StyledExt, WindowExtension, v_flex}; use ui::{StyledExt, WindowExtension, v_flex};
pub fn open(window: &mut Window, cx: &mut App) { pub fn open(dock: WeakEntity<DockArea>, window: &mut Window, cx: &mut App) {
let view = cx.new(|cx| NewChat::new(window, cx)); let view = cx.new(|cx| NewChat::new(dock, window, cx));
window.open_modal(cx, move |this, _window, _cx| { window.open_modal(cx, move |this, _window, _cx| {
this.width(px(420.)).title("New chat").child(view.clone()) this.width(px(420.)).title("New chat").child(view.clone())
@@ -20,6 +21,9 @@ pub fn open(window: &mut Window, cx: &mut App) {
} }
pub struct NewChat { pub struct NewChat {
/// The dock a started chat opens in
dock: WeakEntity<DockArea>,
/// Public key input /// Public key input
input: Entity<InputState>, input: Entity<InputState>,
@@ -31,7 +35,7 @@ pub struct NewChat {
} }
impl NewChat { impl NewChat {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(dock: WeakEntity<DockArea>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let input = cx.new(|cx| InputState::new(window, cx).placeholder("npub")); let input = cx.new(|cx| InputState::new(window, cx).placeholder("npub"));
let subscription = cx.subscribe_in(&input, window, |this, _input, event, window, cx| { let subscription = cx.subscribe_in(&input, window, |this, _input, event, window, cx| {
@@ -41,6 +45,7 @@ impl NewChat {
}); });
Self { Self {
dock,
input, input,
error: None, error: None,
_subscription: Some(subscription), _subscription: Some(subscription),
@@ -56,6 +61,8 @@ impl NewChat {
}; };
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
let chat = ChatRegistry::global(cx);
let Some(current_user) = nostr.read(cx).current_user() else { let Some(current_user) = nostr.read(cx).current_user() else {
self.set_error("You are not signed in", cx); self.set_error("You are not signed in", cx);
return; return;
@@ -70,12 +77,20 @@ impl NewChat {
.organize(&current_user) .organize(&current_user)
.kind(RoomKind::Ongoing); .kind(RoomKind::Ongoing);
let chat = ChatRegistry::global(cx); let room = chat.update(cx, |chat, cx| {
chat.update(cx, |chat, cx| {
let room = cx.new(|_| room); let room = cx.new(|_| room);
chat.emit_room(&room, window, cx); chat.track_room(&room, cx);
room
}); });
ui::dock::add_panel_to(
&self.dock,
PanelHandle::new(chat_ui::init(room.downgrade(), window, cx)),
DockPlacement::Center,
window,
cx,
);
window.close_modal(cx); window.close_modal(cx);
} }
+18 -268
View File
@@ -1,4 +1,3 @@
use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use ::settings::AppSettings; use ::settings::AppSettings;
@@ -6,25 +5,20 @@ use anyhow::Error;
use auto_update::AutoUpdater; use auto_update::AutoUpdater;
use chat::{ChatEvent, ChatRegistry}; use chat::{ChatEvent, ChatRegistry};
use common::download_dir; use common::download_dir;
use community::{CommunityEvent, CommunityRegistry};
use community_ui::CommunityPanel;
use device::{DeviceEvent, DeviceRegistry}; use device::{DeviceEvent, DeviceRegistry};
use gpui::prelude::FluentBuilder;
use gpui::{ use gpui::{
Action, AnyElement, App, AppContext, Context, Entity, InteractiveElement, IntoElement, Action, App, AppContext, Context, Entity, InteractiveElement, IntoElement, ParentElement,
ParentElement, Render, SharedString, Styled, Subscription, Task, WeakEntity, Window, div, px, Render, SharedString, Styled, Subscription, Task, Window, div, px,
}; };
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
use person::{PersonRegistry, shorten_pubkey};
use serde::Deserialize; use serde::Deserialize;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};
use state::{NostrRegistry, StateEvent}; use state::{NostrRegistry, StateEvent};
use theme::{ActiveTheme, SIDEBAR_WIDTH, Theme, ThemeRegistry}; use theme::{ActiveTheme, SIDEBAR_WIDTH, Theme, ThemeRegistry};
use ui::button::{Button, ButtonVariants}; use ui::button::{Button, ButtonVariants};
use ui::dock::{self, ClosePanel, DockArea, DockLayout, DockPlacement, Panel, PanelHandle}; use ui::dock::{self, DockArea, DockLayout, DockPlacement, Panel, PanelHandle};
use ui::menu::{DropdownMenu, PopupMenuItem};
use ui::notification::{Notification, NotificationKind}; use ui::notification::{Notification, NotificationKind};
use ui::{Icon, IconName, Root, Sizable, WindowExtension, h_flex, v_flex}; use ui::{IconName, Root, Sizable, WindowExtension, h_flex, v_flex};
use crate::dialogs::restore::RestoreEncryption; use crate::dialogs::restore::RestoreEncryption;
use crate::dialogs::{new_chat, new_community, settings}; use crate::dialogs::{new_chat, new_community, settings};
@@ -71,9 +65,6 @@ enum Command {
pub struct Workspace { pub struct Workspace {
dock: Entity<DockArea>, dock: Entity<DockArea>,
title_bar_chrome: Rc<dock::TitleBarChrome>,
/// The community panel currently docked, if any
community_panel: Option<WeakEntity<CommunityPanel>>,
/// Async tasks /// Async tasks
tasks: Vec<Task<Result<(), Error>>>, tasks: Vec<Task<Result<(), Error>>>,
/// Event subscriptions /// Event subscriptions
@@ -83,12 +74,11 @@ pub struct Workspace {
impl Workspace { impl Workspace {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let chat = ChatRegistry::global(cx); let chat = ChatRegistry::global(cx);
let communities = CommunityRegistry::global(cx);
let device = DeviceRegistry::global(cx); let device = DeviceRegistry::global(cx);
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
let sidebar = cx.new(|cx| Sidebar::new(window, cx)); let (dock, _) = dock::dock_area("coop", window, cx);
let (dock, title_bar_chrome) = dock::dock_area("coop", window, cx); let sidebar = cx.new(|cx| Sidebar::new(window, dock.downgrade(), cx));
let mut subscriptions = smallvec![]; let mut subscriptions = smallvec![];
@@ -164,7 +154,7 @@ impl Workspace {
subscriptions.push( subscriptions.push(
// Observe all events emitted by the chat registry // Observe all events emitted by the chat registry
cx.subscribe_in(&chat, window, move |this, chat, ev, window, cx| { cx.subscribe_in(&chat, window, move |_this, _chat, ev, window, cx| {
match ev { match ev {
ChatEvent::InboxRelayNotFound => { ChatEvent::InboxRelayNotFound => {
const MSG: &str = "Messaging Relays not found. Cannot receive messages."; const MSG: &str = "Messaging Relays not found. Cannot receive messages.";
@@ -187,28 +177,6 @@ impl Workspace {
cx, cx,
); );
} }
ChatEvent::OpenRoom(id) => {
if let Some(room) = chat.read(cx).room(id, cx) {
this.add_panel_to_dock(
chat_ui::init(room, window, cx),
DockPlacement::Center,
window,
cx,
);
}
}
ChatEvent::CloseRoom(..) => {
this.dock.update(cx, |area, cx| {
// Force focus to the tab panel
ui::dock::focus_tab_panel(area, window, cx);
// Dispatch the close panel action
cx.defer_in(window, |_, window, cx| {
window.dispatch_action(Box::new(ClosePanel), cx);
window.close_all_modals(cx);
});
});
}
ChatEvent::Error(error) => { ChatEvent::Error(error) => {
window.push_notification(Notification::error(error).autohide(false), cx); window.push_notification(Notification::error(error).autohide(false), cx);
} }
@@ -217,71 +185,23 @@ impl Workspace {
}), }),
); );
subscriptions.push(
// Observe all events emitted by the community registry
cx.subscribe_in(
&communities,
window,
move |this, communities, event, window, cx| match event {
CommunityEvent::Open(id) => {
if let Some(community) = communities.read(cx).community(id) {
let panel = community_ui::init(community, window, cx);
this.community_panel = Some(panel.downgrade());
this.add_panel_to_dock(panel, DockPlacement::Center, window, cx);
}
}
CommunityEvent::Close(_) => {
let Some(panel) = this
.community_panel
.take()
.and_then(|panel| panel.upgrade())
else {
return;
};
this.dock.update(cx, |area, cx| {
ui::dock::add_panel(
area,
PanelHandle::new(panel),
DockPlacement::Center,
window,
cx,
);
ui::dock::focus_tab_panel(area, window, cx);
cx.defer_in(window, |_, window, cx| {
window.dispatch_action(Box::new(ClosePanel), cx);
});
});
}
_ => {}
},
),
);
cx.defer_in(window, move |this, window, cx| { cx.defer_in(window, move |this, window, cx| {
let sidebar = PanelHandle::new(sidebar); let sidebar = PanelHandle::new(sidebar);
this.dock.update(cx, |area, cx| {
let left = DockLayout::tabs().panel_view(Arc::new(sidebar), cx);
area.set_dock(DockPlacement::Left, left, window, cx);
area.set_dock_size(DockPlacement::Left, SIDEBAR_WIDTH, window, cx);
});
let greeter = PanelHandle::new(greeter::init(window, cx)); let greeter = PanelHandle::new(greeter::init(window, cx));
let center = DockLayout::v_split()
.child(DockLayout::tabs().panel_view(Arc::new(greeter), cx), None);
this.dock.update(cx, |area, cx| { this.dock.update(cx, |this, cx| {
area.set_center(center, window, cx); let left = DockLayout::tabs().panel_view(Arc::new(sidebar), cx);
let center = DockLayout::v_split()
.child(DockLayout::tabs().panel_view(Arc::new(greeter), cx), None);
this.set_dock(DockPlacement::Left, left, window, cx);
this.set_dock_size(DockPlacement::Left, SIDEBAR_WIDTH, window, cx);
this.set_center(center, window, cx);
}); });
}); });
Self { Self {
dock, dock,
title_bar_chrome,
community_panel: None,
tasks: vec![], tasks: vec![],
_subscriptions: subscriptions, _subscriptions: subscriptions,
} }
@@ -365,10 +285,11 @@ impl Workspace {
self.add_panel_to_dock(browse::init(window, cx), DockPlacement::Center, window, cx); self.add_panel_to_dock(browse::init(window, cx), DockPlacement::Center, window, cx);
} }
Command::ShowSearch => { Command::ShowSearch => {
self.add_panel_to_dock(search::init(window, cx), DockPlacement::Center, window, cx); let panel = search::init(self.dock.downgrade(), window, cx);
self.add_panel_to_dock(panel, DockPlacement::Center, window, cx);
} }
Command::NewChat => { Command::NewChat => {
new_chat::open(window, cx); new_chat::open(self.dock.downgrade(), window, cx);
} }
Command::NewCommunity => { Command::NewCommunity => {
new_community::open(window, cx); new_community::open(window, cx);
@@ -583,174 +504,6 @@ impl Workspace {
})) }))
}); });
} }
fn titlebar_right(_window: &mut Window, cx: &mut App) -> AnyElement {
let auto_updater = AutoUpdater::try_global(cx);
let chat = ChatRegistry::global(cx);
let nip4e_enabled = AppSettings::get_nip4e(cx);
let nostr = NostrRegistry::global(cx);
let Some(public_key) = nostr.read(cx).current_user() else {
return div().into_any_element();
};
let persons = PersonRegistry::global(cx);
let profile = persons.read(cx).get(&public_key, cx);
let announcement = profile.announcement();
let updater_status = auto_updater.as_ref().and_then(|updater| {
let updater = updater.read(cx);
(!updater.idle()).then(|| updater.status())
});
let staged_update = auto_updater
.as_ref()
.is_some_and(|updater| updater.read(cx).staged());
h_flex()
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
.gap_2()
.when_some(updater_status, |this, status| {
this.child(div().text_xs().italic().child(status))
})
.when(staged_update, |this| {
this.child(
Button::new("restart-to-update")
.label("Restart to Update")
.tooltip("Quit and relaunch into the installed update")
.small()
.ghost()
.on_click(|_event, _window, cx| {
if let Some(auto_updater) = AutoUpdater::try_global(cx) {
auto_updater.update(cx, |this, cx| this.restart(cx));
}
}),
)
})
.when(nip4e_enabled, |this| {
this.child(
Button::new("key")
.icon(IconName::UserKey)
.tooltip("Decoupled encryption key")
.small()
.ghost()
.dropdown_menu(move |this, _window, _cx| {
this.min_w(px(260.))
.label("Encryption Key")
.when_some(announcement.as_ref(), |this, announcement| {
let name = announcement.client_name();
let pkey = shorten_pubkey(announcement.public_key(), 8);
this.item(PopupMenuItem::element(move |_window, cx| {
h_flex()
.gap_1()
.text_sm()
.child(
Icon::new(IconName::Device)
.small()
.text_color(cx.theme().icon_muted),
)
.child(name.clone())
}))
.item(
PopupMenuItem::element(move |_window, cx| {
h_flex()
.gap_1()
.text_sm()
.child(
Icon::new(IconName::UserKey)
.small()
.text_color(cx.theme().icon_muted),
)
.child(SharedString::from(pkey.clone()))
}),
)
})
.separator()
.menu_with_icon(
"Backup",
IconName::Shield,
Box::new(Command::BackupEncryption),
)
.menu_with_icon(
"Restore from secret key",
IconName::Usb,
Box::new(Command::ImportEncryption),
)
.separator()
.menu_with_icon(
"Reload",
IconName::Refresh,
Box::new(Command::RefreshEncryption),
)
.menu_with_icon(
"Reset",
IconName::Warning,
Box::new(Command::ResetEncryption),
)
}),
)
})
.child(
Button::new("inbox")
.icon(IconName::Inbox)
.small()
.ghost()
.dropdown_menu(move |this, _window, cx| {
let urls: Vec<(SharedString, SharedString)> = profile
.messaging_relays()
.iter()
.map(|url| {
(
SharedString::from(url.to_string()),
chat.read(cx).count_messages(url).to_string().into(),
)
})
.collect();
// Header
let menu = this.min_w(px(260.)).label("Messaging Relays");
// Content
let menu = urls.into_iter().fold(menu, |this, (url, count)| {
this.item(PopupMenuItem::element(move |_window, cx| {
h_flex()
.px_1()
.w_full()
.text_sm()
.justify_between()
.child(url.clone())
.child(
div()
.text_xs()
.text_color(cx.theme().text_muted)
.child(count.clone()),
)
}))
});
// Footer
menu.separator()
.menu_with_icon(
"Manage gossip relays",
IconName::Relay,
Box::new(Command::ShowRelayList),
)
.menu_with_icon(
"Manage messaging relays",
IconName::Relay,
Box::new(Command::ShowMessaging),
)
.separator()
.menu_with_icon(
"Reload",
IconName::Refresh,
Box::new(Command::RefreshMessagingRelays),
)
}),
)
.into_any_element()
}
} }
impl Render for Workspace { impl Render for Workspace {
@@ -758,9 +511,6 @@ impl Render for Workspace {
let modal_layer = Root::render_modal_layer(window, cx); let modal_layer = Root::render_modal_layer(window, cx);
let notification_layer = Root::render_notification_layer(window, cx); let notification_layer = Root::render_notification_layer(window, cx);
// Render the title bar chrome
self.title_bar_chrome.set_trailing(Self::titlebar_right);
div() div()
.id("workspace") .id("workspace")
.on_action(cx.listener(Self::on_command)) .on_action(cx.listener(Self::on_command))
+25 -9
View File
@@ -7,8 +7,8 @@ use common::DebouncedDelay;
use gpui::prelude::FluentBuilder; use gpui::prelude::FluentBuilder;
use gpui::{ use gpui::{
AnyElement, App, AppContext, Context, ElementId, Entity, EventEmitter, FocusHandle, Focusable, AnyElement, App, AppContext, Context, ElementId, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Subscription, Task, Window, div, IntoElement, ParentElement, Render, SharedString, Styled, Subscription, Task, WeakEntity,
uniform_list, Window, div, uniform_list,
}; };
use instant::Duration; use instant::Duration;
use nostr_sdk::prelude::*; use nostr_sdk::prelude::*;
@@ -17,7 +17,7 @@ use smallvec::{SmallVec, smallvec};
use state::{FIND_DELAY, NostrRegistry}; use state::{FIND_DELAY, NostrRegistry};
use theme::ActiveTheme; use theme::ActiveTheme;
use ui::button::{Button, ButtonVariants}; use ui::button::{Button, ButtonVariants};
use ui::dock::{Panel, PanelEvent}; use ui::dock::{DockArea, DockPlacement, Panel, PanelEvent, PanelHandle};
use ui::input::{Input, InputEvent, InputState}; use ui::input::{Input, InputEvent, InputState};
use ui::notification::Notification; use ui::notification::Notification;
use ui::{Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, h_flex, v_flex}; use ui::{Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
@@ -26,13 +26,15 @@ use crate::sidebar::{TreeRow, TreeRowKind};
const INPUT_PLACEHOLDER: &str = "Find or start a conversation"; const INPUT_PLACEHOLDER: &str = "Find or start a conversation";
pub fn init(window: &mut Window, cx: &mut App) -> Entity<SearchPanel> { pub fn init(dock: WeakEntity<DockArea>, window: &mut Window, cx: &mut App) -> Entity<SearchPanel> {
cx.new(|cx| SearchPanel::new(window, cx)) cx.new(|cx| SearchPanel::new(dock, window, cx))
} }
pub struct SearchPanel { pub struct SearchPanel {
name: SharedString, name: SharedString,
focus_handle: FocusHandle, focus_handle: FocusHandle,
/// The dock a started chat opens in
dock: WeakEntity<DockArea>,
/// Find input state /// Find input state
find_input: Entity<InputState>, find_input: Entity<InputState>,
@@ -63,7 +65,7 @@ pub struct SearchPanel {
} }
impl SearchPanel { impl SearchPanel {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self { fn new(dock: WeakEntity<DockArea>, window: &mut Window, cx: &mut Context<Self>) -> Self {
let contact_list = cx.new(|_| None); let contact_list = cx.new(|_| None);
let selected_pkeys = cx.new(|_| HashSet::new()); let selected_pkeys = cx.new(|_| HashSet::new());
let find_results = cx.new(|_| None); let find_results = cx.new(|_| None);
@@ -107,6 +109,7 @@ impl SearchPanel {
Self { Self {
name: "Search".into(), name: "Search".into(),
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
dock,
find_input, find_input,
find_debouncer: DebouncedDelay::new(), find_debouncer: DebouncedDelay::new(),
find_results, find_results,
@@ -285,6 +288,7 @@ impl SearchPanel {
fn create_room(&mut self, window: &mut Window, cx: &mut Context<Self>) { fn create_room(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let chat = ChatRegistry::global(cx); let chat = ChatRegistry::global(cx);
let async_chat = chat.downgrade(); let async_chat = chat.downgrade();
let dock = self.dock.clone();
let nostr = NostrRegistry::global(cx); let nostr = NostrRegistry::global(cx);
let Some(public_key) = nostr.read(cx).current_user() else { let Some(public_key) = nostr.read(cx).current_user() else {
@@ -295,14 +299,26 @@ impl SearchPanel {
let receivers = self.get_selected(cx); let receivers = self.get_selected(cx);
self.tasks.push(cx.spawn_in(window, async move |this, cx| { self.tasks.push(cx.spawn_in(window, async move |this, cx| {
// Create a new room and emit it // Create a new room and register it
async_chat.update_in(cx, |this, _window, cx| { let room = async_chat.update_in(cx, |chat, _window, cx| {
let room = cx.new(|_| { let room = cx.new(|_| {
Room::new(public_key, receivers) Room::new(public_key, receivers)
.organize(&public_key) .organize(&public_key)
.kind(RoomKind::Ongoing) .kind(RoomKind::Ongoing)
}); });
this.emit_room(&room, _window, cx); chat.track_room(&room, cx);
room
})?;
// Open it in the dock
cx.update(|window, cx| {
ui::dock::add_panel_to(
&dock,
PanelHandle::new(chat_ui::init(room.downgrade(), window, cx)),
DockPlacement::Center,
window,
cx,
);
})?; })?;
// Reset the find panel // Reset the find panel
File diff suppressed because it is too large Load Diff
@@ -1,74 +0,0 @@
use gpui::{App, InteractiveElement, IntoElement, ParentElement, Styled, Window, div, svg};
use theme::{ActiveTheme, TABBAR_HEIGHT};
use ui::button::{Button, ButtonVariants};
use ui::{StyledExt, h_flex, title_bar_drag_handlers, v_flex};
use crate::dialogs::import;
const TITLE: &str = "Welcome to Coop!";
const DESCRIPTION: &str = "Chat Freely, Stay Private on Nostr.";
pub(super) fn render(window: &mut Window, cx: &mut App) -> impl IntoElement {
v_flex()
.size_full()
.relative()
.bg(cx.theme().surface_background)
.child(title_bar_drag_handlers(
div()
.id("onboarding-drag")
.absolute()
.top_0()
.left_0()
.h(TABBAR_HEIGHT)
.w_full(),
window,
cx,
))
.child(
v_flex()
.size_full()
.justify_end()
.gap_4()
.p_4()
.child(
h_flex()
.gap_2()
.child(
svg()
.path("brand/coop.svg")
.size_8()
.text_color(cx.theme().icon_muted),
)
.child(
v_flex().child(div().font_semibold().child(TITLE)).child(
div()
.text_xs()
.text_color(cx.theme().text_muted)
.child(DESCRIPTION),
),
),
)
.child(
v_flex()
.gap_2()
.w_full()
.child(
Button::new("join-now")
.label("Join now")
.primary()
.font_semibold()
.h_8()
.w_full(),
)
.child(
Button::new("import-identity")
.label("Import identity")
.secondary()
.font_semibold()
.h_8()
.w_full()
.on_click(|_event, window, cx| import::open(window, cx)),
),
),
)
}