chore: refactor account and fixes
This commit is contained in:
93
Cargo.lock
generated
93
Cargo.lock
generated
@@ -219,7 +219,7 @@ dependencies = [
|
||||
"enumflags2",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
"url",
|
||||
@@ -485,9 +485,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.28.0"
|
||||
version = "0.28.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f7720b74ed28ca77f90769a71fd8c637a0137f6fae4ae947e1050229cff57f"
|
||||
checksum = "0ddeb19ee86cb16ecfc871e5b0660aff6285760957aaedda6284cf0e790d3769"
|
||||
dependencies = [
|
||||
"bindgen 0.69.5",
|
||||
"cc",
|
||||
@@ -1015,9 +1015,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
|
||||
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -1025,9 +1025,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.36"
|
||||
version = "4.5.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
|
||||
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -1135,7 +1135,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "collections"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"rustc-hash 2.1.1",
|
||||
@@ -1524,7 +1524,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "derive_refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2306,7 +2306,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"as-raw-xcb-connection",
|
||||
@@ -2387,6 +2387,7 @@ dependencies = [
|
||||
"windows 0.61.1",
|
||||
"windows-core 0.61.0",
|
||||
"windows-numerics",
|
||||
"windows-registry 0.5.1",
|
||||
"workspace-hack",
|
||||
"x11-clipboard",
|
||||
"x11rb",
|
||||
@@ -2397,7 +2398,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gpui_macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2621,7 +2622,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -2638,7 +2639,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "http_client_tls"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"rustls",
|
||||
"rustls-platform-verifier",
|
||||
@@ -3197,7 +3198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3379,7 +3380,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "media"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bindgen 0.71.1",
|
||||
@@ -3577,7 +3578,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
||||
[[package]]
|
||||
name = "nostr"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64",
|
||||
@@ -3602,7 +3603,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-connect"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"nostr",
|
||||
@@ -3614,7 +3615,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-database"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"flatbuffers",
|
||||
"lru",
|
||||
@@ -3625,7 +3626,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-lmdb"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"heed",
|
||||
@@ -3638,7 +3639,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-relay-pool"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"async-wsocket",
|
||||
@@ -3655,7 +3656,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "nostr-sdk"
|
||||
version = "0.41.0"
|
||||
source = "git+https://github.com/rust-nostr/nostr#48de47bc7d6283e37e2e980f13608c3ed63286d9"
|
||||
source = "git+https://github.com/rust-nostr/nostr#54bdb993633146ca4bcfbcedd15735fff7dcbada"
|
||||
dependencies = [
|
||||
"async-utility",
|
||||
"nostr",
|
||||
@@ -4085,7 +4086,7 @@ dependencies = [
|
||||
"num",
|
||||
"num-bigint-dig",
|
||||
"pbkdf2",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"serde",
|
||||
"sha2",
|
||||
"subtle",
|
||||
@@ -4568,7 +4569,7 @@ checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.2",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"ring",
|
||||
"rustc-hash 2.1.1",
|
||||
"rustls",
|
||||
@@ -4622,13 +4623,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
"zerocopy 0.8.24",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4813,7 +4813,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "refineable"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"derive_refineable",
|
||||
"workspace-hack",
|
||||
@@ -4951,7 +4951,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "reqwest_client"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -4969,9 +4969,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "resvg"
|
||||
version = "0.45.0"
|
||||
version = "0.45.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd43d1c474e9dadf09a8fdf22d713ba668b499b5117b9b9079500224e26b5b29"
|
||||
checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pico-args",
|
||||
@@ -5421,7 +5421,7 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749"
|
||||
[[package]]
|
||||
name = "semantic_version"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"serde",
|
||||
@@ -5564,9 +5564,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -5744,7 +5744,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
[[package]]
|
||||
name = "sum_tree"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"log",
|
||||
@@ -5832,9 +5832,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "svg_fmt"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce5d813d71d82c4cbc1742135004e4a79fd870214c155443451c139c9470a0aa"
|
||||
checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb"
|
||||
|
||||
[[package]]
|
||||
name = "svgtypes"
|
||||
@@ -6411,7 +6411,7 @@ dependencies = [
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.9.0",
|
||||
"rand 0.9.1",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"sha1",
|
||||
@@ -6588,9 +6588,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "usvg"
|
||||
version = "0.45.0"
|
||||
version = "0.45.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ac8e0e3e4696253dc06167990b3fe9a2668ab66270adf949a464db4088cb354"
|
||||
checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"data-url",
|
||||
@@ -6646,7 +6646,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
[[package]]
|
||||
name = "util"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/zed-industries/zed#a7a7335da4ebeb6ebd5c644f108edf2441f7d77b"
|
||||
source = "git+https://github.com/zed-industries/zed#107d8ca483276263362c23482612d1cadea81c71"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-fs",
|
||||
@@ -7076,7 +7076,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7249,6 +7249,17 @@ dependencies = [
|
||||
"windows-targets 0.53.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-registry"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad1da3e436dc7653dfdf3da67332e22bff09bb0e28b0239e1624499c7830842e"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows-result 0.3.2",
|
||||
"windows-strings 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
|
||||
@@ -31,6 +31,7 @@ impl Account {
|
||||
cx.set_global(GlobalAccount(account));
|
||||
}
|
||||
|
||||
/// Login to the account using the given signer.
|
||||
pub fn login<S>(&mut self, signer: S, window: &mut Window, cx: &mut Context<Self>)
|
||||
where
|
||||
S: NostrSigner + 'static,
|
||||
@@ -56,12 +57,15 @@ impl Account {
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| match task.await {
|
||||
Ok(profile) => {
|
||||
cx.update(|_, cx| {
|
||||
cx.update(|window, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.profile = Some(profile);
|
||||
this.profile(profile, cx);
|
||||
|
||||
cx.defer_in(window, |this, _, cx| {
|
||||
this.subscribe(cx);
|
||||
cx.notify();
|
||||
});
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
@@ -75,28 +79,80 @@ impl Account {
|
||||
.detach();
|
||||
}
|
||||
|
||||
/// Create a new account with the given metadata.
|
||||
pub fn new_account(&mut self, metadata: Metadata, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let client = get_client();
|
||||
const DEFAULT_NIP_65_RELAYS: [&str; 4] = [
|
||||
"wss://relay.damus.io",
|
||||
"wss://relay.primal.net",
|
||||
"wss://relay.nostr.net",
|
||||
"wss://nos.lol",
|
||||
];
|
||||
|
||||
const DEFAULT_MESSAGING_RELAYS: [&str; 2] =
|
||||
["wss://auth.nostr1.com", "wss://relay.0xchat.com"];
|
||||
|
||||
let keys = Keys::generate();
|
||||
let public_key = keys.public_key();
|
||||
|
||||
let task: Task<Result<Profile, Error>> = cx.background_spawn(async move {
|
||||
let public_key = keys.public_key();
|
||||
let client = get_client();
|
||||
|
||||
// Update signer
|
||||
client.set_signer(keys).await;
|
||||
|
||||
// Set metadata
|
||||
client.set_metadata(&metadata).await?;
|
||||
|
||||
// Create relay list
|
||||
let tags: Vec<Tag> = DEFAULT_NIP_65_RELAYS
|
||||
.into_iter()
|
||||
.filter_map(|url| {
|
||||
if let Ok(url) = RelayUrl::parse(url) {
|
||||
Some(Tag::relay_metadata(url, None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let builder = EventBuilder::new(Kind::RelayList, "").tags(tags);
|
||||
|
||||
if let Err(e) = client.send_event_builder(builder).await {
|
||||
log::error!("Failed to send relay list event: {}", e);
|
||||
};
|
||||
|
||||
// Create messaging relay list
|
||||
let tags: Vec<Tag> = DEFAULT_MESSAGING_RELAYS
|
||||
.into_iter()
|
||||
.filter_map(|url| {
|
||||
if let Ok(url) = RelayUrl::parse(url) {
|
||||
Some(Tag::relay(url))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let builder = EventBuilder::new(Kind::InboxRelays, "").tags(tags);
|
||||
|
||||
if let Err(e) = client.send_event_builder(builder).await {
|
||||
log::error!("Failed to send messaging relay list event: {}", e);
|
||||
};
|
||||
|
||||
Ok(Profile::new(public_key, metadata))
|
||||
});
|
||||
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
if let Ok(profile) = task.await {
|
||||
cx.update(|_, cx| {
|
||||
cx.update(|window, cx| {
|
||||
this.update(cx, |this, cx| {
|
||||
this.profile = Some(profile);
|
||||
this.profile(profile, cx);
|
||||
|
||||
cx.defer_in(window, |this, _, cx| {
|
||||
this.subscribe(cx);
|
||||
cx.notify();
|
||||
});
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.ok();
|
||||
} else {
|
||||
@@ -109,12 +165,18 @@ impl Account {
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn subscribe(&self, cx: &Context<Self>) {
|
||||
/// Sets the profile for the account.
|
||||
pub fn profile(&mut self, profile: Profile, cx: &mut Context<Self>) {
|
||||
self.profile = Some(profile);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
/// Subscribes to the current account's metadata.
|
||||
pub fn subscribe(&self, cx: &mut Context<Self>) {
|
||||
let Some(profile) = self.profile.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let client = get_client();
|
||||
let user = profile.public_key();
|
||||
let opts = SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE);
|
||||
|
||||
@@ -145,6 +207,7 @@ impl Account {
|
||||
let new_msg = Filter::new().kind(Kind::GiftWrap).pubkey(user).limit(0);
|
||||
|
||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||
let client = get_client();
|
||||
client.subscribe(metadata, Some(opts)).await?;
|
||||
client.subscribe(data, None).await?;
|
||||
|
||||
|
||||
@@ -337,13 +337,7 @@ impl Room {
|
||||
.author(*pubkey)
|
||||
.limit(1);
|
||||
|
||||
let is_ready = client
|
||||
.database()
|
||||
.query(filter)
|
||||
.await
|
||||
.ok()
|
||||
.and_then(|events| events.first_owned())
|
||||
.is_some();
|
||||
let is_ready = client.database().query(filter).await?.first().is_some();
|
||||
|
||||
result.push((*pubkey, is_ready));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
use account::Account;
|
||||
use anyhow::Error;
|
||||
use global::get_client;
|
||||
use gpui::{
|
||||
div, impl_internal_actions, prelude::FluentBuilder, px, App, AppContext, Axis, Context, Entity,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, Styled, Subscription, Window,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, Styled, Subscription, Task, Window,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::sync::Arc;
|
||||
@@ -13,7 +16,7 @@ use ui::{
|
||||
ContextModal, IconName, Root, Sizable, TitleBar,
|
||||
};
|
||||
|
||||
use crate::views::{chat, compose, contacts, profile, relays, welcome};
|
||||
use crate::views::{chat, compose, contacts, login, new_account, profile, relays, welcome};
|
||||
use crate::views::{onboarding, sidebar};
|
||||
|
||||
const MODAL_WIDTH: f32 = 420.;
|
||||
@@ -25,6 +28,16 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<ChatSpace> {
|
||||
ChatSpace::new(window, cx)
|
||||
}
|
||||
|
||||
pub fn login(window: &mut Window, cx: &mut App) {
|
||||
let panel = login::init(window, cx);
|
||||
ChatSpace::set_center_panel(panel, window, cx);
|
||||
}
|
||||
|
||||
pub fn new_account(window: &mut Window, cx: &mut App) {
|
||||
let panel = new_account::init(window, cx);
|
||||
ChatSpace::set_center_panel(panel, window, cx);
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||
pub enum PanelKind {
|
||||
Room(u64),
|
||||
@@ -37,6 +50,7 @@ pub enum ModalKind {
|
||||
Compose,
|
||||
Contact,
|
||||
Relay,
|
||||
SetupRelay,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Deserialize)]
|
||||
@@ -65,10 +79,17 @@ pub struct ChatSpace {
|
||||
|
||||
impl ChatSpace {
|
||||
pub fn new(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
||||
let account = Account::global(cx);
|
||||
let dock = cx.new(|cx| DockArea::new(window, cx));
|
||||
let dock = cx.new(|cx| {
|
||||
let panel = Arc::new(onboarding::init(window, cx));
|
||||
let center = DockItem::panel(panel);
|
||||
let mut dock = DockArea::new(window, cx);
|
||||
// Initialize the dock area with the center panel
|
||||
dock.set_center(center, window, cx);
|
||||
dock
|
||||
});
|
||||
|
||||
cx.new(|cx| {
|
||||
let account = Account::global(cx);
|
||||
let mut subscriptions = smallvec![];
|
||||
|
||||
subscriptions.push(cx.observe_in(
|
||||
@@ -83,35 +104,17 @@ impl ChatSpace {
|
||||
},
|
||||
));
|
||||
|
||||
let mut this = Self {
|
||||
Self {
|
||||
dock,
|
||||
subscriptions,
|
||||
titlebar: false,
|
||||
};
|
||||
|
||||
if Account::global(cx).read(cx).profile.is_some() {
|
||||
this.open_chats(window, cx);
|
||||
} else {
|
||||
this.open_onboarding(window, cx);
|
||||
}
|
||||
|
||||
this
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_center_panel<P: PanelView>(panel: P, window: &mut Window, cx: &mut App) {
|
||||
if let Some(Some(root)) = window.root::<Root>() {
|
||||
if let Ok(chatspace) = root.read(cx).view().clone().downcast::<ChatSpace>() {
|
||||
let panel = Arc::new(panel);
|
||||
let center = DockItem::panel(panel);
|
||||
|
||||
chatspace.update(cx, |this, cx| {
|
||||
this.dock.update(cx, |this, cx| {
|
||||
this.set_center(center, window, cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
fn show_titlebar(&mut self, cx: &mut Context<Self>) {
|
||||
self.titlebar = true;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn open_onboarding(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
@@ -147,31 +150,44 @@ impl ChatSpace {
|
||||
this.set_left_dock(left, Some(px(SIDEBAR_WIDTH)), true, window, cx);
|
||||
this.set_center(center, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
fn show_titlebar(&mut self, cx: &mut Context<Self>) {
|
||||
self.titlebar = true;
|
||||
cx.notify();
|
||||
}
|
||||
cx.defer_in(window, |this, window, cx| {
|
||||
let verify_messaging_relays = this.verify_messaging_relays(cx);
|
||||
|
||||
fn render_appearance_btn(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
Button::new("appearance")
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.map(|this| {
|
||||
if cx.theme().appearance.is_dark() {
|
||||
this.icon(IconName::Sun)
|
||||
} else {
|
||||
this.icon(IconName::Moon)
|
||||
cx.spawn_in(window, async move |_, cx| {
|
||||
if let Ok(status) = verify_messaging_relays.await {
|
||||
if !status {
|
||||
cx.update(|window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(ToggleModal {
|
||||
modal: ModalKind::SetupRelay,
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_click(cx.listener(|_, _, window, cx| {
|
||||
if cx.theme().appearance.is_dark() {
|
||||
Theme::change(Appearance::Light, Some(window), cx);
|
||||
} else {
|
||||
Theme::change(Appearance::Dark, Some(window), cx);
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
}))
|
||||
|
||||
fn verify_messaging_relays(&self, cx: &App) -> Task<Result<bool, Error>> {
|
||||
cx.background_spawn(async move {
|
||||
let client = get_client();
|
||||
let signer = client.signer().await?;
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::InboxRelays)
|
||||
.author(public_key)
|
||||
.limit(1);
|
||||
|
||||
let exist = client.database().query(filter).await?.first().is_some();
|
||||
|
||||
Ok(exist)
|
||||
})
|
||||
}
|
||||
|
||||
fn on_panel_action(&mut self, action: &AddPanel, window: &mut Window, cx: &mut Context<Self>) {
|
||||
@@ -235,8 +251,32 @@ impl ChatSpace {
|
||||
.child(relays.clone())
|
||||
});
|
||||
}
|
||||
ModalKind::SetupRelay => {
|
||||
let relays = relays::init(window, cx);
|
||||
|
||||
window.open_modal(cx, move |this, _, _| {
|
||||
this.width(px(MODAL_WIDTH))
|
||||
.title("Your Messaging Relays are not configured")
|
||||
.child(relays.clone())
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn set_center_panel<P: PanelView>(panel: P, window: &mut Window, cx: &mut App) {
|
||||
if let Some(Some(root)) = window.root::<Root>() {
|
||||
if let Ok(chatspace) = root.read(cx).view().clone().downcast::<ChatSpace>() {
|
||||
let panel = Arc::new(panel);
|
||||
let center = DockItem::panel(panel);
|
||||
|
||||
chatspace.update(cx, |this, cx| {
|
||||
this.dock.update(cx, |this, cx| {
|
||||
this.set_center(center, window, cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ChatSpace {
|
||||
@@ -266,7 +306,33 @@ impl Render for ChatSpace {
|
||||
.justify_end()
|
||||
.gap_2()
|
||||
.px_2()
|
||||
.child(self.render_appearance_btn(cx)),
|
||||
.child(
|
||||
Button::new("appearance")
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.map(|this| {
|
||||
if cx.theme().appearance.is_dark() {
|
||||
this.icon(IconName::Sun)
|
||||
} else {
|
||||
this.icon(IconName::Moon)
|
||||
}
|
||||
})
|
||||
.on_click(cx.listener(|_, _, window, cx| {
|
||||
if cx.theme().appearance.is_dark() {
|
||||
Theme::change(
|
||||
Appearance::Light,
|
||||
Some(window),
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
Theme::change(
|
||||
Appearance::Dark,
|
||||
Some(window),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
})),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -27,7 +27,7 @@ use std::{collections::HashSet, mem, sync::Arc, time::Duration};
|
||||
use ui::{theme::Theme, Root};
|
||||
|
||||
pub(crate) mod asset;
|
||||
pub(crate) mod chat_space;
|
||||
pub(crate) mod chatspace;
|
||||
pub(crate) mod views;
|
||||
|
||||
actions!(coop, [Quit]);
|
||||
@@ -84,7 +84,7 @@ fn main() {
|
||||
};
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::ArticlesCurationSet)
|
||||
.kind(Kind::ReleaseArtifactSet)
|
||||
.coordinate(&coordinate)
|
||||
.limit(1);
|
||||
|
||||
@@ -334,7 +334,7 @@ fn main() {
|
||||
})
|
||||
.detach();
|
||||
|
||||
Root::new(chat_space::init(window, cx).into(), window, cx)
|
||||
Root::new(chatspace::init(window, cx).into(), window, cx)
|
||||
})
|
||||
})
|
||||
.expect("Failed to open window. Please restart the application.");
|
||||
|
||||
@@ -178,6 +178,7 @@ impl Login {
|
||||
}
|
||||
} else if content.starts_with("bunker://") {
|
||||
let keys = get_client_keys().to_owned();
|
||||
|
||||
let Ok(uri) = NostrConnectURI::parse(content.as_ref()) else {
|
||||
self.set_error_message("Bunker URL is not valid".to_owned(), cx);
|
||||
self.set_logging_in(false, cx);
|
||||
@@ -196,8 +197,8 @@ impl Login {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.set_logging_in(false, cx);
|
||||
window.push_notification(Notification::error(INPUT_INVALID), cx);
|
||||
self.set_logging_in(false, cx);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use async_utility::task::spawn;
|
||||
use common::nip96_upload;
|
||||
use global::{constants::IMAGE_SERVICE, get_client};
|
||||
use gpui::{
|
||||
div, img, prelude::FluentBuilder, px, relative, AnyElement, App, AppContext, Context, Entity,
|
||||
div, img, prelude::FluentBuilder, relative, AnyElement, App, AppContext, Context, Entity,
|
||||
EventEmitter, Flatten, FocusHandle, Focusable, IntoElement, ParentElement, PathPromptOptions,
|
||||
Render, SharedString, Styled, Window,
|
||||
};
|
||||
@@ -19,9 +19,6 @@ use ui::{
|
||||
Disableable, Icon, IconName, Sizable, Size, StyledExt,
|
||||
};
|
||||
|
||||
const STEAM_ID_DESCRIPTION: &str =
|
||||
"Steam ID is used to get your currently playing game and update your status.";
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<NewAccount> {
|
||||
NewAccount::new(window, cx)
|
||||
}
|
||||
@@ -30,7 +27,6 @@ pub struct NewAccount {
|
||||
name_input: Entity<TextInput>,
|
||||
avatar_input: Entity<TextInput>,
|
||||
bio_input: Entity<TextInput>,
|
||||
steam_input: Entity<TextInput>,
|
||||
is_uploading: bool,
|
||||
is_submitting: bool,
|
||||
// Panel
|
||||
@@ -59,12 +55,6 @@ impl NewAccount {
|
||||
.placeholder("https://example.com/avatar.jpg")
|
||||
});
|
||||
|
||||
let steam_input = cx.new(|cx| {
|
||||
TextInput::new(window, cx)
|
||||
.text_size(Size::Small)
|
||||
.placeholder("76561199810385277")
|
||||
});
|
||||
|
||||
let bio_input = cx.new(|cx| {
|
||||
TextInput::new(window, cx)
|
||||
.text_size(Size::Small)
|
||||
@@ -75,7 +65,6 @@ impl NewAccount {
|
||||
Self {
|
||||
name_input,
|
||||
avatar_input,
|
||||
steam_input,
|
||||
bio_input,
|
||||
is_uploading: false,
|
||||
is_submitting: false,
|
||||
@@ -92,12 +81,8 @@ impl NewAccount {
|
||||
let avatar = self.avatar_input.read(cx).text().to_string();
|
||||
let name = self.name_input.read(cx).text().to_string();
|
||||
let bio = self.bio_input.read(cx).text().to_string();
|
||||
let steam = self.steam_input.read(cx).text().to_string();
|
||||
|
||||
let mut metadata = Metadata::new()
|
||||
.display_name(name)
|
||||
.about(bio)
|
||||
.custom_field("steam", steam);
|
||||
let mut metadata = Metadata::new().display_name(name).about(bio);
|
||||
|
||||
if let Ok(url) = Url::from_str(&avatar) {
|
||||
metadata = metadata.picture(url);
|
||||
@@ -126,6 +111,7 @@ impl NewAccount {
|
||||
this.update(cx, |this, cx| {
|
||||
this.set_uploading(false, cx);
|
||||
})
|
||||
.ok();
|
||||
})
|
||||
.ok();
|
||||
|
||||
@@ -299,21 +285,6 @@ impl Render for NewAccount {
|
||||
.child("Bio:")
|
||||
.child(self.bio_input.clone()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.child("Steam ID:")
|
||||
.child(self.steam_input.clone())
|
||||
.child(
|
||||
div()
|
||||
.text_size(px(10.))
|
||||
.text_color(cx.theme().base.step(cx, ColorScaleStep::ELEVEN))
|
||||
.child(STEAM_ID_DESCRIPTION),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.my_2()
|
||||
|
||||
@@ -10,13 +10,7 @@ use ui::{
|
||||
Icon, IconName, StyledExt,
|
||||
};
|
||||
|
||||
use crate::chat_space::ChatSpace;
|
||||
|
||||
use super::{login, new_account};
|
||||
|
||||
const LOGO_URL: &str = "brand/coop.svg";
|
||||
const TITLE: &str = "Welcome to Coop!";
|
||||
const SUBTITLE: &str = "Secure Communication on Nostr.";
|
||||
use crate::chatspace;
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Onboarding> {
|
||||
Onboarding::new(window, cx)
|
||||
@@ -42,16 +36,6 @@ impl Onboarding {
|
||||
focus_handle: cx.focus_handle(),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_new_account(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let new_account = new_account::init(window, cx);
|
||||
ChatSpace::set_center_panel(new_account, window, cx);
|
||||
}
|
||||
|
||||
fn open_login(&self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let login = login::init(window, cx);
|
||||
ChatSpace::set_center_panel(login, window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl Panel for Onboarding {
|
||||
@@ -74,10 +58,6 @@ impl Panel for Onboarding {
|
||||
fn popup_menu(&self, menu: PopupMenu, _cx: &App) -> PopupMenu {
|
||||
menu.track_focus(&self.focus_handle)
|
||||
}
|
||||
|
||||
fn toolbar_buttons(&self, _window: &Window, _cx: &App) -> Vec<Button> {
|
||||
vec![]
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for Onboarding {}
|
||||
@@ -90,6 +70,9 @@ impl Focusable for Onboarding {
|
||||
|
||||
impl Render for Onboarding {
|
||||
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
const TITLE: &str = "Welcome to Coop!";
|
||||
const SUBTITLE: &str = "Secure Communication on Nostr.";
|
||||
|
||||
div()
|
||||
.py_4()
|
||||
.size_full()
|
||||
@@ -106,7 +89,7 @@ impl Render for Onboarding {
|
||||
.gap_4()
|
||||
.child(
|
||||
svg()
|
||||
.path(LOGO_URL)
|
||||
.path("brand/coop.svg")
|
||||
.size_16()
|
||||
.text_color(cx.theme().base.step(cx, ColorScaleStep::THREE)),
|
||||
)
|
||||
@@ -139,8 +122,8 @@ impl Render for Onboarding {
|
||||
.label("Start Messaging")
|
||||
.primary()
|
||||
.reverse()
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.open_new_account(window, cx);
|
||||
.on_click(cx.listener(move |_, _, window, cx| {
|
||||
chatspace::new_account(window, cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
@@ -148,8 +131,8 @@ impl Render for Onboarding {
|
||||
.label("Already have an account? Log in.")
|
||||
.ghost()
|
||||
.underline()
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
this.open_login(window, cx);
|
||||
.on_click(cx.listener(move |_, _, window, cx| {
|
||||
chatspace::login(window, cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use anyhow::{anyhow, Error};
|
||||
use anyhow::Error;
|
||||
use global::{constants::NEW_MESSAGE_SUB_ID, get_client};
|
||||
use gpui::{
|
||||
div, prelude::FluentBuilder, px, uniform_list, App, AppContext, Context, Entity, FocusHandle,
|
||||
@@ -41,11 +41,6 @@ impl Relays {
|
||||
});
|
||||
|
||||
let relays = cx.new(|cx| {
|
||||
let relays = vec![
|
||||
RelayUrl::parse("wss://auth.nostr1.com").unwrap(),
|
||||
RelayUrl::parse("wss://relay.0xchat.com").unwrap(),
|
||||
];
|
||||
|
||||
let task: Task<Result<Vec<RelayUrl>, Error>> = cx.background_spawn(async move {
|
||||
let client = get_client();
|
||||
let signer = client.signer().await?;
|
||||
@@ -59,16 +54,18 @@ impl Relays {
|
||||
if let Some(event) = client.database().query(filter).await?.first_owned() {
|
||||
let relays = event
|
||||
.tags
|
||||
.filter_standardized(TagKind::Relay)
|
||||
.filter_map(|t| match t {
|
||||
TagStandard::Relay(url) => Some(url.to_owned()),
|
||||
_ => None,
|
||||
})
|
||||
.filter(TagKind::Relay)
|
||||
.filter_map(|tag| RelayUrl::parse(tag.content()?).ok())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(relays)
|
||||
} else {
|
||||
Err(anyhow!("Messaging Relays not found."))
|
||||
let relays = vec![
|
||||
RelayUrl::parse("wss://auth.nostr1.com")?,
|
||||
RelayUrl::parse("wss://relay.0xchat.com")?,
|
||||
];
|
||||
|
||||
Ok(relays)
|
||||
}
|
||||
});
|
||||
|
||||
@@ -86,7 +83,7 @@ impl Relays {
|
||||
})
|
||||
.detach();
|
||||
|
||||
relays
|
||||
vec![]
|
||||
});
|
||||
|
||||
cx.new(|cx| {
|
||||
|
||||
@@ -25,7 +25,7 @@ use ui::{
|
||||
IconName, Sizable, StyledExt,
|
||||
};
|
||||
|
||||
use crate::chat_space::{AddPanel, ModalKind, PanelKind, ToggleModal};
|
||||
use crate::chatspace::{AddPanel, ModalKind, PanelKind, ToggleModal};
|
||||
|
||||
mod button;
|
||||
mod folder;
|
||||
|
||||
Reference in New Issue
Block a user