feat: make the web version fully working #67

Merged
reya merged 9 commits from web into master 2026-10-25 13:10:52 +00:00
8 changed files with 420 additions and 25 deletions
Showing only changes of commit ded0e27a56 - Show all commits
Generated
+318 -11
View File
@@ -82,6 +82,18 @@ dependencies = [
"windows-core 0.62.2",
]
[[package]]
name = "accessory"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc86a613208ca7d144ca24f6ec49c5cdfa5c05a46f2f7ab5880ff99371f165de"
dependencies = [
"macroific 3.1.0",
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "addr2line"
version = "0.25.1"
@@ -1391,6 +1403,7 @@ dependencies = [
"ui",
"universal-time 0.3.1 (git+https://github.com/shadowylab/universal-time)",
"wasm-bindgen",
"wasm-bindgen-futures",
"workspace",
]
@@ -1733,6 +1746,20 @@ dependencies = [
"thiserror 2.0.21",
]
[[package]]
name = "delegate-display"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54e3a499943fd5180aeffcb708164ffb22125ceeccb05491b5297981d37d6249"
dependencies = [
"impartial-ord",
"itoa",
"macroific 3.1.0",
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "deranged"
version = "0.5.9"
@@ -1762,6 +1789,7 @@ dependencies = [
"quote",
"rustc_version",
"syn 2.0.119",
"unicode-xid",
]
[[package]]
@@ -1826,7 +1854,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users 0.5.3",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -2054,7 +2082,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -2113,6 +2141,30 @@ dependencies = [
"zune-inflate",
]
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]]
name = "fallible-streaming-iterator"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fancy_constructor"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a8211ab12c36b63c269e17873331dc1da196a3edb7a5c79015677ef972da34a"
dependencies = [
"macroific 3.1.0",
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "faster-hex"
version = "0.10.1"
@@ -3912,6 +3964,51 @@ version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f"
[[package]]
name = "impartial-ord"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc680e03d1a08bdc1c01b60e0c39723430ced63d8cabd93cee0449b6ba916a25"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "indexed_db_futures"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ff41758cbd104e91033bb53bc449bec7eea65652960c81eddf3fc146ecea19"
dependencies = [
"accessory",
"cfg-if",
"delegate-display",
"derive_more",
"fancy_constructor",
"indexed_db_futures_macros_internal",
"js-sys",
"sealed 0.6.0",
"smallvec",
"thiserror 2.0.21",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "indexed_db_futures_macros_internal"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caeba94923b68f254abef921cea7e7698bf4675fdd89d7c58bf1ed885b49a27d"
dependencies = [
"macroific 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "indexmap"
version = "1.9.3"
@@ -4310,6 +4407,17 @@ dependencies = [
"libc",
]
[[package]]
name = "libsqlite3-sys"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95b4103cffefa72eb8428cb6b47d6627161e51c2739fc5e3b734584157bc642a"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "linebender_resource_handle"
version = "0.1.1"
@@ -4487,6 +4595,102 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b"
[[package]]
name = "macroific"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89f276537b4b8f981bf1c13d79470980f71134b7bdcc5e6e911e910e556b0285"
dependencies = [
"macroific_attr_parse 2.0.0",
"macroific_core 2.0.0",
"macroific_macro 2.0.0",
]
[[package]]
name = "macroific"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc8ab95c98294764c0f1eacebdb5b027849201b71fbc383871fe991a1de7eb83"
dependencies = [
"macroific_attr_parse 3.1.0",
"macroific_core 3.1.0",
"macroific_macro 3.1.0",
]
[[package]]
name = "macroific_attr_parse"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad4023761b45fcd36abed8fb7ae6a80456b0a38102d55e89a57d9a594a236be9"
dependencies = [
"proc-macro2",
"quote",
"sealed 0.6.0",
"syn 2.0.119",
]
[[package]]
name = "macroific_attr_parse"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf9b7bdb92825e6a507392b12f0570ade17480be20f4ca951b9071b40deba1d1"
dependencies = [
"proc-macro2",
"quote",
"sealed 0.7.0",
"syn 3.0.9",
]
[[package]]
name = "macroific_core"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a7594d3c14916fa55bef7e9d18c5daa9ed410dd37504251e4b75bbdeec33e3"
dependencies = [
"proc-macro2",
"quote",
"sealed 0.6.0",
"syn 2.0.119",
]
[[package]]
name = "macroific_core"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc880da2bc00d6d87f748805e242d670e248d1b9b6fcef3190503210b6cf056"
dependencies = [
"proc-macro2",
"quote",
"sealed 0.7.0",
"syn 3.0.9",
]
[[package]]
name = "macroific_macro"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4da6f2ed796261b0a74e2b52b42c693bb6dee1effba3a482c49592659f824b3b"
dependencies = [
"macroific_attr_parse 2.0.0",
"macroific_core 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "macroific_macro"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201faf668c264432727fb64e44407bcfcf1f5f8153bf4ec248eb6bbe4a39b144"
dependencies = [
"macroific_attr_parse 3.1.0",
"macroific_core 3.1.0",
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@@ -5006,6 +5210,19 @@ dependencies = [
"universal-time 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nostr-sqlite"
version = "0.45.2"
source = "git+https://github.com/rust-nostr/nostr#f7ebc0a88ea27ac4e3d74b941e3a44ddb10b306c"
dependencies = [
"async-utility",
"nostr",
"nostr-database",
"rusqlite",
"serde_json",
"tokio",
]
[[package]]
name = "notify"
version = "8.2.0"
@@ -5062,7 +5279,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -6150,7 +6367,7 @@ dependencies = [
"once_cell",
"socket2",
"tracing",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -6601,6 +6818,30 @@ dependencies = [
"memchr",
]
[[package]]
name = "rsqlite-vfs"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c"
dependencies = [
"hashbrown 0.16.1",
"thiserror 2.0.21",
]
[[package]]
name = "rusqlite"
version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1c93dd1c9683b438c392c492109cb702b8090b2bfc8fed6f6e4eb4523f17af3"
dependencies = [
"bitflags 2.13.2",
"fallible-iterator",
"fallible-streaming-iterator",
"libsqlite3-sys",
"smallvec",
"sqlite-wasm-rs",
]
[[package]]
name = "rust-embed"
version = "8.13.0"
@@ -6723,7 +6964,7 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -6791,7 +7032,7 @@ dependencies = [
"security-framework",
"security-framework-sys",
"webpki-root-certs",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -6961,6 +7202,28 @@ version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]]
name = "sealed"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22f968c5ea23d555e670b449c1c5e7b2fc399fdaec1d304a17cd48e288abc107"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.119",
]
[[package]]
name = "sealed"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b68e2ea526d9fb32f23ca8894fb5da9e743f34c2f41701f0501dc8a25c4b343"
dependencies = [
"proc-macro2",
"quote",
"syn 3.0.9",
]
[[package]]
name = "secp256k1"
version = "0.30.0"
@@ -7397,7 +7660,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -7427,6 +7690,34 @@ dependencies = [
"bitflags 2.13.2",
]
[[package]]
name = "sqlite-wasm-rs"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75"
dependencies = [
"cc",
"js-sys",
"rsqlite-vfs",
"wasm-bindgen",
]
[[package]]
name = "sqlite-wasm-vfs"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7a5c9ac229421d577bb5a9bb59048838509958b218dd4e0b3c1214a87c361e"
dependencies = [
"indexed_db_futures",
"js-sys",
"rsqlite-vfs",
"thiserror 2.0.21",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -7448,6 +7739,7 @@ dependencies = [
"gpui_tokio",
"instant",
"js-sys",
"log",
"mime_guess",
"nostr",
"nostr-blossom",
@@ -7457,10 +7749,13 @@ dependencies = [
"nostr-lmdb",
"nostr-memory",
"nostr-sdk",
"nostr-sqlite",
"rustls",
"serde_json",
"sha2 0.10.9",
"smol",
"sqlite-wasm-rs",
"sqlite-wasm-vfs",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
@@ -7723,7 +8018,7 @@ dependencies = [
"getrandom 0.4.3",
"once_cell",
"rustix",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -8254,7 +8549,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
dependencies = [
"memoffset",
"tempfile",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -8354,6 +8649,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "universal-hash"
version = "0.5.1"
@@ -8528,6 +8829,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
@@ -9052,7 +9359,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.48.0",
"windows-sys 0.61.2",
]
[[package]]
@@ -9677,7 +9984,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
dependencies = [
"cfg-if",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
+1
View File
@@ -34,6 +34,7 @@ nostr-gossip-memory = { git = "https://github.com/rust-nostr/nostr" }
nostr-connect = { git = "https://github.com/rust-nostr/nostr" }
nostr-browser-signer = { git = "https://github.com/rust-nostr/nostr" }
nostr-sdk = { git = "https://github.com/rust-nostr/nostr" }
nostr-sqlite = { git = "https://github.com/rust-nostr/nostr" }
nostr = { git = "https://github.com/rust-nostr/nostr", features = [ "nip59", "nip49", "nip44", "nip98" ] }
# Crypto (NIP-17 encrypted file messages)
+4
View File
@@ -20,6 +20,7 @@ futures.workspace = true
anyhow.workspace = true
webbrowser.workspace = true
serde_json.workspace = true
log.workspace = true
mime_guess = "2.0.4"
@@ -31,6 +32,7 @@ data-encoding.workspace = true
js-sys = "0.3"
nostr-browser-signer.workspace = true
nostr-memory.workspace = true
nostr-sqlite.workspace = true
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
web-sys = { version = "0.3", features = [
@@ -43,6 +45,8 @@ web-sys = { version = "0.3", features = [
"Url",
"Window",
] }
sqlite-wasm-rs = "0.5"
sqlite-wasm-vfs = "0.2"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
browser-signer-proxy = { path = "../browser-signer-proxy" }
+3 -4
View File
@@ -16,8 +16,6 @@ use nostr_connect::prelude::*;
use nostr_gossip_memory::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
use nostr_lmdb::prelude::*;
#[cfg(target_arch = "wasm32")]
use nostr_memory::prelude::*;
use nostr_sdk::prelude::*;
mod blossom;
@@ -28,6 +26,8 @@ mod nip05;
mod nip4e;
mod signer;
#[cfg(target_arch = "wasm32")]
pub mod web_database;
#[cfg(target_arch = "wasm32")]
pub mod web_file;
@@ -114,7 +114,6 @@ impl NostrRegistry {
let signer = UniversalSigner::new(Keys::generate());
let authenticator = SignerAuthenticator::new(signer.clone());
// Construct the nostr lmdb instance
#[cfg(not(target_arch = "wasm32"))]
let database = cx.foreground_executor().block_on(async move {
NostrLmdb::open(config_dir().join("nostr"))
@@ -123,7 +122,7 @@ impl NostrRegistry {
});
#[cfg(target_arch = "wasm32")]
let database = MemoryDatabase::unbounded();
let database = web_database::take();
// Construct the nostr client
let client = ClientBuilder::default()
+62
View File
@@ -0,0 +1,62 @@
use std::cell::RefCell;
use std::sync::Arc;
use nostr_memory::prelude::*;
use nostr_sqlite::prelude::NostrSqlite;
use sqlite_wasm_rs::WasmOsCallback;
use sqlite_wasm_vfs::relaxed_idb;
const DATABASE_PATH: &str = "coop.sqlite3";
const VFS_NAME: &str = "coop-relaxed-idb";
thread_local! {
static DATABASE: RefCell<Option<NostrSqlite>> = const { RefCell::new(None) };
}
/// Install the IndexedDB storage backend and open the database.
pub async fn open() {
match open_persistent().await {
Some(database) => DATABASE.with(|slot| *slot.borrow_mut() = Some(database)),
None => log::error!("Falling back to the in-memory nostr database"),
}
}
/// Hand the opened database to the client constructor
pub(crate) fn take() -> Arc<dyn NostrDatabase> {
let database = DATABASE.with(|slot| slot.borrow_mut().take());
match database {
Some(database) => Arc::new(database),
None => {
log::error!("Persistent web database was not opened, falling back to memory");
Arc::new(MemoryDatabase::unbounded())
}
}
}
/// Open the database on IndexedDB storage, or `None` when unavailable
async fn open_persistent() -> Option<NostrSqlite> {
let options = relaxed_idb::RelaxedIdbCfgBuilder::new()
.vfs_name(VFS_NAME)
.build();
if let Err(e) = relaxed_idb::install::<WasmOsCallback>(&options, true).await {
log::warn!("IndexedDB storage unavailable: {e:?}");
return None;
}
match NostrSqlite::builder()
.persistent_with_vfs(DATABASE_PATH, VFS_NAME)
.build()
.await
{
Ok(database) => {
log::info!("Nostr database opened on IndexedDB storage");
Some(database)
}
Err(e) => {
log::error!("Failed to open the nostr database on IndexedDB: {e:?}");
None
}
}
}
+1
View File
@@ -30,6 +30,7 @@ console_error_panic_hook = "0.1"
tracing-wasm = "0.2"
console_log = "1.0"
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
universal-time = { git = "https://github.com/shadowylab/universal-time" }
+28 -10
View File
@@ -32,15 +32,34 @@ impl MonotonicClock for BrowserTimeProvider {
define_time_provider!(BrowserTimeProvider);
fn init_logging() {
// Called from both entry points; the first one wins
static ONCE: std::sync::OnceLock<()> = std::sync::OnceLock::new();
ONCE.get_or_init(|| {
console_error_panic_hook::set_once();
// Initialize logging to browser console
console_log::init_with_level(log::Level::Info).ok();
// Also initialize tracing for WASM
tracing_wasm::set_as_global_default();
});
}
/// Open the persistent nostr database before the app starts.
#[wasm_bindgen]
pub async fn open_database() -> Result<(), JsValue> {
init_logging();
state::web_database::open().await;
Ok(())
}
#[wasm_bindgen]
pub fn run() -> Result<(), JsValue> {
console_error_panic_hook::set_once();
// Initialize logging to browser console
console_log::init_with_level(log::Level::Info).expect("Failed to initialize logger");
// Also initialize tracing for WASM
tracing_wasm::set_as_global_default();
init_logging();
// Sets the panic hook and GPUI's console logger
gpui_platform::web_init();
@@ -59,12 +78,11 @@ pub fn run() -> Result<(), JsValue> {
APPLICATION.with(|application| {
*application.borrow_mut() = Some(app.run_embedded(|cx| {
gpui_kit::init(cx);
load_embedded_fonts(cx);
apply_web_fonts(cx);
// Initialize the framework before anything renders
gpui_kit::init(cx);
// Initialize settings
settings::init(cx);
+3
View File
@@ -7,6 +7,9 @@ async function init() {
const wasm = await import('./wasm/coop_web.js');
await wasm.default();
// Open the persistent nostr database before the app starts
await wasm.open_database();
// Initialize the story gallery
await wasm.run();