update ui
This commit is contained in:
69
Cargo.lock
generated
69
Cargo.lock
generated
@@ -1230,7 +1230,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collections"
|
name = "collections"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gpui_util",
|
"gpui_util",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -1393,6 +1393,7 @@ dependencies = [
|
|||||||
"gpui",
|
"gpui",
|
||||||
"gpui_platform",
|
"gpui_platform",
|
||||||
"gpui_web",
|
"gpui_web",
|
||||||
|
"instant",
|
||||||
"log",
|
"log",
|
||||||
"person",
|
"person",
|
||||||
"settings",
|
"settings",
|
||||||
@@ -1713,7 +1714,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#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1825,13 +1826,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "displaydoc"
|
name = "displaydoc"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
|
checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.119",
|
"syn 3.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1906,7 +1907,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"memchr",
|
"memchr",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"toml 1.1.3+spec-1.1.0",
|
"toml 1.1.4+spec-1.1.0",
|
||||||
"vswhom",
|
"vswhom",
|
||||||
"winreg",
|
"winreg",
|
||||||
]
|
]
|
||||||
@@ -2609,7 +2610,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@@ -2691,7 +2692,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_linux"
|
name = "gpui_linux"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_unix",
|
"accesskit_unix",
|
||||||
@@ -2743,7 +2744,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_macos"
|
name = "gpui_macos"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_macos",
|
"accesskit_macos",
|
||||||
@@ -2792,7 +2793,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#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2803,7 +2804,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_platform"
|
name = "gpui_platform"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -2816,7 +2817,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_shared_string"
|
name = "gpui_shared_string"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"schemars",
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2826,7 +2827,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_tokio"
|
name = "gpui_tokio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -2837,7 +2838,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_util"
|
name = "gpui_util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"log",
|
"log",
|
||||||
@@ -2847,7 +2848,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_web"
|
name = "gpui_web"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
@@ -2870,7 +2871,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_wgpu"
|
name = "gpui_wgpu"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
@@ -2900,7 +2901,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui_windows"
|
name = "gpui_windows"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"accesskit",
|
"accesskit",
|
||||||
"accesskit_windows",
|
"accesskit_windows",
|
||||||
@@ -3190,7 +3191,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#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@@ -3210,7 +3211,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#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-platform-verifier",
|
"rustls-platform-verifier",
|
||||||
@@ -3502,6 +3503,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4014,7 +4018,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "media"
|
name = "media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
@@ -4917,7 +4921,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "perf"
|
name = "perf"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collections",
|
"collections",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -5729,7 +5733,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "refineable"
|
name = "refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_refineable",
|
"derive_refineable",
|
||||||
]
|
]
|
||||||
@@ -5811,7 +5815,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest_client"
|
name = "reqwest_client"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -6126,7 +6130,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "scheduler"
|
name = "scheduler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-task",
|
"async-task",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -6750,7 +6754,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#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heapless 0.9.3",
|
"heapless 0.9.3",
|
||||||
"log",
|
"log",
|
||||||
@@ -7286,9 +7290,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "1.1.3+spec-1.1.0"
|
version = "1.1.4+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
|
checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
@@ -7751,7 +7755,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util_macros"
|
name = "util_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"perf",
|
"perf",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -7961,8 +7965,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm_thread"
|
name = "wasm_thread"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/zed-industries/wasm_thread?rev=0cf96c7708dfb97ccf3da50347e25edcf75d6937#0cf96c7708dfb97ccf3da50347e25edcf75d6937"
|
||||||
checksum = "b7516db7f32decdadb1c3b8deb1b7d78b9df7606c5cc2f6241737c2ab3a0258e"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -9485,7 +9488,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "zlog"
|
name = "zlog"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -9502,7 +9505,7 @@ checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing"
|
name = "ztracing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -9513,7 +9516,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing_macro"
|
name = "ztracing_macro"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#8e4e5a39eed932d943cb7a3e7078885b75d1ea54"
|
source = "git+https://github.com/zed-industries/zed#06b6160d46ae8a9074cd367ed64f742b47beca64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::cmp::Reverse;
|
|||||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::{Arc, LazyLock, RwLock};
|
use std::sync::{Arc, LazyLock, RwLock};
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::{Error, anyhow};
|
use anyhow::{Error, anyhow};
|
||||||
use common::EventExt;
|
use common::EventExt;
|
||||||
@@ -12,6 +11,7 @@ use gpui::{
|
|||||||
App, AppContext, Context, Entity, EventEmitter, Global, SharedString, Subscription, Task,
|
App, AppContext, Context, Entity, EventEmitter, Global, SharedString, Subscription, Task,
|
||||||
WeakEntity, Window,
|
WeakEntity, Window,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use state::{DEVICE_GIFTWRAP, NostrRegistry, USER_GIFTWRAP, UniversalSigner};
|
use state::{DEVICE_GIFTWRAP, NostrRegistry, USER_GIFTWRAP, UniversalSigner};
|
||||||
@@ -399,7 +399,7 @@ impl ChatRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
let filter = Filter::new().kind(Kind::GiftWrap).pubkey(public_key);
|
||||||
let id = SubscriptionId::new(format!("{}-msg", public_key.to_hex()));
|
let id = SubscriptionId::new(USER_GIFTWRAP);
|
||||||
|
|
||||||
let target: HashMap<RelayUrl, Filter> = relays
|
let target: HashMap<RelayUrl, Filter> = relays
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@@ -1474,12 +1474,7 @@ impl Render for ChatPanel {
|
|||||||
.gap_2()
|
.gap_2()
|
||||||
.border_b_1()
|
.border_b_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.child(
|
.child(Input::new(&self.subject_input).text_sm().small())
|
||||||
Input::new(&self.subject_input)
|
|
||||||
.text_sm()
|
|
||||||
.small()
|
|
||||||
.bordered(false),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Button::new("change")
|
Button::new("change")
|
||||||
.icon(IconName::CheckCircle)
|
.icon(IconName::CheckCircle)
|
||||||
|
|||||||
@@ -39,14 +39,15 @@ pub const NOSTR_CONNECT_RELAY: &str = "wss://relay.nip46.com";
|
|||||||
pub const WOT_RELAYS: [&str; 1] = ["wss://relay.vertexlab.io"];
|
pub const WOT_RELAYS: [&str; 1] = ["wss://relay.vertexlab.io"];
|
||||||
|
|
||||||
/// Default search relays
|
/// Default search relays
|
||||||
pub const INDEXER_RELAYS: [&str; 1] = ["wss://indexer.coracle.social"];
|
pub const INDEXER_RELAYS: [&str; 2] = ["wss://indexer.coracle.social", "wss://user.kindpag.es"];
|
||||||
|
|
||||||
/// Default search relays
|
/// Default search relays
|
||||||
pub const SEARCH_RELAYS: [&str; 2] = ["wss://antiprimal.net", "wss://search.nos.today"];
|
pub const SEARCH_RELAYS: [&str; 2] = ["wss://antiprimal.net", "wss://search.nos.today"];
|
||||||
|
|
||||||
/// Default bootstrap relays
|
/// Default bootstrap relays
|
||||||
pub const BOOTSTRAP_RELAYS: [&str; 3] = [
|
pub const BOOTSTRAP_RELAYS: [&str; 4] = [
|
||||||
"wss://relay.ditto.pub",
|
"wss://relay.ditto.pub",
|
||||||
"wss://relay.primal.net",
|
"wss://relay.primal.net",
|
||||||
"wss://user.kindpag.es",
|
"wss://relay.nostr.net",
|
||||||
|
"wss://profiles.nostr1.com",
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ impl ThemeColors {
|
|||||||
elevated_surface_background: neutral().light().step_3(),
|
elevated_surface_background: neutral().light().step_3(),
|
||||||
panel_background: neutral().light().step_1(),
|
panel_background: neutral().light().step_1(),
|
||||||
overlay: neutral().light_alpha().step_3(),
|
overlay: neutral().light_alpha().step_3(),
|
||||||
title_bar: neutral().light().step_3(),
|
title_bar: neutral().light().step_2(),
|
||||||
title_bar_inactive: neutral().light().step_1(),
|
title_bar_inactive: neutral().light().step_1(),
|
||||||
window_border: hsl(240.0, 5.9, 78.0),
|
window_border: hsl(240.0, 5.9, 78.0),
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ impl ThemeColors {
|
|||||||
elevated_surface_background: neutral().dark().step_3(),
|
elevated_surface_background: neutral().dark().step_3(),
|
||||||
panel_background: neutral().dark().step_1(),
|
panel_background: neutral().dark().step_1(),
|
||||||
overlay: neutral().dark_alpha().step_3(),
|
overlay: neutral().dark_alpha().step_3(),
|
||||||
title_bar: neutral().dark().step_3(),
|
title_bar: neutral().dark().step_2(),
|
||||||
title_bar_inactive: neutral().dark().step_1(),
|
title_bar_inactive: neutral().dark().step_1(),
|
||||||
window_border: hsl(240.0, 3.7, 28.0),
|
window_border: hsl(240.0, 3.7, 28.0),
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ pub const CLIENT_SIDE_DECORATION_BORDER: Pixels = px(1.0);
|
|||||||
pub const TITLEBAR_HEIGHT: Pixels = px(36.0);
|
pub const TITLEBAR_HEIGHT: Pixels = px(36.0);
|
||||||
|
|
||||||
/// Defines workspace tabbar height
|
/// Defines workspace tabbar height
|
||||||
pub const TABBAR_HEIGHT: Pixels = px(28.0);
|
pub const TABBAR_HEIGHT: Pixels = px(36.0);
|
||||||
|
|
||||||
/// Defines default sidebar width
|
/// Defines default sidebar width
|
||||||
pub const SIDEBAR_WIDTH: Pixels = px(240.);
|
pub const SIDEBAR_WIDTH: Pixels = px(240.);
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, AnyView, App, AppContext, Axis, Bounds, Context, Decorations, Edges, Entity,
|
AnyElement, AnyView, App, AppContext, Axis, Bounds, Context, Edges, Entity, EntityId,
|
||||||
EntityId, EventEmitter, Focusable, InteractiveElement as _, IntoElement, ParentElement as _,
|
EventEmitter, Focusable, InteractiveElement as _, IntoElement, ParentElement as _, Pixels,
|
||||||
Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window, actions, div, px,
|
Render, SharedString, Styled, Subscription, WeakEntity, Window, actions, div, px,
|
||||||
};
|
};
|
||||||
use theme::CLIENT_SIDE_DECORATION_ROUNDING;
|
|
||||||
|
|
||||||
use crate::ElementExt;
|
use crate::ElementExt;
|
||||||
|
|
||||||
@@ -110,15 +109,8 @@ impl DockItem {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut App,
|
cx: &mut App,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut items = items;
|
|
||||||
|
|
||||||
let stack_panel = cx.new(|cx| {
|
let stack_panel = cx.new(|cx| {
|
||||||
let mut stack_panel = StackPanel::new(axis, window, cx);
|
let mut stack_panel = StackPanel::new(axis, window, cx);
|
||||||
for (i, item) in items.iter_mut().enumerate() {
|
|
||||||
let view = item.view();
|
|
||||||
let size = sizes.get(i).copied().flatten();
|
|
||||||
stack_panel.add_panel(view.clone(), size, dock_area.clone(), window, cx)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i, item) in items.iter().enumerate() {
|
for (i, item) in items.iter().enumerate() {
|
||||||
let view = item.view();
|
let view = item.view();
|
||||||
@@ -745,34 +737,22 @@ impl EventEmitter<DockEvent> for DockArea {}
|
|||||||
impl Render for DockArea {
|
impl Render for DockArea {
|
||||||
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 view = cx.entity().clone();
|
let view = cx.entity().clone();
|
||||||
let decorations = window.window_decorations();
|
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id("dock-area")
|
.id("dock-area")
|
||||||
.relative()
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.overflow_hidden()
|
|
||||||
.on_prepaint(move |bounds, _, cx| view.update(cx, |r, _| r.bounds = bounds))
|
.on_prepaint(move |bounds, _, cx| view.update(cx, |r, _| r.bounds = bounds))
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
if let Some(zoom_view) = self.zoom_view.clone() {
|
if let Some(zoom_view) = self.zoom_view.clone() {
|
||||||
this.map(|this| match decorations {
|
this.child(zoom_view)
|
||||||
Decorations::Server => this,
|
|
||||||
Decorations::Client { tiling } => this
|
|
||||||
.when(!(tiling.top || tiling.right), |div| {
|
|
||||||
div.rounded_br(CLIENT_SIDE_DECORATION_ROUNDING)
|
|
||||||
})
|
|
||||||
.when(!(tiling.top || tiling.left), |div| {
|
|
||||||
div.rounded_bl(CLIENT_SIDE_DECORATION_ROUNDING)
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
.child(zoom_view)
|
|
||||||
} else {
|
} else {
|
||||||
// render dock
|
// render dock
|
||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_row()
|
.flex_row()
|
||||||
.h_full()
|
.size_full()
|
||||||
// Left dock
|
// Left dock
|
||||||
.when_some(self.left_dock.clone(), |this, dock| {
|
.when_some(self.left_dock.clone(), |this, dock| {
|
||||||
this.child(div().flex().flex_none().child(dock))
|
this.child(div().flex().flex_none().child(dock))
|
||||||
@@ -783,14 +763,8 @@ impl Render for DockArea {
|
|||||||
.flex()
|
.flex()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.overflow_hidden()
|
|
||||||
// Top center
|
// Top center
|
||||||
.child(
|
.child(div().flex_1().child(self.render_items(window, cx)))
|
||||||
div()
|
|
||||||
.flex_1()
|
|
||||||
.overflow_hidden()
|
|
||||||
.child(self.render_items(window, cx)),
|
|
||||||
)
|
|
||||||
// Bottom Dock
|
// Bottom Dock
|
||||||
.when_some(self.bottom_dock.clone(), |this, dock| {
|
.when_some(self.bottom_dock.clone(), |this, dock| {
|
||||||
this.child(dock)
|
this.child(dock)
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gpui::prelude::FluentBuilder;
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
App, AppContext, Axis, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
|
App, AppContext, Axis, Context, DismissEvent, Entity, EventEmitter, FocusHandle, Focusable,
|
||||||
IntoElement, ParentElement, Pixels, Render, SharedString, Styled, Subscription, WeakEntity,
|
IntoElement, ParentElement, Pixels, Render, SharedString, Styled, Subscription, WeakEntity,
|
||||||
Window,
|
Window,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use theme::{ActiveTheme, AxisExt as _, CLIENT_SIDE_DECORATION_ROUNDING, Placement};
|
use theme::{AxisExt as _, Placement};
|
||||||
|
|
||||||
use super::{DockArea, PanelEvent};
|
use super::{DockArea, PanelEvent};
|
||||||
use crate::dock::panel::{Panel, PanelView};
|
use crate::dock::panel::{Panel, PanelView};
|
||||||
@@ -369,18 +368,12 @@ impl Focusable for StackPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EventEmitter<PanelEvent> for StackPanel {}
|
impl EventEmitter<PanelEvent> for StackPanel {}
|
||||||
|
|
||||||
impl EventEmitter<DismissEvent> for StackPanel {}
|
impl EventEmitter<DismissEvent> for StackPanel {}
|
||||||
|
|
||||||
impl Render for StackPanel {
|
impl Render for StackPanel {
|
||||||
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 {
|
||||||
h_flex()
|
h_flex().size_full().overflow_hidden().child(
|
||||||
.size_full()
|
|
||||||
.overflow_hidden()
|
|
||||||
.bg(cx.theme().panel_background)
|
|
||||||
.when(cx.theme().platform.is_linux(), |this| {
|
|
||||||
this.rounded_br(CLIENT_SIDE_DECORATION_ROUNDING)
|
|
||||||
})
|
|
||||||
.child(
|
|
||||||
ResizablePanelGroup::new("stack-panel-group")
|
ResizablePanelGroup::new("stack-panel-group")
|
||||||
.with_state(&self.state)
|
.with_state(&self.state)
|
||||||
.axis(self.axis)
|
.axis(self.axis)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use gpui::{
|
|||||||
ParentElement, Pixels, Render, ScrollHandle, SharedString, StatefulInteractiveElement, Styled,
|
ParentElement, Pixels, Render, ScrollHandle, SharedString, StatefulInteractiveElement, Styled,
|
||||||
WeakEntity, Window, div, px, rems,
|
WeakEntity, Window, div, px, rems,
|
||||||
};
|
};
|
||||||
use theme::{ActiveTheme, AxisExt, CLIENT_SIDE_DECORATION_ROUNDING, Placement, TABBAR_HEIGHT};
|
use theme::{ActiveTheme, AxisExt, Placement, TABBAR_HEIGHT};
|
||||||
|
|
||||||
use crate::button::{Button, ButtonVariants as _};
|
use crate::button::{Button, ButtonVariants as _};
|
||||||
use crate::dock::dock::DockPlacement;
|
use crate::dock::dock::DockPlacement;
|
||||||
@@ -567,6 +567,7 @@ impl TabPanel {
|
|||||||
let left_dock_button = self.render_dock_toggle_button(DockPlacement::Left, window, cx);
|
let left_dock_button = self.render_dock_toggle_button(DockPlacement::Left, window, cx);
|
||||||
let bottom_dock_button = self.render_dock_toggle_button(DockPlacement::Bottom, window, cx);
|
let bottom_dock_button = self.render_dock_toggle_button(DockPlacement::Bottom, window, cx);
|
||||||
let right_dock_button = self.render_dock_toggle_button(DockPlacement::Right, window, cx);
|
let right_dock_button = self.render_dock_toggle_button(DockPlacement::Right, window, cx);
|
||||||
|
|
||||||
let has_extend_dock_button = left_dock_button.is_some() || bottom_dock_button.is_some();
|
let has_extend_dock_button = left_dock_button.is_some() || bottom_dock_button.is_some();
|
||||||
let tabs_count = self.panels.len();
|
let tabs_count = self.panels.len();
|
||||||
let is_bottom_dock = bottom_dock_button.is_some();
|
let is_bottom_dock = bottom_dock_button.is_some();
|
||||||
@@ -586,6 +587,7 @@ impl TabPanel {
|
|||||||
.py_2()
|
.py_2()
|
||||||
.pl_3()
|
.pl_3()
|
||||||
.pr_2()
|
.pr_2()
|
||||||
|
.rounded_t(cx.theme().radius_lg)
|
||||||
.bg(cx.theme().panel_background)
|
.bg(cx.theme().panel_background)
|
||||||
.when(left_dock_button.is_some(), |this| this.pl_2())
|
.when(left_dock_button.is_some(), |this| this.pl_2())
|
||||||
.when(right_dock_button.is_some(), |this| this.pr_2())
|
.when(right_dock_button.is_some(), |this| this.pr_2())
|
||||||
@@ -641,17 +643,14 @@ impl TabPanel {
|
|||||||
TabBar::new("tab-bar")
|
TabBar::new("tab-bar")
|
||||||
.track_scroll(&self.tab_bar_scroll_handle)
|
.track_scroll(&self.tab_bar_scroll_handle)
|
||||||
.h(TABBAR_HEIGHT)
|
.h(TABBAR_HEIGHT)
|
||||||
|
.bg(cx.theme().panel_background)
|
||||||
|
.rounded_t(cx.theme().radius_lg)
|
||||||
.when(has_extend_dock_button, |this| {
|
.when(has_extend_dock_button, |this| {
|
||||||
this.prefix(
|
this.prefix(
|
||||||
h_flex()
|
h_flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.top_0()
|
.top_0()
|
||||||
.right(-px(1.))
|
.right(-px(1.))
|
||||||
.border_r_1()
|
|
||||||
.border_b_1()
|
|
||||||
.h_full()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.bg(cx.theme().tab_background)
|
|
||||||
.pl_0p5()
|
.pl_0p5()
|
||||||
.pr_1()
|
.pr_1()
|
||||||
.children(left_dock_button)
|
.children(left_dock_button)
|
||||||
@@ -780,12 +779,8 @@ impl TabPanel {
|
|||||||
.top_0()
|
.top_0()
|
||||||
.right_0()
|
.right_0()
|
||||||
.h_full()
|
.h_full()
|
||||||
.border_l_1()
|
|
||||||
.border_b_1()
|
|
||||||
.px_0p5()
|
.px_0p5()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.bg(cx.theme().tab_background)
|
|
||||||
.child(self.render_toolbar(state, window, cx))
|
.child(self.render_toolbar(state, window, cx))
|
||||||
.when_some(right_dock_button, |this, btn| this.child(btn)),
|
.when_some(right_dock_button, |this, btn| this.child(btn)),
|
||||||
)
|
)
|
||||||
@@ -815,10 +810,8 @@ impl TabPanel {
|
|||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
|
.rounded_b(cx.theme().radius_lg)
|
||||||
.bg(cx.theme().panel_background)
|
.bg(cx.theme().panel_background)
|
||||||
.when(cx.theme().platform.is_linux(), |this| {
|
|
||||||
this.rounded_b(CLIENT_SIDE_DECORATION_ROUNDING)
|
|
||||||
})
|
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(
|
.child(
|
||||||
active_panel
|
active_panel
|
||||||
@@ -1140,17 +1133,24 @@ impl Render for TabPanel {
|
|||||||
state.closable = false;
|
state.closable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
v_flex()
|
div()
|
||||||
.when(!self.collapsed, |this| {
|
.when(!self.collapsed, |this| {
|
||||||
this.on_action(cx.listener(Self::on_action_toggle_zoom))
|
this.on_action(cx.listener(Self::on_action_toggle_zoom))
|
||||||
.on_action(cx.listener(Self::on_action_close_panel))
|
.on_action(cx.listener(Self::on_action_close_panel))
|
||||||
})
|
})
|
||||||
.id("tab-panel")
|
.id("tab-panel")
|
||||||
.tab_group()
|
|
||||||
.track_focus(&focus_handle)
|
.track_focus(&focus_handle)
|
||||||
.size_full()
|
.size_full()
|
||||||
|
.p_1()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
|
.rounded(cx.theme().radius_lg)
|
||||||
|
.when(cx.theme().shadow, |this| this.shadow_xs())
|
||||||
|
.size_full()
|
||||||
|
.tab_group()
|
||||||
.child(self.render_title_bar(&state, window, cx))
|
.child(self.render_title_bar(&state, window, cx))
|
||||||
.child(self.render_active_panel(&state, window, cx))
|
.child(self.render_active_panel(&state, window, cx)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ pub struct Input {
|
|||||||
cleanable: bool,
|
cleanable: bool,
|
||||||
mask_toggle: bool,
|
mask_toggle: bool,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
bordered: bool,
|
|
||||||
focus_bordered: bool,
|
|
||||||
tab_index: isize,
|
tab_index: isize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
}
|
}
|
||||||
@@ -73,8 +71,6 @@ impl Input {
|
|||||||
cleanable: false,
|
cleanable: false,
|
||||||
mask_toggle: false,
|
mask_toggle: false,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
bordered: true,
|
|
||||||
focus_bordered: true,
|
|
||||||
tab_index: 0,
|
tab_index: 0,
|
||||||
selected: false,
|
selected: false,
|
||||||
}
|
}
|
||||||
@@ -108,18 +104,6 @@ impl Input {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the bordered for the input, default: true
|
|
||||||
pub fn bordered(mut self, bordered: bool) -> Self {
|
|
||||||
self.bordered = bordered;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set focus border for the input, default is true.
|
|
||||||
pub fn focus_bordered(mut self, bordered: bool) -> Self {
|
|
||||||
self.focus_bordered = bordered;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to show the clear button when the input field is not empty, default is false.
|
/// Set whether to show the clear button when the input field is not empty, default is false.
|
||||||
pub fn cleanable(mut self, cleanable: bool) -> Self {
|
pub fn cleanable(mut self, cleanable: bool) -> Self {
|
||||||
self.cleanable = cleanable;
|
self.cleanable = cleanable;
|
||||||
@@ -332,11 +316,6 @@ impl RenderOnce for Input {
|
|||||||
this.bg(bg)
|
this.bg(bg)
|
||||||
.when(self.disabled, |this| this.opacity(0.5))
|
.when(self.disabled, |this| this.opacity(0.5))
|
||||||
.rounded(cx.theme().radius)
|
.rounded(cx.theme().radius)
|
||||||
.when(self.bordered, |this| {
|
|
||||||
this.border_color(cx.theme().border)
|
|
||||||
.border_1()
|
|
||||||
.when(cx.theme().shadow, |this| this.shadow_xs())
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap(gap_x)
|
.gap(gap_x)
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ impl<T: 'static, E: 'static + Render> Element for ResizeHandle<T, E> {
|
|||||||
cx.theme().border
|
cx.theme().border
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut el = div()
|
let mut ele = div()
|
||||||
.id(self.id.clone())
|
.id(self.id.clone())
|
||||||
.occlude()
|
.occlude()
|
||||||
.absolute()
|
.absolute()
|
||||||
@@ -160,16 +160,15 @@ impl<T: 'static, E: 'static + Render> Element for ResizeHandle<T, E> {
|
|||||||
})
|
})
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.bg(bg_color)
|
|
||||||
.group_hover("handle", |this| this.bg(bg_color))
|
.group_hover("handle", |this| this.bg(bg_color))
|
||||||
.when(axis.is_horizontal(), |this| this.h_full().w(HANDLE_SIZE))
|
.when(axis.is_horizontal(), |this| this.h_full().w(HANDLE_SIZE))
|
||||||
.when(axis.is_vertical(), |this| this.w_full().h(HANDLE_SIZE)),
|
.when(axis.is_vertical(), |this| this.w_full().h(HANDLE_SIZE)),
|
||||||
)
|
)
|
||||||
.into_any_element();
|
.into_any_element();
|
||||||
|
|
||||||
let layout_id = el.request_layout(window, cx);
|
let layout_id = ele.request_layout(window, cx);
|
||||||
|
|
||||||
((layout_id, el), state)
|
((layout_id, ele), state)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,396 +2,15 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use gpui::prelude::FluentBuilder as _;
|
use gpui::prelude::FluentBuilder as _;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, App, ClickEvent, Div, Edges, Hsla, InteractiveElement, IntoElement, MouseButton,
|
AnyElement, App, ClickEvent, Div, InteractiveElement, IntoElement, MouseButton, ParentElement,
|
||||||
ParentElement, Pixels, RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window,
|
RenderOnce, SharedString, StatefulInteractiveElement, Styled, Window, div, px, relative,
|
||||||
div, px, relative,
|
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use theme::{ActiveTheme, TABBAR_HEIGHT};
|
||||||
|
|
||||||
use crate::{Icon, IconName, Selectable, Sizable, Size, StyledExt, h_flex};
|
use crate::{Icon, IconName, Selectable, h_flex};
|
||||||
|
|
||||||
pub mod tab_bar;
|
pub mod tab_bar;
|
||||||
|
|
||||||
/// Tab variants.
|
|
||||||
#[derive(Debug, Clone, Default, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub enum TabVariant {
|
|
||||||
#[default]
|
|
||||||
Tab,
|
|
||||||
Outline,
|
|
||||||
Pill,
|
|
||||||
Segmented,
|
|
||||||
Underline,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TabVariant {
|
|
||||||
fn height(&self, size: Size) -> Pixels {
|
|
||||||
match size {
|
|
||||||
Size::XSmall => match self {
|
|
||||||
TabVariant::Underline => px(26.),
|
|
||||||
_ => px(20.),
|
|
||||||
},
|
|
||||||
Size::Small => match self {
|
|
||||||
TabVariant::Underline => px(30.),
|
|
||||||
_ => px(24.),
|
|
||||||
},
|
|
||||||
Size::Large => match self {
|
|
||||||
TabVariant::Underline => px(44.),
|
|
||||||
_ => px(36.),
|
|
||||||
},
|
|
||||||
_ => match self {
|
|
||||||
TabVariant::Underline => px(36.),
|
|
||||||
_ => px(32.),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner_height(&self, size: Size) -> Pixels {
|
|
||||||
match size {
|
|
||||||
Size::XSmall => match self {
|
|
||||||
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(18.),
|
|
||||||
TabVariant::Segmented => px(16.),
|
|
||||||
TabVariant::Underline => px(20.),
|
|
||||||
},
|
|
||||||
Size::Small => match self {
|
|
||||||
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(22.),
|
|
||||||
TabVariant::Segmented => px(18.),
|
|
||||||
TabVariant::Underline => px(22.),
|
|
||||||
},
|
|
||||||
Size::Large => match self {
|
|
||||||
TabVariant::Tab | TabVariant::Outline | TabVariant::Pill => px(36.),
|
|
||||||
TabVariant::Segmented => px(28.),
|
|
||||||
TabVariant::Underline => px(32.),
|
|
||||||
},
|
|
||||||
_ => match self {
|
|
||||||
TabVariant::Tab => px(30.),
|
|
||||||
TabVariant::Outline | TabVariant::Pill => px(26.),
|
|
||||||
TabVariant::Segmented => px(24.),
|
|
||||||
TabVariant::Underline => px(26.),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Default px(12) to match panel px_3, See [`crate::dock::TabPanel`]
|
|
||||||
fn inner_paddings(&self, size: Size) -> Edges<Pixels> {
|
|
||||||
let mut padding_x = match size {
|
|
||||||
Size::XSmall => px(8.),
|
|
||||||
Size::Small => px(10.),
|
|
||||||
Size::Large => px(16.),
|
|
||||||
_ => px(12.),
|
|
||||||
};
|
|
||||||
|
|
||||||
if matches!(self, TabVariant::Underline) {
|
|
||||||
padding_x = px(0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
Edges {
|
|
||||||
left: padding_x,
|
|
||||||
right: padding_x,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner_margins(&self, size: Size) -> Edges<Pixels> {
|
|
||||||
match size {
|
|
||||||
Size::XSmall => match self {
|
|
||||||
TabVariant::Underline => Edges {
|
|
||||||
top: px(1.),
|
|
||||||
bottom: px(2.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
_ => Edges::all(px(0.)),
|
|
||||||
},
|
|
||||||
Size::Small => match self {
|
|
||||||
TabVariant::Underline => Edges {
|
|
||||||
top: px(2.),
|
|
||||||
bottom: px(3.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
_ => Edges::all(px(0.)),
|
|
||||||
},
|
|
||||||
Size::Large => match self {
|
|
||||||
TabVariant::Underline => Edges {
|
|
||||||
top: px(5.),
|
|
||||||
bottom: px(6.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
_ => Edges::all(px(0.)),
|
|
||||||
},
|
|
||||||
_ => match self {
|
|
||||||
TabVariant::Underline => Edges {
|
|
||||||
top: px(3.),
|
|
||||||
bottom: px(4.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
_ => Edges::all(px(0.)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn normal(&self, cx: &App) -> TabStyle {
|
|
||||||
match self {
|
|
||||||
TabVariant::Tab => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges {
|
|
||||||
left: px(1.),
|
|
||||||
right: px(1.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Outline => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges::all(px(1.)),
|
|
||||||
border_color: cx.theme().border,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Pill => TabStyle {
|
|
||||||
fg: cx.theme().text,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Segmented => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Underline => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
inner_bg: gpui::transparent_black(),
|
|
||||||
borders: Edges {
|
|
||||||
bottom: px(2.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hovered(&self, selected: bool, cx: &App) -> TabStyle {
|
|
||||||
match self {
|
|
||||||
TabVariant::Tab => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges {
|
|
||||||
left: px(1.),
|
|
||||||
right: px(1.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Outline => TabStyle {
|
|
||||||
fg: cx.theme().secondary_foreground,
|
|
||||||
bg: cx.theme().secondary_hover,
|
|
||||||
borders: Edges::all(px(1.)),
|
|
||||||
border_color: cx.theme().border,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Pill => TabStyle {
|
|
||||||
fg: cx.theme().secondary_foreground,
|
|
||||||
bg: cx.theme().secondary_background,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Segmented => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
inner_bg: if selected {
|
|
||||||
cx.theme().background
|
|
||||||
} else {
|
|
||||||
gpui::transparent_black()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Underline => TabStyle {
|
|
||||||
fg: cx.theme().tab_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
inner_bg: gpui::transparent_black(),
|
|
||||||
borders: Edges {
|
|
||||||
bottom: px(2.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: gpui::transparent_black(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selected(&self, cx: &App) -> TabStyle {
|
|
||||||
match self {
|
|
||||||
TabVariant::Tab => TabStyle {
|
|
||||||
fg: cx.theme().tab_active_foreground,
|
|
||||||
bg: cx.theme().tab_active_background,
|
|
||||||
borders: Edges {
|
|
||||||
left: px(1.),
|
|
||||||
right: px(1.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: cx.theme().border,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Outline => TabStyle {
|
|
||||||
fg: cx.theme().text_accent,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges::all(px(1.)),
|
|
||||||
border_color: cx.theme().element_active,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Pill => TabStyle {
|
|
||||||
fg: cx.theme().element_foreground,
|
|
||||||
bg: cx.theme().element_background,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Segmented => TabStyle {
|
|
||||||
fg: cx.theme().tab_active_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
inner_bg: cx.theme().background,
|
|
||||||
shadow: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Underline => TabStyle {
|
|
||||||
fg: cx.theme().tab_active_foreground,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges {
|
|
||||||
bottom: px(2.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
border_color: cx.theme().element_active,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn disabled(&self, selected: bool, cx: &App) -> TabStyle {
|
|
||||||
match self {
|
|
||||||
TabVariant::Tab => TabStyle {
|
|
||||||
fg: cx.theme().text_muted,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
border_color: if selected {
|
|
||||||
cx.theme().border
|
|
||||||
} else {
|
|
||||||
gpui::transparent_black()
|
|
||||||
},
|
|
||||||
borders: Edges {
|
|
||||||
left: px(1.),
|
|
||||||
right: px(1.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Outline => TabStyle {
|
|
||||||
fg: cx.theme().text_muted,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
borders: Edges::all(px(1.)),
|
|
||||||
border_color: if selected {
|
|
||||||
cx.theme().element_active
|
|
||||||
} else {
|
|
||||||
cx.theme().border
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Pill => TabStyle {
|
|
||||||
fg: if selected {
|
|
||||||
cx.theme().element_foreground.opacity(0.5)
|
|
||||||
} else {
|
|
||||||
cx.theme().text_muted
|
|
||||||
},
|
|
||||||
bg: if selected {
|
|
||||||
cx.theme().element_background.opacity(0.5)
|
|
||||||
} else {
|
|
||||||
gpui::transparent_black()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Segmented => TabStyle {
|
|
||||||
fg: cx.theme().text_muted,
|
|
||||||
bg: cx.theme().tab_background,
|
|
||||||
inner_bg: if selected {
|
|
||||||
cx.theme().background
|
|
||||||
} else {
|
|
||||||
gpui::transparent_black()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
TabVariant::Underline => TabStyle {
|
|
||||||
fg: cx.theme().text_muted,
|
|
||||||
bg: gpui::transparent_black(),
|
|
||||||
border_color: if selected {
|
|
||||||
cx.theme().border
|
|
||||||
} else {
|
|
||||||
gpui::transparent_black()
|
|
||||||
},
|
|
||||||
borders: Edges {
|
|
||||||
bottom: px(2.),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn tab_bar_radius(&self, size: Size, cx: &App) -> Pixels {
|
|
||||||
if *self != TabVariant::Segmented {
|
|
||||||
return px(0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
match size {
|
|
||||||
Size::XSmall | Size::Small => cx.theme().radius,
|
|
||||||
Size::Large => cx.theme().radius_lg,
|
|
||||||
_ => cx.theme().radius_lg,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn radius(&self, size: Size, cx: &App) -> Pixels {
|
|
||||||
match self {
|
|
||||||
TabVariant::Outline | TabVariant::Pill => px(99.),
|
|
||||||
TabVariant::Segmented => match size {
|
|
||||||
Size::XSmall | Size::Small => cx.theme().radius,
|
|
||||||
Size::Large => cx.theme().radius_lg,
|
|
||||||
_ => cx.theme().radius_lg,
|
|
||||||
},
|
|
||||||
_ => px(0.),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner_radius(&self, size: Size, cx: &App) -> Pixels {
|
|
||||||
match self {
|
|
||||||
TabVariant::Segmented => match size {
|
|
||||||
Size::Large => self.tab_bar_radius(size, cx) - px(3.),
|
|
||||||
_ => self.tab_bar_radius(size, cx) - px(2.),
|
|
||||||
},
|
|
||||||
_ => px(0.),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
struct TabStyle {
|
|
||||||
borders: Edges<Pixels>,
|
|
||||||
border_color: Hsla,
|
|
||||||
bg: Hsla,
|
|
||||||
fg: Hsla,
|
|
||||||
shadow: bool,
|
|
||||||
inner_bg: Hsla,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TabStyle {
|
|
||||||
fn default() -> Self {
|
|
||||||
TabStyle {
|
|
||||||
borders: Edges::all(px(0.)),
|
|
||||||
border_color: gpui::transparent_white(),
|
|
||||||
bg: gpui::transparent_white(),
|
|
||||||
fg: gpui::transparent_white(),
|
|
||||||
shadow: false,
|
|
||||||
inner_bg: gpui::transparent_white(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
/// A Tab element for the [`super::TabBar`].
|
/// A Tab element for the [`super::TabBar`].
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
@@ -404,8 +23,6 @@ pub struct Tab {
|
|||||||
pub(super) tab_bar_prefix: Option<bool>,
|
pub(super) tab_bar_prefix: Option<bool>,
|
||||||
suffix: Option<AnyElement>,
|
suffix: Option<AnyElement>,
|
||||||
children: Vec<AnyElement>,
|
children: Vec<AnyElement>,
|
||||||
variant: TabVariant,
|
|
||||||
size: Size,
|
|
||||||
pub(super) disabled: bool,
|
pub(super) disabled: bool,
|
||||||
pub(super) selected: bool,
|
pub(super) selected: bool,
|
||||||
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut Window, &mut App) + 'static>>,
|
||||||
@@ -454,8 +71,6 @@ impl Default for Tab {
|
|||||||
selected: false,
|
selected: false,
|
||||||
prefix: None,
|
prefix: None,
|
||||||
suffix: None,
|
suffix: None,
|
||||||
variant: TabVariant::default(),
|
|
||||||
size: Size::default(),
|
|
||||||
on_click: None,
|
on_click: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,36 +94,6 @@ impl Tab {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set Tab Variant.
|
|
||||||
pub fn with_variant(mut self, variant: TabVariant) -> Self {
|
|
||||||
self.variant = variant;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use Pill variant.
|
|
||||||
pub fn pill(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Pill;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use outline variant.
|
|
||||||
pub fn outline(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Outline;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use Segmented variant.
|
|
||||||
pub fn segmented(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Segmented;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use Underline variant.
|
|
||||||
pub fn underline(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Underline;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the left side of the tab
|
/// Set the left side of the tab
|
||||||
pub fn prefix(mut self, prefix: impl IntoElement) -> Self {
|
pub fn prefix(mut self, prefix: impl IntoElement) -> Self {
|
||||||
self.prefix = Some(prefix.into_any_element());
|
self.prefix = Some(prefix.into_any_element());
|
||||||
@@ -580,42 +165,16 @@ impl Styled for Tab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sizable for Tab {
|
|
||||||
fn with_size(mut self, size: impl Into<Size>) -> Self {
|
|
||||||
self.size = size.into();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderOnce for Tab {
|
impl RenderOnce for Tab {
|
||||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
||||||
let mut tab_style = if self.selected {
|
let fg = if self.disabled {
|
||||||
self.variant.selected(cx)
|
cx.theme().text_muted
|
||||||
|
} else if self.selected {
|
||||||
|
cx.theme().tab_active_foreground
|
||||||
} else {
|
} else {
|
||||||
self.variant.normal(cx)
|
cx.theme().tab_foreground
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut hover_style = self.variant.hovered(self.selected, cx);
|
|
||||||
|
|
||||||
if self.disabled {
|
|
||||||
tab_style = self.variant.disabled(self.selected, cx);
|
|
||||||
hover_style = self.variant.disabled(self.selected, cx);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tab_bar_prefix = self.tab_bar_prefix.unwrap_or_default();
|
|
||||||
|
|
||||||
if !tab_bar_prefix && self.ix == 0 && self.variant == TabVariant::Tab {
|
|
||||||
tab_style.borders.left = px(0.);
|
|
||||||
hover_style.borders.left = px(0.);
|
|
||||||
}
|
|
||||||
|
|
||||||
let radius = self.variant.radius(self.size, cx);
|
|
||||||
let inner_radius = self.variant.inner_radius(self.size, cx);
|
|
||||||
let inner_paddings = self.variant.inner_paddings(self.size);
|
|
||||||
let inner_margins = self.variant.inner_margins(self.size);
|
|
||||||
let inner_height = self.variant.inner_height(self.size);
|
|
||||||
let height = self.variant.height(self.size);
|
|
||||||
|
|
||||||
self.base
|
self.base
|
||||||
.id(self.ix)
|
.id(self.ix)
|
||||||
.flex()
|
.flex()
|
||||||
@@ -623,74 +182,39 @@ impl RenderOnce for Tab {
|
|||||||
.gap_1()
|
.gap_1()
|
||||||
.items_center()
|
.items_center()
|
||||||
.flex_shrink_0()
|
.flex_shrink_0()
|
||||||
.h(height)
|
.h(TABBAR_HEIGHT)
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.text_color(tab_style.fg)
|
.text_color(fg)
|
||||||
.map(|this| match self.size {
|
.text_sm()
|
||||||
Size::XSmall => this.text_xs(),
|
|
||||||
Size::Large => this.text_base(),
|
|
||||||
_ => this.text_sm(),
|
|
||||||
})
|
|
||||||
.bg(tab_style.bg)
|
|
||||||
.border_l(tab_style.borders.left)
|
|
||||||
.border_r(tab_style.borders.right)
|
|
||||||
.border_t(tab_style.borders.top)
|
|
||||||
.border_b(tab_style.borders.bottom)
|
|
||||||
.border_color(tab_style.border_color)
|
|
||||||
.rounded(radius)
|
|
||||||
.when(!self.selected && !self.disabled, |this| {
|
.when(!self.selected && !self.disabled, |this| {
|
||||||
this.hover(|this| {
|
this.hover(|this| this.text_color(cx.theme().secondary_foreground))
|
||||||
this.text_color(hover_style.fg)
|
|
||||||
.bg(hover_style.bg)
|
|
||||||
.border_l(hover_style.borders.left)
|
|
||||||
.border_r(hover_style.borders.right)
|
|
||||||
.border_t(hover_style.borders.top)
|
|
||||||
.border_b(hover_style.borders.bottom)
|
|
||||||
.border_color(hover_style.border_color)
|
|
||||||
.rounded(radius)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.when_some(self.prefix, |this, prefix| this.child(prefix))
|
.when_some(self.prefix, |this, prefix| this.child(prefix))
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
.h(inner_height)
|
.h(px(30.))
|
||||||
.line_height(relative(1.))
|
.line_height(relative(1.))
|
||||||
.whitespace_nowrap()
|
.whitespace_nowrap()
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.margins(inner_margins)
|
|
||||||
.flex_shrink_0()
|
.flex_shrink_0()
|
||||||
|
.px_3()
|
||||||
.map(|this| match self.icon {
|
.map(|this| match self.icon {
|
||||||
Some(icon) => {
|
Some(icon) => this.w(px(38.)).child(icon.size_4()),
|
||||||
this.w(inner_height * 1.25)
|
|
||||||
.child(icon.map(|this| match self.size {
|
|
||||||
Size::XSmall => this.size_2p5(),
|
|
||||||
Size::Small => this.size_3p5(),
|
|
||||||
Size::Large => this.size_4(),
|
|
||||||
_ => this.size_4(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
None => this
|
None => this
|
||||||
.paddings(inner_paddings)
|
|
||||||
.map(|this| match self.label {
|
.map(|this| match self.label {
|
||||||
Some(label) => this.child(label),
|
Some(label) => this.child(label),
|
||||||
None => this,
|
None => this,
|
||||||
})
|
})
|
||||||
.children(self.children),
|
.children(self.children),
|
||||||
})
|
}),
|
||||||
.bg(tab_style.inner_bg)
|
|
||||||
.rounded(inner_radius)
|
|
||||||
.when(tab_style.shadow, |this| this.shadow_xs())
|
|
||||||
.hover(|this| this.bg(hover_style.inner_bg).rounded(inner_radius)),
|
|
||||||
)
|
)
|
||||||
.when_some(self.suffix, |this, suffix| {
|
.when_some(self.suffix, |this, suffix| {
|
||||||
this.child(div().pr_2().child(suffix))
|
this.child(div().pr_2().child(suffix))
|
||||||
})
|
})
|
||||||
.on_mouse_down(MouseButton::Left, |_, _, cx| {
|
.on_mouse_down(MouseButton::Left, |_ev, _window, cx| {
|
||||||
// Stop propagation behavior, for works on TitleBar.
|
|
||||||
// https://github.com/longbridge/gpui-component/issues/1836
|
|
||||||
cx.stop_propagation();
|
cx.stop_propagation();
|
||||||
})
|
})
|
||||||
.when(!self.disabled, |this| {
|
.when(!self.disabled, |this| {
|
||||||
|
|||||||
@@ -2,19 +2,17 @@ use std::rc::Rc;
|
|||||||
|
|
||||||
use gpui::prelude::FluentBuilder as _;
|
use gpui::prelude::FluentBuilder as _;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Anchor, AnyElement, App, Div, Edges, ElementId, InteractiveElement, IntoElement, ParentElement,
|
Anchor, AnyElement, App, Div, ElementId, InteractiveElement, IntoElement, ParentElement,
|
||||||
RenderOnce, ScrollHandle, Stateful, StatefulInteractiveElement as _, StyleRefinement, Styled,
|
RenderOnce, ScrollHandle, Stateful, StatefulInteractiveElement as _, StyleRefinement, Styled,
|
||||||
Window, div, px,
|
Window, div, px,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use theme::ActiveTheme;
|
|
||||||
|
|
||||||
use super::{Tab, TabVariant};
|
use super::Tab;
|
||||||
use crate::button::{Button, ButtonVariants as _};
|
use crate::button::{Button, ButtonVariants as _};
|
||||||
use crate::menu::{DropdownMenu as _, PopupMenuItem};
|
use crate::menu::{DropdownMenu as _, PopupMenuItem};
|
||||||
use crate::{IconName, Selectable, Sizable, Size, StyledExt, h_flex};
|
use crate::{IconName, Selectable, Sizable, StyledExt, h_flex};
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
|
||||||
/// A TabBar element that contains multiple [`Tab`] items.
|
/// A TabBar element that contains multiple [`Tab`] items.
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct TabBar {
|
pub struct TabBar {
|
||||||
@@ -26,9 +24,8 @@ pub struct TabBar {
|
|||||||
children: SmallVec<[Tab; 2]>,
|
children: SmallVec<[Tab; 2]>,
|
||||||
last_empty_space: AnyElement,
|
last_empty_space: AnyElement,
|
||||||
selected_index: Option<usize>,
|
selected_index: Option<usize>,
|
||||||
variant: TabVariant,
|
|
||||||
size: Size,
|
|
||||||
menu: bool,
|
menu: bool,
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
on_click: Option<Rc<dyn Fn(&usize, &mut Window, &mut App) + 'static>>,
|
on_click: Option<Rc<dyn Fn(&usize, &mut Window, &mut App) + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +39,6 @@ impl TabBar {
|
|||||||
scroll_handle: None,
|
scroll_handle: None,
|
||||||
prefix: None,
|
prefix: None,
|
||||||
suffix: None,
|
suffix: None,
|
||||||
variant: TabVariant::default(),
|
|
||||||
size: Size::default(),
|
|
||||||
last_empty_space: div().w_3().into_any_element(),
|
last_empty_space: div().w_3().into_any_element(),
|
||||||
selected_index: None,
|
selected_index: None,
|
||||||
on_click: None,
|
on_click: None,
|
||||||
@@ -51,36 +46,6 @@ impl TabBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the Tab variant, all children will inherit the variant.
|
|
||||||
pub fn with_variant(mut self, variant: TabVariant) -> Self {
|
|
||||||
self.variant = variant;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the Tab variant to Pill, all children will inherit the variant.
|
|
||||||
pub fn pill(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Pill;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the Tab variant to Outline, all children will inherit the variant.
|
|
||||||
pub fn outline(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Outline;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the Tab variant to Segmented, all children will inherit the variant.
|
|
||||||
pub fn segmented(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Segmented;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the Tab variant to Underline, all children will inherit the variant.
|
|
||||||
pub fn underline(mut self) -> Self {
|
|
||||||
self.variant = TabVariant::Underline;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether to show the menu button when tabs overflow, default is false.
|
/// Set whether to show the menu button when tabs overflow, default is false.
|
||||||
pub fn menu(mut self, menu: bool) -> Self {
|
pub fn menu(mut self, menu: bool) -> Self {
|
||||||
self.menu = menu;
|
self.menu = menu;
|
||||||
@@ -105,13 +70,13 @@ impl TabBar {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add children of the TabBar, all children will inherit the variant.
|
/// Add children of the TabBar.
|
||||||
pub fn children(mut self, children: impl IntoIterator<Item = impl Into<Tab>>) -> Self {
|
pub fn children(mut self, children: impl IntoIterator<Item = impl Into<Tab>>) -> Self {
|
||||||
self.children.extend(children.into_iter().map(Into::into));
|
self.children.extend(children.into_iter().map(Into::into));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add child of the TabBar, tab will inherit the variant.
|
/// Add child of the TabBar.
|
||||||
pub fn child(mut self, child: impl Into<Tab>) -> Self {
|
pub fn child(mut self, child: impl Into<Tab>) -> Self {
|
||||||
self.children.push(child.into());
|
self.children.push(child.into());
|
||||||
self
|
self
|
||||||
@@ -147,60 +112,8 @@ impl Styled for TabBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sizable for TabBar {
|
|
||||||
fn with_size(mut self, size: impl Into<Size>) -> Self {
|
|
||||||
self.size = size.into();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderOnce for TabBar {
|
impl RenderOnce for TabBar {
|
||||||
fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement {
|
fn render(self, _: &mut Window, _cx: &mut App) -> impl IntoElement {
|
||||||
let default_gap = match self.size {
|
|
||||||
Size::Small | Size::XSmall => px(8.),
|
|
||||||
Size::Large => px(16.),
|
|
||||||
_ => px(12.),
|
|
||||||
};
|
|
||||||
let (bg, paddings, gap) = match self.variant {
|
|
||||||
TabVariant::Tab => {
|
|
||||||
let padding = Edges::all(px(0.));
|
|
||||||
(cx.theme().tab_background, padding, px(0.))
|
|
||||||
}
|
|
||||||
TabVariant::Outline => {
|
|
||||||
let padding = Edges::all(px(0.));
|
|
||||||
(gpui::transparent_black(), padding, default_gap)
|
|
||||||
}
|
|
||||||
TabVariant::Pill => {
|
|
||||||
let padding = Edges::all(px(0.));
|
|
||||||
(gpui::transparent_black(), padding, px(4.))
|
|
||||||
}
|
|
||||||
TabVariant::Segmented => {
|
|
||||||
let padding_x = match self.size {
|
|
||||||
Size::XSmall => px(2.),
|
|
||||||
Size::Small => px(3.),
|
|
||||||
_ => px(4.),
|
|
||||||
};
|
|
||||||
let padding = Edges {
|
|
||||||
left: padding_x,
|
|
||||||
right: padding_x,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
(cx.theme().tab_background, padding, px(2.))
|
|
||||||
}
|
|
||||||
TabVariant::Underline => {
|
|
||||||
// This gap is same as the tab inner_paddings
|
|
||||||
let gap = match self.size {
|
|
||||||
Size::XSmall => px(10.),
|
|
||||||
Size::Small => px(12.),
|
|
||||||
Size::Large => px(20.),
|
|
||||||
_ => px(16.),
|
|
||||||
};
|
|
||||||
|
|
||||||
(gpui::transparent_black(), Edges::all(px(0.)), gap)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut item_labels = Vec::new();
|
let mut item_labels = Vec::new();
|
||||||
let selected_index = self.selected_index;
|
let selected_index = self.selected_index;
|
||||||
let on_click = self.on_click.clone();
|
let on_click = self.on_click.clone();
|
||||||
@@ -210,25 +123,6 @@ impl RenderOnce for TabBar {
|
|||||||
.relative()
|
.relative()
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.bg(bg)
|
|
||||||
.text_color(cx.theme().tab_foreground)
|
|
||||||
.when(
|
|
||||||
self.variant == TabVariant::Underline || self.variant == TabVariant::Tab,
|
|
||||||
|this| {
|
|
||||||
this.child(
|
|
||||||
div()
|
|
||||||
.id("border-b")
|
|
||||||
.absolute()
|
|
||||||
.left_0()
|
|
||||||
.bottom_0()
|
|
||||||
.size_full()
|
|
||||||
.border_b_1()
|
|
||||||
.border_color(cx.theme().border),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.rounded(self.variant.tab_bar_radius(self.size, cx))
|
|
||||||
.paddings(paddings)
|
|
||||||
.refine_style(&self.style)
|
.refine_style(&self.style)
|
||||||
.when_some(self.prefix, |this, prefix| this.child(prefix))
|
.when_some(self.prefix, |this, prefix| this.child(prefix))
|
||||||
.child(
|
.child(
|
||||||
@@ -239,15 +133,13 @@ impl RenderOnce for TabBar {
|
|||||||
.when_some(self.scroll_handle, |this, scroll_handle| {
|
.when_some(self.scroll_handle, |this, scroll_handle| {
|
||||||
this.track_scroll(&scroll_handle)
|
this.track_scroll(&scroll_handle)
|
||||||
})
|
})
|
||||||
.gap(gap)
|
.gap(px(0.))
|
||||||
.children(self.children.into_iter().enumerate().map(|(ix, child)| {
|
.children(self.children.into_iter().enumerate().map(|(ix, child)| {
|
||||||
item_labels.push((child.label.clone(), child.disabled));
|
item_labels.push((child.label.clone(), child.disabled));
|
||||||
let tab_bar_prefix = child.tab_bar_prefix.unwrap_or(true);
|
let tab_bar_prefix = child.tab_bar_prefix.unwrap_or(true);
|
||||||
child
|
child
|
||||||
.ix(ix)
|
.ix(ix)
|
||||||
.tab_bar_prefix(tab_bar_prefix)
|
.tab_bar_prefix(tab_bar_prefix)
|
||||||
.with_variant(self.variant)
|
|
||||||
.with_size(self.size)
|
|
||||||
.when_some(self.selected_index, |this, selected_ix| {
|
.when_some(self.selected_index, |this, selected_ix| {
|
||||||
this.selected(selected_ix == ix)
|
this.selected(selected_ix == ix)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -283,8 +283,6 @@ impl RenderOnce for TitleBar {
|
|||||||
this.px_2()
|
this.px_2()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.border_b_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.bg(cx.theme().title_bar)
|
.bg(cx.theme().title_bar)
|
||||||
.refine_style(&self.style)
|
.refine_style(&self.style)
|
||||||
.when(is_linux, |this| {
|
.when(is_linux, |this| {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::{Error, anyhow};
|
use anyhow::{Error, anyhow};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||||
Subscription, Task, Window, div,
|
Subscription, Task, Window, div,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_connect::prelude::*;
|
use nostr_connect::prelude::*;
|
||||||
use state::{CoopAuthUrlHandler, NostrRegistry, USER_KEYRING};
|
use state::{CoopAuthUrlHandler, NostrRegistry, USER_KEYRING};
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
@@ -36,7 +35,7 @@ pub struct ImportIdentity {
|
|||||||
|
|
||||||
impl ImportIdentity {
|
impl ImportIdentity {
|
||||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||||
let key_input = cx.new(|cx| InputState::new(window, cx));
|
let key_input = cx.new(|cx| InputState::new(window, cx).placeholder("nsec or bunker://"));
|
||||||
let pass_input = cx.new(|cx| InputState::new(window, cx).masked(true));
|
let pass_input = cx.new(|cx| InputState::new(window, cx).masked(true));
|
||||||
let error = cx.new(|_| None);
|
let error = cx.new(|_| None);
|
||||||
|
|
||||||
@@ -135,7 +134,6 @@ impl ImportIdentity {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -208,6 +206,10 @@ impl Render for ImportIdentity {
|
|||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
.size_full()
|
.size_full()
|
||||||
|
.gap_4()
|
||||||
|
.text_sm()
|
||||||
|
.child(
|
||||||
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -228,20 +230,21 @@ impl Render for ImportIdentity {
|
|||||||
.when(key_warning, |this| {
|
.when(key_warning, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
div()
|
div()
|
||||||
.v_flex()
|
|
||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().text_warning)
|
.text_color(cx.theme().text_warning)
|
||||||
.child(div().font_semibold().child("Warning"))
|
.child(div().font_semibold().child("Warning"))
|
||||||
.child(div().child(MSG)),
|
.child(div().child(MSG)),
|
||||||
)
|
)
|
||||||
})
|
}),
|
||||||
|
)
|
||||||
.child(
|
.child(
|
||||||
Button::new("login")
|
Button::new("login")
|
||||||
.label("Continue")
|
.label("Continue")
|
||||||
.primary()
|
.primary()
|
||||||
|
.font_semibold()
|
||||||
.loading(self.loading)
|
.loading(self.loading)
|
||||||
.disabled(self.loading)
|
.disabled(self.loading)
|
||||||
.on_click(cx.listener(move |this, _, window, cx| {
|
.on_click(cx.listener(move |this, _ev, window, cx| {
|
||||||
this.login(window, cx);
|
this.login(window, cx);
|
||||||
})),
|
})),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use crate::dialogs::import::ImportIdentity;
|
|||||||
use crate::dialogs::restore::RestoreEncryption;
|
use crate::dialogs::restore::RestoreEncryption;
|
||||||
use crate::dialogs::settings;
|
use crate::dialogs::settings;
|
||||||
use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list, trash};
|
use crate::panels::{backup, contact_list, greeter, messaging_relays, profile, relay_list, trash};
|
||||||
|
use crate::sidebar::Sidebar;
|
||||||
|
|
||||||
mod dialogs;
|
mod dialogs;
|
||||||
mod panels;
|
mod panels;
|
||||||
@@ -60,6 +61,7 @@ enum Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Workspace {
|
pub struct Workspace {
|
||||||
|
sidebar: Entity<Sidebar>,
|
||||||
/// App's Dock Area
|
/// App's Dock Area
|
||||||
dock: Entity<DockArea>,
|
dock: Entity<DockArea>,
|
||||||
|
|
||||||
@@ -79,14 +81,10 @@ impl Workspace {
|
|||||||
let device = DeviceRegistry::global(cx);
|
let device = DeviceRegistry::global(cx);
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
|
|
||||||
let dock = cx.new(|cx| {
|
let sidebar = cx.new(|cx| Sidebar::new(window, cx));
|
||||||
let mut this = DockArea::new(window, cx);
|
let dock = cx.new(|cx| DockArea::new(window, cx));
|
||||||
let left = DockItem::panel(Arc::new(sidebar::init(window, cx)));
|
|
||||||
this.set_left_dock(left, Some(SIDEBAR_WIDTH), true, window, cx);
|
|
||||||
this
|
|
||||||
});
|
|
||||||
|
|
||||||
let image_cache = CoopImageCache::new(IMAGE_CACHE_SIZE, cx);
|
let image_cache = CoopImageCache::new(IMAGE_CACHE_SIZE, cx);
|
||||||
|
|
||||||
let mut subscriptions = smallvec![];
|
let mut subscriptions = smallvec![];
|
||||||
|
|
||||||
subscriptions.push(
|
subscriptions.push(
|
||||||
@@ -245,6 +243,7 @@ impl Workspace {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
sidebar,
|
||||||
dock,
|
dock,
|
||||||
image_cache,
|
image_cache,
|
||||||
tasks: vec![],
|
tasks: vec![],
|
||||||
@@ -826,9 +825,20 @@ impl Render for Workspace {
|
|||||||
.child(self.titlebar_left(cx))
|
.child(self.titlebar_left(cx))
|
||||||
.child(self.titlebar_right(cx)),
|
.child(self.titlebar_right(cx)),
|
||||||
)
|
)
|
||||||
// Dock
|
// Main
|
||||||
|
.child(
|
||||||
|
h_flex()
|
||||||
|
.size_full()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.flex_shrink_0()
|
||||||
|
.h_full()
|
||||||
|
.w(SIDEBAR_WIDTH)
|
||||||
|
.child(self.sidebar.clone()),
|
||||||
|
)
|
||||||
.child(self.dock.clone()),
|
.child(self.dock.clone()),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
// Notifications
|
// Notifications
|
||||||
.children(notification_layer)
|
.children(notification_layer)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||||
Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, div,
|
Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, div,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use state::USER_KEYRING;
|
use state::USER_KEYRING;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
@@ -155,12 +154,7 @@ impl Render for BackupPanel {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("Public Key:")),
|
.child(SharedString::from("Public Key:")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(Input::new(&self.npub_input).small().disabled(true)),
|
||||||
Input::new(&self.npub_input)
|
|
||||||
.small()
|
|
||||||
.bordered(false)
|
|
||||||
.disabled(true),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -173,12 +167,7 @@ impl Render for BackupPanel {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("Secret Key:")),
|
.child(SharedString::from("Secret Key:")),
|
||||||
)
|
)
|
||||||
.child(
|
.child(Input::new(&self.nsec_input).small().disabled(true)),
|
||||||
Input::new(&self.nsec_input)
|
|
||||||
.small()
|
|
||||||
.bordered(false)
|
|
||||||
.disabled(true),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
Button::new("copy")
|
Button::new("copy")
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
@@ -8,6 +7,7 @@ use gpui::{
|
|||||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||||
Task, TextAlign, Window, div, rems,
|
Task, TextAlign, Window, div, rems,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use person::PersonRegistry;
|
use person::PersonRegistry;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
@@ -303,12 +303,7 @@ impl Render for ContactListPanel {
|
|||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.w_full()
|
.w_full()
|
||||||
.child(
|
.child(Input::new(&self.input).small().cleanable(true))
|
||||||
Input::new(&self.input)
|
|
||||||
.small()
|
|
||||||
.bordered(false)
|
|
||||||
.cleanable(true),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Button::new("add")
|
Button::new("add")
|
||||||
.icon(IconName::Plus)
|
.icon(IconName::Plus)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::{Error, anyhow};
|
use anyhow::{Error, anyhow};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
@@ -8,6 +7,7 @@ use gpui::{
|
|||||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||||
Task, TextAlign, Window, div, rems,
|
Task, TextAlign, Window, div, rems,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use state::NostrRegistry;
|
use state::NostrRegistry;
|
||||||
@@ -320,12 +320,7 @@ impl Render for MessagingRelayPanel {
|
|||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.w_full()
|
.w_full()
|
||||||
.child(
|
.child(Input::new(&self.input).small().cleanable(true))
|
||||||
Input::new(&self.input)
|
|
||||||
.small()
|
|
||||||
.bordered(false)
|
|
||||||
.cleanable(true),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Button::new("add")
|
Button::new("add")
|
||||||
.icon(IconName::Plus)
|
.icon(IconName::Plus)
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ impl Render for ProfilePanel {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("What should people call you?")),
|
.child(SharedString::from("What should people call you?")),
|
||||||
)
|
)
|
||||||
.child(Input::new(&self.name_input).bordered(false).small()),
|
.child(Input::new(&self.name_input).small()),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -364,7 +364,7 @@ impl Render for ProfilePanel {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("A short introduction about you:")),
|
.child(SharedString::from("A short introduction about you:")),
|
||||||
)
|
)
|
||||||
.child(Input::new(&self.bio_input).bordered(false).small()),
|
.child(Input::new(&self.bio_input).small()),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
@@ -375,7 +375,7 @@ impl Render for ProfilePanel {
|
|||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("Website:")),
|
.child(SharedString::from("Website:")),
|
||||||
)
|
)
|
||||||
.child(Input::new(&self.website_input).bordered(false).small()),
|
.child(Input::new(&self.website_input).small()),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::{Error, anyhow};
|
use anyhow::{Error, anyhow};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
@@ -8,6 +7,7 @@ use gpui::{
|
|||||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||||
Task, TextAlign, Window, div, px, rems,
|
Task, TextAlign, Window, div, px, rems,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
@@ -371,12 +371,7 @@ impl Render for RelayListPanel {
|
|||||||
h_flex()
|
h_flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.w_full()
|
.w_full()
|
||||||
.child(
|
.child(Input::new(&self.input).small().cleanable(true))
|
||||||
Input::new(&self.input)
|
|
||||||
.small()
|
|
||||||
.bordered(false)
|
|
||||||
.cleanable(true),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
Button::new("metadata")
|
Button::new("metadata")
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use chat::{ChatEvent, ChatRegistry, Room, RoomKind};
|
use chat::{ChatEvent, ChatRegistry, Room, RoomKind};
|
||||||
@@ -12,11 +11,12 @@ use gpui::{
|
|||||||
ParentElement, Render, SharedString, Styled, Subscription, Task, UniformListScrollHandle,
|
ParentElement, Render, SharedString, Styled, Subscription, Task, UniformListScrollHandle,
|
||||||
Window, div, uniform_list,
|
Window, div, uniform_list,
|
||||||
};
|
};
|
||||||
|
use instant::Duration;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use person::PersonRegistry;
|
use person::PersonRegistry;
|
||||||
use smallvec::{SmallVec, smallvec};
|
use smallvec::{SmallVec, smallvec};
|
||||||
use state::{FIND_DELAY, IMAGE_CACHE_SIZE, NostrRegistry};
|
use state::{FIND_DELAY, IMAGE_CACHE_SIZE, NostrRegistry};
|
||||||
use theme::{ActiveTheme, SIDEBAR_WIDTH, TABBAR_HEIGHT};
|
use theme::{ActiveTheme, SIDEBAR_WIDTH};
|
||||||
use ui::button::{Button, ButtonVariants};
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock::{Panel, PanelEvent};
|
use ui::dock::{Panel, PanelEvent};
|
||||||
use ui::indicator::Indicator;
|
use ui::indicator::Indicator;
|
||||||
@@ -29,13 +29,8 @@ mod entry;
|
|||||||
|
|
||||||
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<Sidebar> {
|
|
||||||
cx.new(|cx| Sidebar::new(window, cx))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sidebar.
|
/// Sidebar.
|
||||||
pub struct Sidebar {
|
pub struct Sidebar {
|
||||||
name: SharedString,
|
|
||||||
focus_handle: FocusHandle,
|
focus_handle: FocusHandle,
|
||||||
scroll_handle: UniformListScrollHandle,
|
scroll_handle: UniformListScrollHandle,
|
||||||
|
|
||||||
@@ -80,7 +75,7 @@ pub struct Sidebar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Sidebar {
|
impl Sidebar {
|
||||||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let filter = cx.new(|_| RoomKind::Ongoing);
|
let filter = cx.new(|_| RoomKind::Ongoing);
|
||||||
let contact_list = cx.new(|_| None);
|
let contact_list = cx.new(|_| None);
|
||||||
@@ -135,7 +130,6 @@ impl Sidebar {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
name: "Sidebar".into(),
|
|
||||||
focus_handle: cx.focus_handle(),
|
focus_handle: cx.focus_handle(),
|
||||||
scroll_handle: UniformListScrollHandle::new(),
|
scroll_handle: UniformListScrollHandle::new(),
|
||||||
find_input,
|
find_input,
|
||||||
@@ -474,7 +468,7 @@ impl Sidebar {
|
|||||||
|
|
||||||
impl Panel for Sidebar {
|
impl Panel for Sidebar {
|
||||||
fn panel_id(&self) -> SharedString {
|
fn panel_id(&self) -> SharedString {
|
||||||
self.name.clone()
|
"Sidebar".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,8 +482,11 @@ 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 nostr = NostrRegistry::global(cx);
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let loading = chat.read(cx).loading();
|
let logged_in = nostr.read(cx).current_user().is_some();
|
||||||
|
let loading = chat.read(cx).loading() && logged_in;
|
||||||
|
|
||||||
let total_rooms = chat.read(cx).count(self.filter.read(cx), cx);
|
let total_rooms = chat.read(cx).count(self.filter.read(cx), cx);
|
||||||
|
|
||||||
// Whether the find panel should be shown
|
// Whether the find panel should be shown
|
||||||
@@ -507,17 +504,11 @@ impl Render for Sidebar {
|
|||||||
.size_full()
|
.size_full()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex().px_2().child(
|
||||||
.h(TABBAR_HEIGHT)
|
|
||||||
.border_b_1()
|
|
||||||
.border_color(cx.theme().border)
|
|
||||||
.bg(cx.theme().tab_background)
|
|
||||||
.child(
|
|
||||||
Input::new(&self.find_input)
|
Input::new(&self.find_input)
|
||||||
.appearance(false)
|
|
||||||
.bordered(false)
|
|
||||||
.small()
|
.small()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
|
.disabled(loading)
|
||||||
.when(!self.find_input.read(cx).loading, |this| {
|
.when(!self.find_input.read(cx).loading, |this| {
|
||||||
this.suffix(
|
this.suffix(
|
||||||
Button::new("find-icon")
|
Button::new("find-icon")
|
||||||
@@ -608,17 +599,13 @@ impl Render for Sidebar {
|
|||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
.text_center()
|
.text_center()
|
||||||
|
.child(div().text_sm().font_semibold().child("No conversations"))
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.text_sm()
|
.text_xs()
|
||||||
.font_semibold()
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("No conversations")),
|
.child("Start a conversation with someone to get started."),
|
||||||
)
|
|
||||||
.child(div().text_xs().text_color(cx.theme().text_muted).child(
|
|
||||||
SharedString::from(
|
|
||||||
"Start a conversation with someone to get started.",
|
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -643,7 +630,7 @@ impl Render for Sidebar {
|
|||||||
.font_semibold()
|
.font_semibold()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(Icon::new(IconName::ChevronDown))
|
.child(Icon::new(IconName::ChevronDown))
|
||||||
.child(SharedString::from("Results")),
|
.child("Results"),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
uniform_list(
|
uniform_list(
|
||||||
@@ -748,7 +735,7 @@ impl Render for Sidebar {
|
|||||||
.font_semibold()
|
.font_semibold()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(Indicator::new().small().color(cx.theme().icon_accent))
|
.child(Indicator::new().small().color(cx.theme().icon_accent))
|
||||||
.child(SharedString::from("Getting messages...")),
|
.child("Getting messages..."),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ gpui_platform.workspace = true
|
|||||||
gpui_web = { git = "https://github.com/zed-industries/zed" }
|
gpui_web = { git = "https://github.com/zed-industries/zed" }
|
||||||
|
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
instant = { workspace = true, features = ["wasm-bindgen"] }
|
||||||
|
|
||||||
console_error_panic_hook = "0.1"
|
console_error_panic_hook = "0.1"
|
||||||
tracing-wasm = "0.2"
|
tracing-wasm = "0.2"
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
use gpui::*;
|
use gpui::*;
|
||||||
use ui::Root;
|
use ui::Root;
|
||||||
use universal_time::{
|
use universal_time::{Instant, MonotonicClock, SystemTime, WallClock, define_time_provider};
|
||||||
Duration, Instant, MonotonicClock, SystemTime, WallClock, define_time_provider,
|
|
||||||
};
|
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
struct CustomTimeProvider;
|
struct CustomTimeProvider;
|
||||||
|
|
||||||
impl WallClock for CustomTimeProvider {
|
impl WallClock for CustomTimeProvider {
|
||||||
fn system_time(&self) -> SystemTime {
|
fn system_time(&self) -> SystemTime {
|
||||||
SystemTime::from_unix_duration(Duration::from_secs(0))
|
SystemTime::from_unix_duration(instant::Duration::from_secs(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MonotonicClock for CustomTimeProvider {
|
impl MonotonicClock for CustomTimeProvider {
|
||||||
fn instant(&self) -> Instant {
|
fn instant(&self) -> Instant {
|
||||||
Instant::from_ticks(Duration::from_secs(0))
|
Instant::from_ticks(instant::Duration::from_secs(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,21 +32,7 @@ pub fn run() -> Result<(), JsValue> {
|
|||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
gpui_platform::web_init();
|
gpui_platform::web_init();
|
||||||
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
gpui_platform::application().run(|cx| {
|
||||||
let app = gpui_platform::application();
|
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
|
||||||
let app = {
|
|
||||||
let app = gpui_platform::single_threaded_web();
|
|
||||||
|
|
||||||
// Workaround: intentionally leak the `Rc<AppCell>` to keep the application alive
|
|
||||||
struct WasmApplication(std::rc::Rc<AppCell>);
|
|
||||||
let wasm_app = unsafe { std::mem::transmute::<Application, WasmApplication>(app) };
|
|
||||||
std::mem::forget(wasm_app.0.clone());
|
|
||||||
unsafe { std::mem::transmute::<WasmApplication, Application>(wasm_app) }
|
|
||||||
};
|
|
||||||
|
|
||||||
app.run(|cx| {
|
|
||||||
// Open the root window
|
// Open the root window
|
||||||
cx.open_window(WindowOptions::default(), |window, cx| {
|
cx.open_window(WindowOptions::default(), |window, cx| {
|
||||||
// Initialize components
|
// Initialize components
|
||||||
|
|||||||
Reference in New Issue
Block a user