.
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m37s
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m35s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m37s
This commit is contained in:
78
Cargo.lock
generated
78
Cargo.lock
generated
@@ -601,9 +601,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "avif-serialize"
|
name = "avif-serialize"
|
||||||
version = "0.8.6"
|
version = "0.8.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f"
|
checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
]
|
]
|
||||||
@@ -620,9 +620,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-sys"
|
name = "aws-lc-sys"
|
||||||
version = "0.37.0"
|
version = "0.37.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a"
|
checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cmake",
|
"cmake",
|
||||||
@@ -1142,9 +1142,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.57"
|
version = "4.5.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a"
|
checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@@ -1152,9 +1152,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.57"
|
version = "4.5.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238"
|
checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -1176,9 +1176,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_lex"
|
name = "clap_lex"
|
||||||
version = "0.7.7"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32"
|
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
@@ -1263,7 +1263,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collections"
|
name = "collections"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
@@ -1708,7 +1708,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -2639,7 +2639,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "gpui"
|
name = "gpui"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"as-raw-xcb-connection",
|
"as-raw-xcb-connection",
|
||||||
@@ -2741,7 +2741,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -2752,7 +2752,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"gpui",
|
"gpui",
|
||||||
@@ -2987,7 +2987,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
@@ -3012,7 +3012,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-platform-verifier",
|
"rustls-platform-verifier",
|
||||||
@@ -3567,7 +3567,7 @@ checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.7.0",
|
"redox_syscall 0.7.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3780,7 +3780,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "media"
|
name = "media"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bindgen",
|
"bindgen",
|
||||||
@@ -4020,7 +4020,7 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr"
|
name = "nostr"
|
||||||
version = "0.44.1"
|
version = "0.44.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"base64",
|
"base64",
|
||||||
@@ -4045,7 +4045,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-connect"
|
name = "nostr-connect"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -4058,7 +4058,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-database"
|
name = "nostr-database"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"btreecap",
|
"btreecap",
|
||||||
"flatbuffers",
|
"flatbuffers",
|
||||||
@@ -4070,7 +4070,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-gossip"
|
name = "nostr-gossip"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nostr",
|
"nostr",
|
||||||
]
|
]
|
||||||
@@ -4078,7 +4078,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-gossip-memory"
|
name = "nostr-gossip-memory"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lru",
|
"lru",
|
||||||
@@ -4090,7 +4090,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-lmdb"
|
name = "nostr-lmdb"
|
||||||
version = "0.44.0"
|
version = "0.44.0"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"flume",
|
"flume",
|
||||||
@@ -4104,7 +4104,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nostr-sdk"
|
name = "nostr-sdk"
|
||||||
version = "0.44.1"
|
version = "0.44.1"
|
||||||
source = "git+https://github.com/rust-nostr/nostr#aeee536bdec863afffffe4819150230e20b8ad6b"
|
source = "git+https://github.com/rust-nostr/nostr#b968620ae4b8c31ee1cbcdb8ef8ec9ccd87e1fc6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-utility",
|
"async-utility",
|
||||||
"async-wsocket",
|
"async-wsocket",
|
||||||
@@ -4638,7 +4638,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collections",
|
"collections",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -5258,9 +5258,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.7.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27"
|
checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.10.0",
|
"bitflags 2.10.0",
|
||||||
]
|
]
|
||||||
@@ -5299,7 +5299,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "refineable"
|
name = "refineable"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_refineable",
|
"derive_refineable",
|
||||||
]
|
]
|
||||||
@@ -5398,7 +5398,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -5453,7 +5453,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rope"
|
name = "rope"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"log",
|
"log",
|
||||||
@@ -5715,7 +5715,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "scheduler"
|
name = "scheduler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-task",
|
"async-task",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
@@ -6330,7 +6330,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"log",
|
"log",
|
||||||
@@ -7297,7 +7297,7 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util"
|
name = "util"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-fs",
|
"async-fs",
|
||||||
@@ -7335,7 +7335,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "util_macros"
|
name = "util_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"perf",
|
"perf",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -8936,7 +8936,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "zlog"
|
name = "zlog"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -8953,7 +8953,7 @@ checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ztracing"
|
name = "ztracing"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/zed-industries/zed#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -8964,7 +8964,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#6cd7586c161b579ba7c1ecad7dea1b95ca3dd239"
|
source = "git+https://github.com/zed-industries/zed#ee3f40fe25d206ca363b753e5b86e09ac6181eca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ gpui_tokio = { git = "https://github.com/zed-industries/zed" }
|
|||||||
reqwest_client = { git = "https://github.com/zed-industries/zed" }
|
reqwest_client = { git = "https://github.com/zed-industries/zed" }
|
||||||
|
|
||||||
# Nostr
|
# Nostr
|
||||||
|
nostr = { git = "https://github.com/rust-nostr/nostr", features = [ "nip96", "nip59", "nip49", "nip44" ] }
|
||||||
|
nostr-sdk = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
nostr-lmdb = { git = "https://github.com/rust-nostr/nostr" }
|
nostr-lmdb = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
nostr-connect = { git = "https://github.com/rust-nostr/nostr" }
|
nostr-connect = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
nostr-sdk = { git = "https://github.com/rust-nostr/nostr", features = [ "nip96", "nip59", "nip49", "nip44" ] }
|
|
||||||
nostr-gossip-memory = { git = "https://github.com/rust-nostr/nostr" }
|
nostr-gossip-memory = { git = "https://github.com/rust-nostr/nostr" }
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ publish.workspace = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
gpui.workspace = true
|
gpui.workspace = true
|
||||||
|
nostr.workspace = true
|
||||||
nostr-sdk.workspace = true
|
nostr-sdk.workspace = true
|
||||||
|
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
@@ -19,4 +20,3 @@ log.workspace = true
|
|||||||
|
|
||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
qrcode = "0.14.1"
|
qrcode = "0.14.1"
|
||||||
nostr = { git = "https://github.com/rust-nostr/nostr" }
|
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ impl GreeterPanel {
|
|||||||
|
|
||||||
fn add_profile_panel(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
fn add_profile_panel(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let signer_pkey = nostr.read(cx).signer_pkey(cx);
|
let signer = nostr.read(cx).signer();
|
||||||
|
|
||||||
cx.spawn_in(window, async move |_this, cx| {
|
if let Some(public_key) = signer.public_key() {
|
||||||
if let Ok(public_key) = signer_pkey.await {
|
cx.spawn_in(window, async move |_this, cx| {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
Workspace::add_panel(
|
Workspace::add_panel(
|
||||||
profile::init(public_key, window, cx),
|
profile::init(public_key, window, cx),
|
||||||
@@ -45,9 +45,9 @@ impl GreeterPanel {
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
})
|
||||||
})
|
.detach();
|
||||||
.detach();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ impl Render for GreeterPanel {
|
|||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let nip65_state = nostr.read(cx).nip65_state();
|
let nip65_state = nostr.read(cx).nip65_state();
|
||||||
let nip17_state = nostr.read(cx).nip17_state();
|
let nip17_state = nostr.read(cx).nip17_state();
|
||||||
|
let signer = nostr.read(cx).signer();
|
||||||
|
let owned = signer.owned();
|
||||||
|
|
||||||
let required_actions = nip65_state.read(cx) == &RelayState::NotConfigured
|
let required_actions = nip65_state.read(cx) == &RelayState::NotConfigured
|
||||||
|| nip17_state.read(cx) == &RelayState::NotConfigured;
|
|| nip17_state.read(cx) == &RelayState::NotConfigured;
|
||||||
@@ -186,7 +188,7 @@ impl Render for GreeterPanel {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when(!nostr.read(cx).owned_signer(), |this| {
|
.when(!owned, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
v_flex()
|
v_flex()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
|
|||||||
@@ -321,13 +321,13 @@ impl Sidebar {
|
|||||||
let async_chat = chat.downgrade();
|
let async_chat = chat.downgrade();
|
||||||
|
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let signer_pkey = nostr.read(cx).signer_pkey(cx);
|
let signer = nostr.read(cx).signer();
|
||||||
|
|
||||||
// Get all selected public keys
|
// Get all selected public keys
|
||||||
let receivers = self.get_selected(cx);
|
let receivers = self.get_selected(cx);
|
||||||
|
|
||||||
self.tasks.push(cx.spawn_in(window, async move |this, cx| {
|
self.tasks.push(cx.spawn_in(window, async move |this, cx| {
|
||||||
let public_key = signer_pkey.await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
|
||||||
// Create a new room and emit it
|
// Create a new room and emit it
|
||||||
async_chat.update_in(cx, |this, _window, cx| {
|
async_chat.update_in(cx, |this, _window, cx| {
|
||||||
|
|||||||
@@ -2,14 +2,13 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use chat::{ChatEvent, ChatRegistry};
|
use chat::{ChatEvent, ChatRegistry};
|
||||||
use dock::dock::DockPlacement;
|
use dock::dock::DockPlacement;
|
||||||
use dock::panel::PanelView;
|
use dock::panel::{PanelStyle, PanelView};
|
||||||
use dock::{ClosePanel, DockArea, DockItem};
|
use dock::{ClosePanel, DockArea, DockItem};
|
||||||
use gpui::prelude::FluentBuilder;
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, rems, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement,
|
div, rems, App, AppContext, Axis, Context, Entity, InteractiveElement, IntoElement,
|
||||||
ParentElement, Render, SharedString, Styled, Subscription, Window,
|
ParentElement, Render, SharedString, Styled, Subscription, Window,
|
||||||
};
|
};
|
||||||
use nostr_sdk::prelude::*;
|
|
||||||
use person::PersonRegistry;
|
use person::PersonRegistry;
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use state::{NostrRegistry, RelayState};
|
use state::{NostrRegistry, RelayState};
|
||||||
@@ -34,24 +33,15 @@ pub struct Workspace {
|
|||||||
/// App's Dock Area
|
/// App's Dock Area
|
||||||
dock: Entity<DockArea>,
|
dock: Entity<DockArea>,
|
||||||
|
|
||||||
/// Current User
|
|
||||||
current_user: Entity<Option<PublicKey>>,
|
|
||||||
|
|
||||||
/// Event subscriptions
|
/// Event subscriptions
|
||||||
_subscriptions: SmallVec<[Subscription; 3]>,
|
_subscriptions: SmallVec<[Subscription; 3]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||||
let titlebar = cx.new(|_| TitleBar::new());
|
|
||||||
let dock =
|
|
||||||
cx.new(|cx| DockArea::new(window, cx).panel_style(dock::panel::PanelStyle::TabBar));
|
|
||||||
|
|
||||||
let chat = ChatRegistry::global(cx);
|
let chat = ChatRegistry::global(cx);
|
||||||
let current_user = cx.new(|_| None);
|
let titlebar = cx.new(|_| TitleBar::new());
|
||||||
|
let dock = cx.new(|cx| DockArea::new(window, cx).style(PanelStyle::TabBar));
|
||||||
let nostr = NostrRegistry::global(cx);
|
|
||||||
let nip65_state = nostr.read(cx).nip65_state();
|
|
||||||
|
|
||||||
let mut subscriptions = smallvec![];
|
let mut subscriptions = smallvec![];
|
||||||
|
|
||||||
@@ -99,15 +89,6 @@ impl Workspace {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
subscriptions.push(
|
|
||||||
// Observe the NIP-65 state
|
|
||||||
cx.observe(&nip65_state, move |this, state, cx| {
|
|
||||||
if state.read(cx).idle() || state.read(cx).checking() {
|
|
||||||
this.get_current_user(cx);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set the default layout for app's dock
|
// Set the default layout for app's dock
|
||||||
cx.defer_in(window, |this, window, cx| {
|
cx.defer_in(window, |this, window, cx| {
|
||||||
this.set_layout(window, cx);
|
this.set_layout(window, cx);
|
||||||
@@ -116,7 +97,6 @@ impl Workspace {
|
|||||||
Self {
|
Self {
|
||||||
titlebar,
|
titlebar,
|
||||||
dock,
|
dock,
|
||||||
current_user,
|
|
||||||
_subscriptions: subscriptions,
|
_subscriptions: subscriptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,37 +161,19 @@ impl Workspace {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_current_user(&self, cx: &mut Context<Self>) {
|
|
||||||
let nostr = NostrRegistry::global(cx);
|
|
||||||
let client = nostr.read(cx).client();
|
|
||||||
let current_user = self.current_user.downgrade();
|
|
||||||
|
|
||||||
cx.spawn(async move |_this, cx| {
|
|
||||||
if let Some(signer) = client.signer() {
|
|
||||||
if let Ok(public_key) = signer.get_public_key().await {
|
|
||||||
current_user
|
|
||||||
.update(cx, |this, cx| {
|
|
||||||
*this = Some(public_key);
|
|
||||||
cx.notify();
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn titlebar_left(&mut self, _window: &mut Window, cx: &Context<Self>) -> impl IntoElement {
|
fn titlebar_left(&mut self, _window: &mut Window, cx: &Context<Self>) -> impl IntoElement {
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
let nip65 = nostr.read(cx).nip65_state();
|
let nip65 = nostr.read(cx).nip65_state();
|
||||||
let nip17 = nostr.read(cx).nip17_state();
|
let nip17 = nostr.read(cx).nip17_state();
|
||||||
|
let signer = nostr.read(cx).signer();
|
||||||
|
let current_user = signer.public_key();
|
||||||
|
|
||||||
h_flex()
|
h_flex()
|
||||||
.h(TITLEBAR_HEIGHT)
|
.h(TITLEBAR_HEIGHT)
|
||||||
.flex_shrink_0()
|
.flex_shrink_0()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.when_some(self.current_user.read(cx).as_ref(), |this, public_key| {
|
.when_some(current_user.as_ref(), |this, public_key| {
|
||||||
let persons = PersonRegistry::global(cx);
|
let persons = PersonRegistry::global(cx);
|
||||||
let profile = persons.read(cx).get(public_key, cx);
|
let profile = persons.read(cx).get(public_key, cx);
|
||||||
|
|
||||||
@@ -232,6 +194,19 @@ impl Workspace {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.when(nostr.read(cx).creating_signer(), |this| {
|
||||||
|
this.child(div().text_xs().text_color(cx.theme().text_muted).child(
|
||||||
|
SharedString::from("Coop is creating a new identity for you..."),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.when(!nostr.read(cx).connected(), |this| {
|
||||||
|
this.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.text_color(cx.theme().text_muted)
|
||||||
|
.child(SharedString::from("Connecting...")),
|
||||||
|
)
|
||||||
|
})
|
||||||
.map(|this| match nip65.read(cx) {
|
.map(|this| match nip65.read(cx) {
|
||||||
RelayState::Checking => this.child(
|
RelayState::Checking => this.child(
|
||||||
div()
|
div()
|
||||||
@@ -247,7 +222,7 @@ impl Workspace {
|
|||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().warning_foreground)
|
.text_color(cx.theme().warning_foreground)
|
||||||
.bg(cx.theme().warning_background)
|
.bg(cx.theme().warning_background)
|
||||||
.rounded_xs()
|
.rounded_sm()
|
||||||
.child(SharedString::from("User hasn't configured a relay list")),
|
.child(SharedString::from("User hasn't configured a relay list")),
|
||||||
),
|
),
|
||||||
_ => this,
|
_ => this,
|
||||||
@@ -266,7 +241,7 @@ impl Workspace {
|
|||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().warning_foreground)
|
.text_color(cx.theme().warning_foreground)
|
||||||
.bg(cx.theme().warning_background)
|
.bg(cx.theme().warning_background)
|
||||||
.rounded_xs()
|
.rounded_sm()
|
||||||
.child(SharedString::from(
|
.child(SharedString::from(
|
||||||
"User hasn't configured a messaging relay list",
|
"User hasn't configured a messaging relay list",
|
||||||
)),
|
)),
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ impl DockArea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the panel style of the dock area.
|
/// Set the panel style of the dock area.
|
||||||
pub fn panel_style(mut self, style: PanelStyle) -> Self {
|
pub fn style(mut self, style: PanelStyle) -> Self {
|
||||||
self.panel_style = style;
|
self.panel_style = style;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,13 +37,12 @@ pub const USER_GIFTWRAP: &str = "user-gift-wraps";
|
|||||||
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 SEARCH_RELAYS: [&str; 2] = ["wss://antiprimal.net", "wss://relay.noswhere.com"];
|
pub const SEARCH_RELAYS: [&str; 1] = ["wss://antiprimal.net"];
|
||||||
|
|
||||||
/// Default bootstrap relays
|
/// Default bootstrap relays
|
||||||
pub const BOOTSTRAP_RELAYS: [&str; 4] = [
|
pub const BOOTSTRAP_RELAYS: [&str; 3] = [
|
||||||
"wss://relay.damus.io",
|
"wss://relay.damus.io",
|
||||||
"wss://relay.primal.net",
|
"wss://relay.primal.net",
|
||||||
"wss://relay.nos.social",
|
|
||||||
"wss://user.kindpag.es",
|
"wss://user.kindpag.es",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -48,14 +48,15 @@ pub struct NostrRegistry {
|
|||||||
/// Nostr client
|
/// Nostr client
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
||||||
|
/// Whether the bootstrapping relays is connected
|
||||||
|
connected: bool,
|
||||||
|
|
||||||
|
/// Whether coop is creating a default signer
|
||||||
|
creating_signer: bool,
|
||||||
|
|
||||||
/// Nostr signer
|
/// Nostr signer
|
||||||
signer: Arc<CoopSigner>,
|
signer: Arc<CoopSigner>,
|
||||||
|
|
||||||
/// By default, Coop generates a new signer for new users.
|
|
||||||
///
|
|
||||||
/// This flag indicates whether the signer is user-owned or Coop-generated.
|
|
||||||
owned_signer: bool,
|
|
||||||
|
|
||||||
/// NIP-65 relay state
|
/// NIP-65 relay state
|
||||||
nip65: Entity<RelayState>,
|
nip65: Entity<RelayState>,
|
||||||
|
|
||||||
@@ -129,16 +130,17 @@ impl NostrRegistry {
|
|||||||
cx.defer(|cx| {
|
cx.defer(|cx| {
|
||||||
let nostr = NostrRegistry::global(cx);
|
let nostr = NostrRegistry::global(cx);
|
||||||
|
|
||||||
|
// Connect to the bootstrapping relays
|
||||||
nostr.update(cx, |this, cx| {
|
nostr.update(cx, |this, cx| {
|
||||||
this.connect(cx);
|
this.connect(cx);
|
||||||
this.get_identity(cx);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
|
connected: false,
|
||||||
|
creating_signer: false,
|
||||||
signer,
|
signer,
|
||||||
owned_signer: false,
|
|
||||||
nip65,
|
nip65,
|
||||||
nip17,
|
nip17,
|
||||||
app_keys,
|
app_keys,
|
||||||
@@ -151,19 +153,29 @@ impl NostrRegistry {
|
|||||||
fn connect(&mut self, cx: &mut Context<Self>) {
|
fn connect(&mut self, cx: &mut Context<Self>) {
|
||||||
let client = self.client();
|
let client = self.client();
|
||||||
|
|
||||||
self.tasks.push(cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
// Add search relay to the relay pool
|
// Add search relay to the relay pool
|
||||||
for url in SEARCH_RELAYS.into_iter() {
|
for url in SEARCH_RELAYS.into_iter() {
|
||||||
client.add_relay(url).await?;
|
client.add_relay(url).and_connect().await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add bootstrap relay to the relay pool
|
// Add bootstrap relay to the relay pool
|
||||||
for url in BOOTSTRAP_RELAYS.into_iter() {
|
for url in BOOTSTRAP_RELAYS.into_iter() {
|
||||||
client.add_relay(url).await?;
|
client.add_relay(url).and_connect().await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect to all added relays
|
Ok(())
|
||||||
client.connect().await;
|
});
|
||||||
|
|
||||||
|
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||||
|
// Wait for the task to complete
|
||||||
|
task.await?;
|
||||||
|
|
||||||
|
// Update the state
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.set_connected(cx);
|
||||||
|
this.get_signer(cx);
|
||||||
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
@@ -174,22 +186,16 @@ impl NostrRegistry {
|
|||||||
self.client.clone()
|
self.client.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the nostr signer
|
||||||
|
pub fn signer(&self) -> Arc<CoopSigner> {
|
||||||
|
self.signer.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the app keys
|
/// Get the app keys
|
||||||
pub fn app_keys(&self) -> &Keys {
|
pub fn app_keys(&self) -> &Keys {
|
||||||
&self.app_keys
|
&self.app_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether the current signer is owned by user
|
|
||||||
pub fn owned_signer(&self) -> bool {
|
|
||||||
self.owned_signer
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set whether the current signer is owned by user
|
|
||||||
pub fn set_owned_signer(&mut self, owned: bool, cx: &mut Context<Self>) {
|
|
||||||
self.owned_signer = owned;
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the NIP-65 state
|
/// Get the NIP-65 state
|
||||||
pub fn nip65_state(&self) -> Entity<RelayState> {
|
pub fn nip65_state(&self) -> Entity<RelayState> {
|
||||||
self.nip65.clone()
|
self.nip65.clone()
|
||||||
@@ -200,16 +206,26 @@ impl NostrRegistry {
|
|||||||
self.nip17.clone()
|
self.nip17.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get current signer's public key
|
/// Get the connected state
|
||||||
pub fn signer_pkey(&self, cx: &App) -> Task<Result<PublicKey, Error>> {
|
pub fn connected(&self) -> bool {
|
||||||
let client = self.client();
|
self.connected
|
||||||
|
}
|
||||||
|
|
||||||
cx.background_spawn(async move {
|
/// Set the connected state
|
||||||
let signer = client.signer().context("Signer not found")?;
|
fn set_connected(&mut self, cx: &mut Context<Self>) {
|
||||||
let public_key = signer.get_public_key().await?;
|
self.connected = true;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
Ok(public_key)
|
/// Get the creating signer status
|
||||||
})
|
pub fn creating_signer(&self) -> bool {
|
||||||
|
self.creating_signer
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the creating signer status
|
||||||
|
fn set_creating_signer(&mut self, status: bool, cx: &mut Context<Self>) {
|
||||||
|
self.creating_signer = status;
|
||||||
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a relay hint (messaging relay) for a given public key
|
/// Get a relay hint (messaging relay) for a given public key
|
||||||
@@ -290,18 +306,17 @@ impl NostrRegistry {
|
|||||||
T: NostrSigner + 'static,
|
T: NostrSigner + 'static,
|
||||||
{
|
{
|
||||||
let client = self.client();
|
let client = self.client();
|
||||||
let signer = self.signer.clone();
|
let signer = self.signer();
|
||||||
|
|
||||||
// Create a task to update the signer and verify the public key
|
// Create a task to update the signer and verify the public key
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
// Update signer
|
// Update signer
|
||||||
signer.switch(new).await;
|
signer.switch(new, owned).await;
|
||||||
|
|
||||||
// Verify signer
|
// Verify signer
|
||||||
let signer = client.signer().context("Signer not found")?;
|
let signer = client.signer().context("Signer not found")?;
|
||||||
let public_key = signer.get_public_key().await?;
|
let public_key = signer.get_public_key().await?;
|
||||||
|
log::info!("Signer's public key: {}", public_key);
|
||||||
log::info!("Signer's public key: {public_key}");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
@@ -313,8 +328,6 @@ impl NostrRegistry {
|
|||||||
// Update states
|
// Update states
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.reset_relay_states(cx);
|
this.reset_relay_states(cx);
|
||||||
this.get_relay_list(cx);
|
|
||||||
this.set_owned_signer(owned, cx);
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -615,83 +628,61 @@ impl NostrRegistry {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get local stored identity
|
|
||||||
fn get_identity(&mut self, cx: &mut Context<Self>) {
|
|
||||||
let read_credential = cx.read_credentials(KEYRING);
|
|
||||||
|
|
||||||
self.tasks.push(cx.spawn(async move |this, cx| {
|
|
||||||
match read_credential.await {
|
|
||||||
Ok(Some((_, secret))) => {
|
|
||||||
let secret = SecretKey::from_slice(&secret)?;
|
|
||||||
let keys = Keys::new(secret);
|
|
||||||
|
|
||||||
this.update(cx, |this, cx| {
|
|
||||||
this.set_signer(keys, false, cx);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
this.update(cx, |this, cx| {
|
|
||||||
this.get_bunker(cx);
|
|
||||||
})
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new identity
|
/// Create a new identity
|
||||||
fn create_identity(&mut self, cx: &mut Context<Self>) {
|
fn set_default_signer(&mut self, cx: &mut Context<Self>) {
|
||||||
let client = self.client();
|
let client = self.client();
|
||||||
let keys = Keys::generate();
|
let keys = Keys::generate();
|
||||||
let async_keys = keys.clone();
|
|
||||||
|
|
||||||
// Get write credential task
|
// Create a write credential task
|
||||||
let write_credential = cx.write_credentials(
|
let write_credential = cx.write_credentials(
|
||||||
KEYRING,
|
KEYRING,
|
||||||
&keys.public_key().to_hex(),
|
&keys.public_key().to_hex(),
|
||||||
&keys.secret_key().to_secret_bytes(),
|
&keys.secret_key().to_secret_bytes(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Update the signer
|
||||||
|
self.set_signer(keys, false, cx);
|
||||||
|
|
||||||
|
// Set the creating signer status
|
||||||
|
self.set_creating_signer(true, cx);
|
||||||
|
|
||||||
// Run async tasks in background
|
// Run async tasks in background
|
||||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||||
// Build and sign the relay list event
|
let signer = client.signer().context("Signer not found")?;
|
||||||
|
|
||||||
|
// Get default relay list
|
||||||
let relay_list = default_relay_list();
|
let relay_list = default_relay_list();
|
||||||
let event = EventBuilder::relay_list(relay_list)
|
|
||||||
.sign(&async_keys)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Publish relay list event
|
// Publish relay list event
|
||||||
client.send_event(&event).await?;
|
let event = EventBuilder::relay_list(relay_list).sign(signer).await?;
|
||||||
|
let output = client.send_event(&event).broadcast().await?;
|
||||||
|
log::info!("Published relay list event: {:?}", output.id());
|
||||||
|
|
||||||
// Build and sign the metadata event
|
// Construct the default metadata
|
||||||
let name = petname::petname(2, "-").unwrap_or("Cooper".to_string());
|
let name = petname::petname(2, "-").unwrap_or("Cooper".to_string());
|
||||||
let avatar = Url::parse(&format!("https://avatar.vercel.sh/{name}")).unwrap();
|
let avatar = Url::parse(&format!("https://avatar.vercel.sh/{name}")).unwrap();
|
||||||
let metadata = Metadata::new().display_name(&name).picture(avatar);
|
let metadata = Metadata::new().display_name(&name).picture(avatar);
|
||||||
let event = EventBuilder::metadata(&metadata).sign(&async_keys).await?;
|
|
||||||
|
|
||||||
// Publish metadata event
|
// Publish metadata event
|
||||||
client.send_event(&event).await?;
|
let event = EventBuilder::metadata(&metadata).sign(signer).await?;
|
||||||
|
let output = client.send_event(&event).broadcast().await?;
|
||||||
|
log::info!("Published metadata event: {:?}", output.id());
|
||||||
|
|
||||||
// Build and sign the contact list event
|
// Construct the default contact list
|
||||||
let contacts = vec![Contact::new(PublicKey::parse(COOP_PUBKEY).unwrap())];
|
let contacts = vec![Contact::new(PublicKey::parse(COOP_PUBKEY).unwrap())];
|
||||||
let event = EventBuilder::contact_list(contacts)
|
|
||||||
.sign(&async_keys)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Publish contact list event
|
// Publish contact list event
|
||||||
client.send_event(&event).await?;
|
let event = EventBuilder::contact_list(contacts).sign(signer).await?;
|
||||||
|
let output = client.send_event(&event).broadcast().await?;
|
||||||
|
log::info!("Published contact list event: {:?}", output.id());
|
||||||
|
|
||||||
// Build and sign the messaging relay list event
|
// Construct the default messaging relay list
|
||||||
let relays = default_messaging_relays();
|
let relays = default_messaging_relays();
|
||||||
let event = EventBuilder::nip17_relay_list(relays)
|
|
||||||
.sign(&async_keys)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
// Publish messaging relay list event
|
// Publish messaging relay list event
|
||||||
client.send_event(&event).await?;
|
let event = EventBuilder::nip17_relay_list(relays).sign(signer).await?;
|
||||||
|
let output = client.send_event(&event).to_nip65().await?;
|
||||||
|
log::info!("Published messaging relay list event: {:?}", output.id());
|
||||||
|
|
||||||
// Write user's credentials to the system keyring
|
// Write user's credentials to the system keyring
|
||||||
write_credential.await?;
|
write_credential.await?;
|
||||||
@@ -703,15 +694,41 @@ impl NostrRegistry {
|
|||||||
// Wait for the task to complete
|
// Wait for the task to complete
|
||||||
task.await?;
|
task.await?;
|
||||||
|
|
||||||
// Update the signer
|
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.set_signer(keys, false, cx);
|
this.set_creating_signer(false, cx);
|
||||||
|
this.get_relay_list(cx);
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get local stored signer
|
||||||
|
fn get_signer(&mut self, cx: &mut Context<Self>) {
|
||||||
|
let read_credential = cx.read_credentials(KEYRING);
|
||||||
|
|
||||||
|
self.tasks.push(cx.spawn(async move |this, cx| {
|
||||||
|
match read_credential.await {
|
||||||
|
Ok(Some((_user, secret))) => {
|
||||||
|
let secret = SecretKey::from_slice(&secret)?;
|
||||||
|
let keys = Keys::new(secret);
|
||||||
|
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.set_signer(keys, false, cx);
|
||||||
|
this.get_relay_list(cx);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
this.update(cx, |this, cx| {
|
||||||
|
this.get_bunker(cx);
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
/// Get local stored bunker connection
|
/// Get local stored bunker connection
|
||||||
fn get_bunker(&mut self, cx: &mut Context<Self>) {
|
fn get_bunker(&mut self, cx: &mut Context<Self>) {
|
||||||
let client = self.client();
|
let client = self.client();
|
||||||
@@ -741,6 +758,7 @@ impl NostrRegistry {
|
|||||||
Ok(signer) => {
|
Ok(signer) => {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.set_signer(signer, true, cx);
|
this.set_signer(signer, true, cx);
|
||||||
|
this.get_relay_list(cx);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
@@ -748,7 +766,7 @@ impl NostrRegistry {
|
|||||||
log::warn!("Failed to get bunker: {e}");
|
log::warn!("Failed to get bunker: {e}");
|
||||||
// Create a new identity if no stored bunker exists
|
// Create a new identity if no stored bunker exists
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.create_identity(cx);
|
this.set_default_signer(cx);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
@@ -8,6 +9,17 @@ use smol::lock::RwLock;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CoopSigner {
|
pub struct CoopSigner {
|
||||||
signer: RwLock<Arc<dyn NostrSigner>>,
|
signer: RwLock<Arc<dyn NostrSigner>>,
|
||||||
|
|
||||||
|
/// Signer's public key
|
||||||
|
signer_pkey: RwLock<Option<PublicKey>>,
|
||||||
|
|
||||||
|
/// Whether coop is creating a new identity
|
||||||
|
creating: AtomicBool,
|
||||||
|
|
||||||
|
/// By default, Coop generates a new signer for new users.
|
||||||
|
///
|
||||||
|
/// This flag indicates whether the signer is user-owned or Coop-generated.
|
||||||
|
owned: AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CoopSigner {
|
impl CoopSigner {
|
||||||
@@ -17,6 +29,9 @@ impl CoopSigner {
|
|||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
signer: RwLock::new(signer.into_nostr_signer()),
|
signer: RwLock::new(signer.into_nostr_signer()),
|
||||||
|
signer_pkey: RwLock::new(None),
|
||||||
|
creating: AtomicBool::new(false),
|
||||||
|
owned: AtomicBool::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,13 +40,39 @@ impl CoopSigner {
|
|||||||
self.signer.read().await.clone()
|
self.signer.read().await.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get public key
|
||||||
|
pub fn public_key(&self) -> Option<PublicKey> {
|
||||||
|
self.signer_pkey.read_blocking().to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the flag indicating whether the signer is creating a new identity.
|
||||||
|
pub fn creating(&self) -> bool {
|
||||||
|
self.creating.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the flag indicating whether the signer is user-owned.
|
||||||
|
pub fn owned(&self) -> bool {
|
||||||
|
self.owned.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
|
||||||
/// Switch the current signer to a new signer.
|
/// Switch the current signer to a new signer.
|
||||||
pub async fn switch<T>(&self, new: T)
|
pub async fn switch<T>(&self, new: T, owned: bool)
|
||||||
where
|
where
|
||||||
T: IntoNostrSigner,
|
T: IntoNostrSigner,
|
||||||
{
|
{
|
||||||
|
let new_signer = new.into_nostr_signer();
|
||||||
|
let public_key = new_signer.get_public_key().await.ok();
|
||||||
let mut signer = self.signer.write().await;
|
let mut signer = self.signer.write().await;
|
||||||
*signer = new.into_nostr_signer();
|
let mut signer_pkey = self.signer_pkey.write().await;
|
||||||
|
|
||||||
|
// Switch to the new signer
|
||||||
|
*signer = new_signer;
|
||||||
|
|
||||||
|
// Update the public key
|
||||||
|
*signer_pkey = public_key;
|
||||||
|
|
||||||
|
// Update the owned flag
|
||||||
|
self.owned.store(owned, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user