feat: add option for toggle chat folders

This commit is contained in:
2025-04-30 13:10:18 +07:00
parent 44f0650617
commit 2c2aeb915e
9 changed files with 247 additions and 164 deletions

217
Cargo.lock generated
View File

@@ -252,14 +252,15 @@ dependencies = [
[[package]] [[package]]
name = "async-executor" name = "async-executor"
version = "1.13.1" version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
dependencies = [ dependencies = [
"async-task", "async-task",
"concurrent-queue", "concurrent-queue",
"fastrand 2.3.0", "fastrand 2.3.0",
"futures-lite 2.6.0", "futures-lite 2.6.0",
"pin-project-lite",
"slab", "slab",
] ]
@@ -439,7 +440,7 @@ dependencies = [
"gpui", "gpui",
"log", "log",
"nostr-sdk", "nostr-sdk",
"reqwest 0.12.15", "reqwest 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
"smol", "smol",
"tempfile", "tempfile",
] ]
@@ -781,9 +782,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.22.0" version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
dependencies = [ dependencies = [
"bytemuck_derive", "bytemuck_derive",
] ]
@@ -979,9 +980,9 @@ dependencies = [
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.40" version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
@@ -1135,7 +1136,7 @@ dependencies = [
[[package]] [[package]]
name = "collections" name = "collections"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
@@ -1524,7 +1525,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#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2315,7 +2316,7 @@ dependencies = [
[[package]] [[package]]
name = "gpui" name = "gpui"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"as-raw-xcb-connection", "as-raw-xcb-connection",
@@ -2407,7 +2408,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#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2631,7 +2632,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#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -2648,7 +2649,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#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-platform-verifier", "rustls-platform-verifier",
@@ -3140,9 +3141,9 @@ dependencies = [
[[package]] [[package]]
name = "kurbo" name = "kurbo"
version = "0.11.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f" checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"smallvec", "smallvec",
@@ -3389,7 +3390,7 @@ dependencies = [
[[package]] [[package]]
name = "media" name = "media"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bindgen 0.71.1", "bindgen 0.71.1",
@@ -3537,12 +3538,6 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "negentropy"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe"
[[package]] [[package]]
name = "negentropy" name = "negentropy"
version = "0.5.0" version = "0.5.0"
@@ -3587,7 +3582,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]] [[package]]
name = "nostr" name = "nostr"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"aes", "aes",
"base64", "base64",
@@ -3600,7 +3595,7 @@ dependencies = [
"getrandom 0.2.16", "getrandom 0.2.16",
"instant", "instant",
"regex", "regex",
"reqwest 0.12.15", "reqwest 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
"scrypt", "scrypt",
"secp256k1", "secp256k1",
"serde", "serde",
@@ -3612,7 +3607,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-connect" name = "nostr-connect"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"nostr", "nostr",
@@ -3624,7 +3619,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-database" name = "nostr-database"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"flatbuffers", "flatbuffers",
"lru", "lru",
@@ -3635,7 +3630,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-lmdb" name = "nostr-lmdb"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"heed", "heed",
@@ -3648,14 +3643,13 @@ dependencies = [
[[package]] [[package]]
name = "nostr-relay-pool" name = "nostr-relay-pool"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"async-wsocket", "async-wsocket",
"atomic-destructor", "atomic-destructor",
"lru", "lru",
"negentropy 0.3.1", "negentropy",
"negentropy 0.5.0",
"nostr", "nostr",
"nostr-database", "nostr-database",
"tokio", "tokio",
@@ -3665,7 +3659,7 @@ dependencies = [
[[package]] [[package]]
name = "nostr-sdk" name = "nostr-sdk"
version = "0.41.0" version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99" source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [ dependencies = [
"async-utility", "async-utility",
"nostr", "nostr",
@@ -4822,7 +4816,7 @@ dependencies = [
[[package]] [[package]]
name = "refineable" name = "refineable"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"derive_refineable", "derive_refineable",
"workspace-hack", "workspace-hack",
@@ -4857,53 +4851,6 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "reqwest"
version = "0.12.8"
source = "git+https://github.com/zed-industries/reqwest.git?rev=fd110f6998da16bbca97b6dddda9be7827c50e29#fd110f6998da16bbca97b6dddda9be7827c50e29"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"once_cell",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"rustls-pki-types",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-rustls",
"tokio-socks",
"tokio-util",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"windows-registry 0.2.0",
]
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.15" version = "0.12.15"
@@ -4957,10 +4904,58 @@ dependencies = [
"windows-registry 0.4.0", "windows-registry 0.4.0",
] ]
[[package]]
name = "reqwest"
version = "0.12.15"
source = "git+https://github.com/zed-industries/reqwest.git?rev=951c770a32f1998d6e999cef3e59e0013e6c4415#951c770a32f1998d6e999cef3e59e0013e6c4415"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"http-body-util",
"hyper",
"hyper-rustls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"once_cell",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-native-certs",
"rustls-pemfile",
"rustls-pki-types",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-rustls",
"tokio-socks",
"tokio-util",
"tower",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"wasm-streams",
"web-sys",
"windows-registry 0.4.0",
]
[[package]] [[package]]
name = "reqwest_client" name = "reqwest_client"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes", "bytes",
@@ -4969,7 +4964,7 @@ dependencies = [
"http_client_tls", "http_client_tls",
"log", "log",
"regex", "regex",
"reqwest 0.12.8", "reqwest 0.12.15 (git+https://github.com/zed-industries/reqwest.git?rev=951c770a32f1998d6e999cef3e59e0013e6c4415)",
"serde", "serde",
"smol", "smol",
"tokio", "tokio",
@@ -5430,7 +5425,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
[[package]] [[package]]
name = "semantic_version" name = "semantic_version"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"serde", "serde",
@@ -5753,7 +5748,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#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"log", "log",
@@ -6266,9 +6261,9 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.8.21" version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231" checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned", "serde_spanned",
@@ -6287,9 +6282,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.25" version = "0.22.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485" checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
@@ -6301,9 +6296,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_write" name = "toml_write"
version = "0.1.0" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976" checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076"
[[package]] [[package]]
name = "tower" name = "tower"
@@ -6663,7 +6658,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "util" name = "util"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92" source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-fs", "async-fs",
@@ -6921,9 +6916,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-backend" name = "wayland-backend"
version = "0.3.8" version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
dependencies = [ dependencies = [
"cc", "cc",
"downcast-rs", "downcast-rs",
@@ -6935,9 +6930,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-client" name = "wayland-client"
version = "0.31.8" version = "0.31.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
dependencies = [ dependencies = [
"bitflags 2.9.0", "bitflags 2.9.0",
"rustix 0.38.44", "rustix 0.38.44",
@@ -6947,9 +6942,9 @@ dependencies = [
[[package]] [[package]]
name = "wayland-cursor" name = "wayland-cursor"
version = "0.31.8" version = "0.31.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182"
dependencies = [ dependencies = [
"rustix 0.38.44", "rustix 0.38.44",
"wayland-client", "wayland-client",
@@ -7244,17 +7239,6 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "windows-registry"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
dependencies = [
"windows-result 0.2.0",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-registry" name = "windows-registry"
version = "0.4.0" version = "0.4.0"
@@ -7286,15 +7270,6 @@ 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.2" version = "0.3.2"
@@ -7304,16 +7279,6 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[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"

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" d="M5.75 3A2.75 2.75 0 0 0 3 5.75v1.422c0 .729.29 1.428.805 1.944l4.829 4.829c.234.234.366.552.366.883v6.422a.75.75 0 0 0 .95.723l4.5-1.25A.75.75 0 0 0 15 20v-5.172c0-.331.132-.649.366-.883l4.829-4.829A2.75 2.75 0 0 0 21 7.172V5.75A2.75 2.75 0 0 0 18.25 3H5.75Z"/>
</svg>

After

Width:  |  Height:  |  Size: 396 B

3
assets/icons/filter.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-linejoin="round" stroke-width="1.5" d="M18.25 3.75H5.75a2 2 0 0 0-2 2v1.422a2 2 0 0 0 .586 1.414l4.828 4.828a2 2 0 0 1 .586 1.414v6.422l4.5-1.25v-5.172a2 2 0 0 1 .586-1.414l4.828-4.828a2 2 0 0 0 .586-1.414V5.75a2 2 0 0 0-2-2Z"/>
</svg>

After

Width:  |  Height:  |  Size: 369 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="M1 11.75A5.75 5.75 0 0 1 6.75 6h10.5A5.75 5.75 0 0 1 23 11.75v.5A5.75 5.75 0 0 1 17.25 18H6.75A5.75 5.75 0 0 1 1 12.25v-.5ZM17 7.5a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9Z" clip-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 345 B

3
assets/icons/toggle.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-width="1.5" d="M17 17.25H7a5.25 5.25 0 1 1 0-10.5h10m0 10.5a5.25 5.25 0 1 0 0-10.5m0 10.5a5.25 5.25 0 1 1 0-10.5"/>
</svg>

After

Width:  |  Height:  |  Size: 256 B

View File

@@ -7,6 +7,7 @@ use gpui::{
}; };
use ui::{ use ui::{
theme::{scale::ColorScaleStep, ActiveTheme}, theme::{scale::ColorScaleStep, ActiveTheme},
tooltip::Tooltip,
Collapsible, Icon, IconName, Sizable, StyledExt, Collapsible, Icon, IconName, Sizable, StyledExt,
}; };
@@ -16,6 +17,7 @@ type Handler = Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>;
pub struct Parent { pub struct Parent {
base: Div, base: Div,
icon: Option<Icon>, icon: Option<Icon>,
tooltip: Option<SharedString>,
label: SharedString, label: SharedString,
items: Vec<Folder>, items: Vec<Folder>,
collapsed: bool, collapsed: bool,
@@ -28,6 +30,7 @@ impl Parent {
base: div().flex().flex_col().gap_2(), base: div().flex().flex_col().gap_2(),
label: label.into(), label: label.into(),
icon: None, icon: None,
tooltip: None,
items: Vec::new(), items: Vec::new(),
collapsed: false, collapsed: false,
handler: Rc::new(|_, _, _| {}), handler: Rc::new(|_, _, _| {}),
@@ -39,6 +42,11 @@ impl Parent {
self self
} }
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
self.tooltip = Some(tooltip.into());
self
}
pub fn collapsed(mut self, collapsed: bool) -> Self { pub fn collapsed(mut self, collapsed: bool) -> Self {
self.collapsed = collapsed; self.collapsed = collapsed;
self self
@@ -105,6 +113,11 @@ impl RenderOnce for Parent {
.when_some(self.icon, |this, icon| this.child(icon.small())) .when_some(self.icon, |this, icon| this.child(icon.small()))
.child(self.label.clone()), .child(self.label.clone()),
) )
.when_some(self.tooltip.clone(), |this, tooltip| {
this.tooltip(move |window, cx| {
Tooltip::new(tooltip.clone(), window, cx).into()
})
})
.hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))) .hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE)))
.on_click(move |ev, window, cx| handler(ev, window, cx)), .on_click(move |ev, window, cx| handler(ev, window, cx)),
) )
@@ -118,6 +131,7 @@ impl RenderOnce for Parent {
pub struct Folder { pub struct Folder {
base: Div, base: Div,
icon: Option<Icon>, icon: Option<Icon>,
tooltip: Option<SharedString>,
label: SharedString, label: SharedString,
items: Vec<FolderItem>, items: Vec<FolderItem>,
collapsed: bool, collapsed: bool,
@@ -130,6 +144,7 @@ impl Folder {
base: div().flex().flex_col().gap_2(), base: div().flex().flex_col().gap_2(),
label: label.into(), label: label.into(),
icon: None, icon: None,
tooltip: None,
items: Vec::new(), items: Vec::new(),
collapsed: false, collapsed: false,
handler: Rc::new(|_, _, _| {}), handler: Rc::new(|_, _, _| {}),
@@ -141,6 +156,11 @@ impl Folder {
self self
} }
pub fn tooltip(mut self, tooltip: impl Into<SharedString>) -> Self {
self.tooltip = Some(tooltip.into());
self
}
pub fn collapsed(mut self, collapsed: bool) -> Self { pub fn collapsed(mut self, collapsed: bool) -> Self {
self.collapsed = collapsed; self.collapsed = collapsed;
self self
@@ -201,6 +221,11 @@ impl RenderOnce for Folder {
.when_some(self.icon, |this, icon| this.child(icon.small())) .when_some(self.icon, |this, icon| this.child(icon.small()))
.child(self.label.clone()), .child(self.label.clone()),
) )
.when_some(self.tooltip.clone(), |this, tooltip| {
this.tooltip(move |window, cx| {
Tooltip::new(tooltip.clone(), window, cx).into()
})
})
.hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE))) .hover(|this| this.bg(cx.theme().base.step(cx, ColorScaleStep::THREE)))
.on_click(move |ev, window, cx| handler(ev, window, cx)), .on_click(move |ev, window, cx| handler(ev, window, cx)),
) )

View File

@@ -1,3 +1,5 @@
use std::{cmp::Reverse, collections::HashSet};
use account::Account; use account::Account;
use button::SidebarButton; use button::SidebarButton;
use chats::{ use chats::{
@@ -10,10 +12,11 @@ use global::get_client;
use gpui::{ use gpui::{
actions, div, img, prelude::FluentBuilder, AnyElement, App, AppContext, Context, Entity, actions, div, img, prelude::FluentBuilder, AnyElement, App, AppContext, Context, Entity,
EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render, EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render,
SharedString, Styled, Task, Window, ScrollHandle, SharedString, StatefulInteractiveElement, Styled, Task, Window,
}; };
use itertools::Itertools;
use ui::{ use ui::{
button::{Button, ButtonVariants}, button::{Button, ButtonCustomVariant, ButtonVariants},
dock_area::{ dock_area::{
dock::DockPlacement, dock::DockPlacement,
panel::{Panel, PanelEvent}, panel::{Panel, PanelEvent},
@@ -36,13 +39,25 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<Sidebar> {
Sidebar::new(window, cx) Sidebar::new(window, cx)
} }
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum Item {
Ongoing,
Incoming,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub enum SubItem {
Trusted,
Unknown,
}
pub struct Sidebar { pub struct Sidebar {
name: SharedString, name: SharedString,
split_into_folders: bool,
active_items: HashSet<Item>,
active_subitems: HashSet<SubItem>,
focus_handle: FocusHandle, focus_handle: FocusHandle,
ongoing: bool, scroll_handle: ScrollHandle,
incoming: bool,
trusted: bool,
unknown: bool,
} }
impl Sidebar { impl Sidebar {
@@ -52,34 +67,41 @@ impl Sidebar {
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self { fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
let focus_handle = cx.focus_handle(); let focus_handle = cx.focus_handle();
let scroll_handle = ScrollHandle::default();
let mut active_items = HashSet::with_capacity(2);
active_items.insert(Item::Ongoing);
let mut active_subitems = HashSet::with_capacity(2);
active_subitems.insert(SubItem::Trusted);
active_subitems.insert(SubItem::Unknown);
Self { Self {
name: "Chat Sidebar".into(), name: "Chat Sidebar".into(),
ongoing: false, split_into_folders: false,
incoming: false, active_items,
trusted: true, active_subitems,
unknown: true,
focus_handle, focus_handle,
scroll_handle,
} }
} }
fn ongoing(&mut self, cx: &mut Context<Self>) { fn toggle_item(&mut self, item: Item, cx: &mut Context<Self>) {
self.ongoing = !self.ongoing; if !self.active_items.remove(&item) {
self.active_items.insert(item);
}
cx.notify(); cx.notify();
} }
fn incoming(&mut self, cx: &mut Context<Self>) { fn toggle_subitem(&mut self, subitem: SubItem, cx: &mut Context<Self>) {
self.incoming = !self.incoming; if !self.active_subitems.remove(&subitem) {
self.active_subitems.insert(subitem);
}
cx.notify(); cx.notify();
} }
fn trusted(&mut self, cx: &mut Context<Self>) { fn split_into_folders(&mut self, cx: &mut Context<Self>) {
self.trusted = !self.trusted; self.split_into_folders = !self.split_into_folders;
cx.notify();
}
fn unknown(&mut self, cx: &mut Context<Self>) {
self.unknown = !self.unknown;
cx.notify(); cx.notify();
} }
@@ -176,20 +198,18 @@ impl Focusable for Sidebar {
} }
impl Render for Sidebar { impl Render for Sidebar {
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 {
let account = Account::global(cx).read(cx).profile.as_ref(); let account = Account::global(cx).read(cx).profile.as_ref();
let registry = ChatRegistry::global(cx).read(cx); let registry = ChatRegistry::global(cx).read(cx);
let rooms = registry.rooms(cx); let rooms = registry.rooms(cx);
let loading = registry.loading(); let loading = registry.loading();
let ongoing = rooms.get(&RoomKind::Ongoing);
let trusted = rooms.get(&RoomKind::Trusted);
let unknown = rooms.get(&RoomKind::Unknown);
div() div()
.scrollable(cx.entity_id(), ScrollbarAxis::Vertical) .id("sidebar")
.track_scroll(&self.scroll_handle)
.on_action(cx.listener(Self::on_logout)) .on_action(cx.listener(Self::on_logout))
.overflow_y_scroll()
.size_full() .size_full()
.flex() .flex()
.flex_col() .flex_col()
@@ -279,23 +299,65 @@ impl Render for Sidebar {
.gap_2() .gap_2()
.child( .child(
div() div()
.px_2() .pl_2()
.pr_1()
.flex()
.justify_between()
.items_center()
.text_xs() .text_xs()
.font_semibold() .font_semibold()
.text_color(cx.theme().base.step(cx, ColorScaleStep::NINE)) .text_color(cx.theme().base.step(cx, ColorScaleStep::NINE))
.child("Messages"), .child("Messages")
.child(
Button::new("menu")
.tooltip("Toggle chat folders")
.map(|this| {
if self.split_into_folders {
this.icon(IconName::ToggleFill)
} else {
this.icon(IconName::Toggle)
}
})
.small()
.custom(
ButtonCustomVariant::new(window, cx)
.foreground(
cx.theme().base.step(cx, ColorScaleStep::NINE),
)
.color(cx.theme().transparent)
.hover(cx.theme().transparent)
.active(cx.theme().transparent)
.border(cx.theme().transparent),
)
.on_click(cx.listener(move |this, _, _, cx| {
this.split_into_folders(cx);
})),
),
) )
.map(|this| { .map(|this| {
if loading { if loading {
this.children(self.render_skeleton(6)) this.children(self.render_skeleton(6))
} else if !self.split_into_folders {
let rooms: Vec<_> = rooms
.values()
.flat_map(|v| v.iter().cloned())
.sorted_by_key(|e| Reverse(e.read(cx).created_at))
.collect();
this.children(Self::render_items(&rooms, cx))
} else { } else {
let ongoing = rooms.get(&RoomKind::Ongoing);
let trusted = rooms.get(&RoomKind::Trusted);
let unknown = rooms.get(&RoomKind::Unknown);
this.when_some(ongoing, |this, rooms| { this.when_some(ongoing, |this, rooms| {
this.child( this.child(
Folder::new("Ongoing") Folder::new("Ongoing")
.icon(IconName::Folder) .icon(IconName::Folder)
.collapsed(self.ongoing) .tooltip("All ongoing conversations")
.collapsed(!self.active_items.contains(&Item::Ongoing))
.on_click(cx.listener(move |this, _, _, cx| { .on_click(cx.listener(move |this, _, _, cx| {
this.ongoing(cx); this.toggle_item(Item::Ongoing, cx);
})) }))
.children(Self::render_items(rooms, cx)), .children(Self::render_items(rooms, cx)),
) )
@@ -303,17 +365,23 @@ impl Render for Sidebar {
.child( .child(
Parent::new("Incoming") Parent::new("Incoming")
.icon(IconName::Folder) .icon(IconName::Folder)
.collapsed(self.incoming) .tooltip("Incoming messages")
.collapsed(!self.active_items.contains(&Item::Incoming))
.on_click(cx.listener(move |this, _, _, cx| { .on_click(cx.listener(move |this, _, _, cx| {
this.incoming(cx); this.toggle_item(Item::Incoming, cx);
})) }))
.when_some(trusted, |this, rooms| { .when_some(trusted, |this, rooms| {
this.child( this.child(
Folder::new("Trusted") Folder::new("Trusted")
.icon(IconName::Folder) .icon(IconName::Folder)
.collapsed(self.trusted) .tooltip("Incoming messages from trusted contacts")
.collapsed(
!self
.active_subitems
.contains(&SubItem::Trusted),
)
.on_click(cx.listener(move |this, _, _, cx| { .on_click(cx.listener(move |this, _, _, cx| {
this.trusted(cx); this.toggle_subitem(SubItem::Trusted, cx);
})) }))
.children(Self::render_items(rooms, cx)), .children(Self::render_items(rooms, cx)),
) )
@@ -322,9 +390,14 @@ impl Render for Sidebar {
this.child( this.child(
Folder::new("Unknown") Folder::new("Unknown")
.icon(IconName::Folder) .icon(IconName::Folder)
.collapsed(self.unknown) .tooltip("Incoming messages from unknowns")
.collapsed(
!self
.active_subitems
.contains(&SubItem::Unknown),
)
.on_click(cx.listener(move |this, _, _, cx| { .on_click(cx.listener(move |this, _, _, cx| {
this.unknown(cx); this.toggle_subitem(SubItem::Unknown, cx);
})) }))
.children(Self::render_items(rooms, cx)), .children(Self::render_items(rooms, cx)),
) )

View File

@@ -36,6 +36,8 @@ pub enum IconName {
EmojiFill, EmojiFill,
Folder, Folder,
FolderFill, FolderFill,
Filter,
FilterFill,
Inbox, Inbox,
Info, Info,
Loader, Loader,
@@ -61,6 +63,8 @@ pub enum IconName {
SortAscending, SortAscending,
SortDescending, SortDescending,
Sun, Sun,
Toggle,
ToggleFill,
ThumbsDown, ThumbsDown,
ThumbsUp, ThumbsUp,
TriangleAlert, TriangleAlert,
@@ -101,6 +105,8 @@ impl IconName {
Self::EyeOff => "icons/eye-off.svg", Self::EyeOff => "icons/eye-off.svg",
Self::Folder => "icons/folder.svg", Self::Folder => "icons/folder.svg",
Self::FolderFill => "icons/folder-fill.svg", Self::FolderFill => "icons/folder-fill.svg",
Self::Filter => "icons/filter.svg",
Self::FilterFill => "icons/filter-fill.svg",
Self::Inbox => "icons/inbox.svg", Self::Inbox => "icons/inbox.svg",
Self::Info => "icons/info.svg", Self::Info => "icons/info.svg",
Self::Loader => "icons/loader.svg", Self::Loader => "icons/loader.svg",
@@ -126,6 +132,8 @@ impl IconName {
Self::SortAscending => "icons/sort-ascending.svg", Self::SortAscending => "icons/sort-ascending.svg",
Self::SortDescending => "icons/sort-descending.svg", Self::SortDescending => "icons/sort-descending.svg",
Self::Sun => "icons/sun.svg", Self::Sun => "icons/sun.svg",
Self::Toggle => "icons/toggle.svg",
Self::ToggleFill => "icons/toggle-fill.svg",
Self::ThumbsDown => "icons/thumbs-down.svg", Self::ThumbsDown => "icons/thumbs-down.svg",
Self::ThumbsUp => "icons/thumbs-up.svg", Self::ThumbsUp => "icons/thumbs-up.svg",
Self::TriangleAlert => "icons/triangle-alert.svg", Self::TriangleAlert => "icons/triangle-alert.svg",

View File

@@ -64,7 +64,7 @@ pub trait StyledExt: Styled + Sized {
/// Set as Popover style /// Set as Popover style
fn popover_style(self, cx: &mut App) -> Self { fn popover_style(self, cx: &mut App) -> Self {
self.bg(cx.theme().base.step(cx, ColorScaleStep::TWO)) self.bg(cx.theme().background)
.border_1() .border_1()
.border_color(cx.theme().base.step(cx, ColorScaleStep::SIX)) .border_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.shadow_lg() .shadow_lg()