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]]
name = "async-executor"
version = "1.13.1"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand 2.3.0",
"futures-lite 2.6.0",
"pin-project-lite",
"slab",
]
@@ -439,7 +440,7 @@ dependencies = [
"gpui",
"log",
"nostr-sdk",
"reqwest 0.12.15",
"reqwest 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
"smol",
"tempfile",
]
@@ -781,9 +782,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "bytemuck"
version = "1.22.0"
version = "1.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540"
checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
dependencies = [
"bytemuck_derive",
]
@@ -979,9 +980,9 @@ dependencies = [
[[package]]
name = "chrono"
version = "0.4.40"
version = "0.4.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -1135,7 +1136,7 @@ dependencies = [
[[package]]
name = "collections"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"indexmap",
"rustc-hash 2.1.1",
@@ -1524,7 +1525,7 @@ dependencies = [
[[package]]
name = "derive_refineable"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"proc-macro2",
"quote",
@@ -2315,7 +2316,7 @@ dependencies = [
[[package]]
name = "gpui"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"as-raw-xcb-connection",
@@ -2407,7 +2408,7 @@ dependencies = [
[[package]]
name = "gpui_macros"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"proc-macro2",
"quote",
@@ -2631,7 +2632,7 @@ dependencies = [
[[package]]
name = "http_client"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"bytes",
@@ -2648,7 +2649,7 @@ dependencies = [
[[package]]
name = "http_client_tls"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"rustls",
"rustls-platform-verifier",
@@ -3140,9 +3141,9 @@ dependencies = [
[[package]]
name = "kurbo"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89234b2cc610a7dd927ebde6b41dd1a5d4214cffaef4cf1fb2195d592f92518f"
checksum = "1077d333efea6170d9ccb96d3c3026f300ca0773da4938cc4c811daa6df68b0c"
dependencies = [
"arrayvec",
"smallvec",
@@ -3389,7 +3390,7 @@ dependencies = [
[[package]]
name = "media"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"bindgen 0.71.1",
@@ -3537,12 +3538,6 @@ dependencies = [
"tempfile",
]
[[package]]
name = "negentropy"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe"
[[package]]
name = "negentropy"
version = "0.5.0"
@@ -3587,7 +3582,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
[[package]]
name = "nostr"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"aes",
"base64",
@@ -3600,7 +3595,7 @@ dependencies = [
"getrandom 0.2.16",
"instant",
"regex",
"reqwest 0.12.15",
"reqwest 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
"scrypt",
"secp256k1",
"serde",
@@ -3612,7 +3607,7 @@ dependencies = [
[[package]]
name = "nostr-connect"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"async-utility",
"nostr",
@@ -3624,7 +3619,7 @@ dependencies = [
[[package]]
name = "nostr-database"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"flatbuffers",
"lru",
@@ -3635,7 +3630,7 @@ dependencies = [
[[package]]
name = "nostr-lmdb"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"async-utility",
"heed",
@@ -3648,14 +3643,13 @@ dependencies = [
[[package]]
name = "nostr-relay-pool"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"async-utility",
"async-wsocket",
"atomic-destructor",
"lru",
"negentropy 0.3.1",
"negentropy 0.5.0",
"negentropy",
"nostr",
"nostr-database",
"tokio",
@@ -3665,7 +3659,7 @@ dependencies = [
[[package]]
name = "nostr-sdk"
version = "0.41.0"
source = "git+https://github.com/rust-nostr/nostr#2423323593f967a7c0d3136a1b0c3c89ee219d99"
source = "git+https://github.com/rust-nostr/nostr#7edeac7becbec534e89b0e3cc1aedf7f64691e2a"
dependencies = [
"async-utility",
"nostr",
@@ -4822,7 +4816,7 @@ dependencies = [
[[package]]
name = "refineable"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"derive_refineable",
"workspace-hack",
@@ -4857,53 +4851,6 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "reqwest"
version = "0.12.15"
@@ -4957,10 +4904,58 @@ dependencies = [
"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]]
name = "reqwest_client"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"bytes",
@@ -4969,7 +4964,7 @@ dependencies = [
"http_client_tls",
"log",
"regex",
"reqwest 0.12.8",
"reqwest 0.12.15 (git+https://github.com/zed-industries/reqwest.git?rev=951c770a32f1998d6e999cef3e59e0013e6c4415)",
"serde",
"smol",
"tokio",
@@ -5430,7 +5425,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
[[package]]
name = "semantic_version"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"serde",
@@ -5753,7 +5748,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "sum_tree"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"arrayvec",
"log",
@@ -6266,9 +6261,9 @@ dependencies = [
[[package]]
name = "toml"
version = "0.8.21"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900f6c86a685850b1bc9f6223b20125115ee3f31e01207d81655bbcc0aea9231"
checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae"
dependencies = [
"serde",
"serde_spanned",
@@ -6287,9 +6282,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.22.25"
version = "0.22.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10558ed0bd2a1562e630926a2d1f0b98c827da99fabd3fe20920a59642504485"
checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e"
dependencies = [
"indexmap",
"serde",
@@ -6301,9 +6296,9 @@ dependencies = [
[[package]]
name = "toml_write"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28391a4201ba7eb1984cfeb6862c0b3ea2cfe23332298967c749dddc0d6cd976"
checksum = "bfb942dfe1d8e29a7ee7fcbde5bd2b9a25fb89aa70caea2eba3bee836ff41076"
[[package]]
name = "tower"
@@ -6663,7 +6658,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "util"
version = "0.1.0"
source = "git+https://github.com/zed-industries/zed#f060918b578bb3b565adb9daf3a387d40496ca92"
source = "git+https://github.com/zed-industries/zed#1a4d7249f6cf59dc37f64c8f745f0dee47a4e9ce"
dependencies = [
"anyhow",
"async-fs",
@@ -6921,9 +6916,9 @@ dependencies = [
[[package]]
name = "wayland-backend"
version = "0.3.8"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf"
checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
dependencies = [
"cc",
"downcast-rs",
@@ -6935,9 +6930,9 @@ dependencies = [
[[package]]
name = "wayland-client"
version = "0.31.8"
version = "0.31.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
dependencies = [
"bitflags 2.9.0",
"rustix 0.38.44",
@@ -6947,9 +6942,9 @@ dependencies = [
[[package]]
name = "wayland-cursor"
version = "0.31.8"
version = "0.31.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d"
checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182"
dependencies = [
"rustix 0.38.44",
"wayland-client",
@@ -7244,17 +7239,6 @@ dependencies = [
"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]]
name = "windows-registry"
version = "0.4.0"
@@ -7286,15 +7270,6 @@ dependencies = [
"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]]
name = "windows-result"
version = "0.3.2"
@@ -7304,16 +7279,6 @@ dependencies = [
"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]]
name = "windows-strings"
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::{
theme::{scale::ColorScaleStep, ActiveTheme},
tooltip::Tooltip,
Collapsible, Icon, IconName, Sizable, StyledExt,
};
@@ -16,6 +17,7 @@ type Handler = Rc<dyn Fn(&ClickEvent, &mut Window, &mut App)>;
pub struct Parent {
base: Div,
icon: Option<Icon>,
tooltip: Option<SharedString>,
label: SharedString,
items: Vec<Folder>,
collapsed: bool,
@@ -28,6 +30,7 @@ impl Parent {
base: div().flex().flex_col().gap_2(),
label: label.into(),
icon: None,
tooltip: None,
items: Vec::new(),
collapsed: false,
handler: Rc::new(|_, _, _| {}),
@@ -39,6 +42,11 @@ impl Parent {
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 {
self.collapsed = collapsed;
self
@@ -105,6 +113,11 @@ impl RenderOnce for Parent {
.when_some(self.icon, |this, icon| this.child(icon.small()))
.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)))
.on_click(move |ev, window, cx| handler(ev, window, cx)),
)
@@ -118,6 +131,7 @@ impl RenderOnce for Parent {
pub struct Folder {
base: Div,
icon: Option<Icon>,
tooltip: Option<SharedString>,
label: SharedString,
items: Vec<FolderItem>,
collapsed: bool,
@@ -130,6 +144,7 @@ impl Folder {
base: div().flex().flex_col().gap_2(),
label: label.into(),
icon: None,
tooltip: None,
items: Vec::new(),
collapsed: false,
handler: Rc::new(|_, _, _| {}),
@@ -141,6 +156,11 @@ impl Folder {
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 {
self.collapsed = collapsed;
self
@@ -201,6 +221,11 @@ impl RenderOnce for Folder {
.when_some(self.icon, |this, icon| this.child(icon.small()))
.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)))
.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 button::SidebarButton;
use chats::{
@@ -10,10 +12,11 @@ use global::get_client;
use gpui::{
actions, div, img, prelude::FluentBuilder, AnyElement, App, AppContext, Context, Entity,
EventEmitter, FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render,
SharedString, Styled, Task, Window,
ScrollHandle, SharedString, StatefulInteractiveElement, Styled, Task, Window,
};
use itertools::Itertools;
use ui::{
button::{Button, ButtonVariants},
button::{Button, ButtonCustomVariant, ButtonVariants},
dock_area::{
dock::DockPlacement,
panel::{Panel, PanelEvent},
@@ -36,13 +39,25 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<Sidebar> {
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 {
name: SharedString,
split_into_folders: bool,
active_items: HashSet<Item>,
active_subitems: HashSet<SubItem>,
focus_handle: FocusHandle,
ongoing: bool,
incoming: bool,
trusted: bool,
unknown: bool,
scroll_handle: ScrollHandle,
}
impl Sidebar {
@@ -52,34 +67,41 @@ impl Sidebar {
fn view(_window: &mut Window, cx: &mut Context<Self>) -> Self {
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 {
name: "Chat Sidebar".into(),
ongoing: false,
incoming: false,
trusted: true,
unknown: true,
split_into_folders: false,
active_items,
active_subitems,
focus_handle,
scroll_handle,
}
}
fn ongoing(&mut self, cx: &mut Context<Self>) {
self.ongoing = !self.ongoing;
fn toggle_item(&mut self, item: Item, cx: &mut Context<Self>) {
if !self.active_items.remove(&item) {
self.active_items.insert(item);
}
cx.notify();
}
fn incoming(&mut self, cx: &mut Context<Self>) {
self.incoming = !self.incoming;
fn toggle_subitem(&mut self, subitem: SubItem, cx: &mut Context<Self>) {
if !self.active_subitems.remove(&subitem) {
self.active_subitems.insert(subitem);
}
cx.notify();
}
fn trusted(&mut self, cx: &mut Context<Self>) {
self.trusted = !self.trusted;
cx.notify();
}
fn unknown(&mut self, cx: &mut Context<Self>) {
self.unknown = !self.unknown;
fn split_into_folders(&mut self, cx: &mut Context<Self>) {
self.split_into_folders = !self.split_into_folders;
cx.notify();
}
@@ -176,20 +198,18 @@ impl Focusable 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 registry = ChatRegistry::global(cx).read(cx);
let rooms = registry.rooms(cx);
let loading = registry.loading();
let ongoing = rooms.get(&RoomKind::Ongoing);
let trusted = rooms.get(&RoomKind::Trusted);
let unknown = rooms.get(&RoomKind::Unknown);
div()
.scrollable(cx.entity_id(), ScrollbarAxis::Vertical)
.id("sidebar")
.track_scroll(&self.scroll_handle)
.on_action(cx.listener(Self::on_logout))
.overflow_y_scroll()
.size_full()
.flex()
.flex_col()
@@ -279,23 +299,65 @@ impl Render for Sidebar {
.gap_2()
.child(
div()
.px_2()
.pl_2()
.pr_1()
.flex()
.justify_between()
.items_center()
.text_xs()
.font_semibold()
.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| {
if loading {
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 {
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.child(
Folder::new("Ongoing")
.icon(IconName::Folder)
.collapsed(self.ongoing)
.tooltip("All ongoing conversations")
.collapsed(!self.active_items.contains(&Item::Ongoing))
.on_click(cx.listener(move |this, _, _, cx| {
this.ongoing(cx);
this.toggle_item(Item::Ongoing, cx);
}))
.children(Self::render_items(rooms, cx)),
)
@@ -303,17 +365,23 @@ impl Render for Sidebar {
.child(
Parent::new("Incoming")
.icon(IconName::Folder)
.collapsed(self.incoming)
.tooltip("Incoming messages")
.collapsed(!self.active_items.contains(&Item::Incoming))
.on_click(cx.listener(move |this, _, _, cx| {
this.incoming(cx);
this.toggle_item(Item::Incoming, cx);
}))
.when_some(trusted, |this, rooms| {
this.child(
Folder::new("Trusted")
.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| {
this.trusted(cx);
this.toggle_subitem(SubItem::Trusted, cx);
}))
.children(Self::render_items(rooms, cx)),
)
@@ -322,9 +390,14 @@ impl Render for Sidebar {
this.child(
Folder::new("Unknown")
.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| {
this.unknown(cx);
this.toggle_subitem(SubItem::Unknown, cx);
}))
.children(Self::render_items(rooms, cx)),
)

View File

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

View File

@@ -64,7 +64,7 @@ pub trait StyledExt: Styled + Sized {
/// Set as Popover style
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_color(cx.theme().base.step(cx, ColorScaleStep::SIX))
.shadow_lg()