Bump to v0.6.1 — native file upload, mention names, connection stability

- Native file picker (+) in compose box uploads via Rust backend (reqwest)
- Pasting a local file path auto-uploads instead of inserting text
- @mentions resolve to profile display names via useProfile hook
- Connection indicator uses 15s grace period before showing offline
- Upload uses correct nostr.build v2 API; Rust-side multipart for native picks
- Content parser extracted to src/lib/parsing.ts
This commit is contained in:
Jure
2026-03-18 14:55:29 +01:00
parent ef189932e6
commit fbf05e8f90
16 changed files with 776 additions and 253 deletions
+116
View File
@@ -234,6 +234,28 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "aws-lc-rs"
version = "1.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf"
dependencies = [
"aws-lc-sys",
"zeroize",
]
[[package]]
name = "aws-lc-sys"
version = "0.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e"
dependencies = [
"cc",
"cmake",
"dunce",
"fs_extra",
]
[[package]]
name = "base64"
version = "0.21.7"
@@ -414,6 +436,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
]
@@ -468,6 +492,15 @@ dependencies = [
"windows-link 0.2.1",
]
[[package]]
name = "cmake"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d"
dependencies = [
"cc",
]
[[package]]
name = "combine"
version = "4.6.7"
@@ -1083,6 +1116,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fs_extra"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
[[package]]
name = "futf"
version = "0.1.5"
@@ -1957,6 +1996,16 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
dependencies = [
"getrandom 0.3.4",
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.91"
@@ -2203,6 +2252,16 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "minisign-verify"
version = "0.2.5"
@@ -2954,6 +3013,7 @@ version = "0.11.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
dependencies = [
"aws-lc-rs",
"bytes",
"getrandom 0.3.4",
"lru-slab",
@@ -3259,8 +3319,10 @@ dependencies = [
"hyper-util",
"js-sys",
"log",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"quinn",
"rustls",
"rustls-pki-types",
"rustls-platform-verifier",
@@ -3280,6 +3342,30 @@ dependencies = [
"web-sys",
]
[[package]]
name = "rfd"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672"
dependencies = [
"block2",
"dispatch2",
"glib-sys",
"gobject-sys",
"gtk-sys",
"js-sys",
"log",
"objc2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation",
"raw-window-handle",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows-sys 0.60.2",
]
[[package]]
name = "ring"
version = "0.17.14"
@@ -3342,6 +3428,7 @@ version = "0.23.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
dependencies = [
"aws-lc-rs",
"once_cell",
"ring",
"rustls-pki-types",
@@ -3405,6 +3492,7 @@ version = "0.103.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53"
dependencies = [
"aws-lc-rs",
"ring",
"rustls-pki-types",
"untrusted",
@@ -4173,6 +4261,24 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-plugin-dialog"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9204b425d9be8d12aa60c2a83a289cf7d1caae40f57f336ed1155b3a5c0e359b"
dependencies = [
"log",
"raw-window-handle",
"rfd",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"tauri-plugin-fs",
"thiserror 2.0.18",
"url",
]
[[package]]
name = "tauri-plugin-fs"
version = "2.4.5"
@@ -4826,6 +4932,12 @@ dependencies = [
"unic-common",
]
[[package]]
name = "unicase"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
[[package]]
name = "unicode-ident"
version = "1.0.24"
@@ -5827,11 +5939,15 @@ name = "wrystr"
version = "0.6.0"
dependencies = [
"keyring",
"mime_guess",
"reqwest 0.13.2",
"rusqlite",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-http",
"tauri-plugin-opener",
"tauri-plugin-process",
+5 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "wrystr"
version = "0.6.0"
version = "0.6.1"
description = "Cross-platform Nostr desktop client with Lightning integration"
authors = ["hoornet"]
edition = "2021"
@@ -27,4 +27,8 @@ serde_json = "1"
keyring = { version = "3", features = ["apple-native", "windows-native", "linux-native"] }
rusqlite = { version = "0.32", features = ["bundled"] }
tauri-plugin-http = "2.5.7"
tauri-plugin-dialog = "2.6.0"
tauri-plugin-fs = "2.4.5"
reqwest = { version = "0.13.2", default-features = false, features = ["multipart", "rustls"] }
mime_guess = "2.0.5"
+7
View File
@@ -13,6 +13,13 @@
"allow": [
{ "url": "https://nostr.build/**" }
]
},
"dialog:default",
{
"identifier": "fs:allow-read-file",
"allow": [
{ "path": "**" }
]
}
]
}
+48
View File
@@ -37,6 +37,51 @@ fn delete_nsec(pubkey: String) -> Result<(), String> {
}
}
// ── File upload ─────────────────────────────────────────────────────────────
#[tauri::command]
async fn upload_file(path: String) -> Result<String, String> {
let file_bytes = std::fs::read(&path).map_err(|e| format!("Failed to read file: {e}"))?;
let file_name = std::path::Path::new(&path)
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("file")
.to_string();
let mime = mime_guess::from_path(&path)
.first_or_octet_stream()
.to_string();
let part = reqwest::multipart::Part::bytes(file_bytes)
.file_name(file_name)
.mime_str(&mime)
.map_err(|e| format!("MIME error: {e}"))?;
let form = reqwest::multipart::Form::new().part("file", part);
let client = reqwest::Client::new();
let resp = client
.post("https://nostr.build/api/v2/upload/files")
.multipart(form)
.send()
.await
.map_err(|e| format!("Upload request failed: {e}"))?;
if !resp.status().is_success() {
return Err(format!("Upload failed (HTTP {})", resp.status()));
}
let data: serde_json::Value = resp
.json()
.await
.map_err(|e| format!("Failed to parse response: {e}"))?;
if data["status"] == "success" {
if let Some(url) = data["data"][0]["url"].as_str() {
return Ok(url.to_string());
}
}
Err(data["message"].as_str().unwrap_or("Upload failed — no URL returned").to_string())
}
// ── SQLite note/profile cache ────────────────────────────────────────────────
struct DbState(Mutex<Connection>);
@@ -142,6 +187,8 @@ pub fn run() {
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.setup(|app| {
// ── SQLite ───────────────────────────────────────────────────────
let data_dir = app.path().app_data_dir()?;
@@ -203,6 +250,7 @@ pub fn run() {
store_nsec,
load_nsec,
delete_nsec,
upload_file,
db_save_notes,
db_load_feed,
db_save_profile,
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Wrystr",
"version": "0.6.0",
"version": "0.6.1",
"identifier": "com.hoornet.wrystr",
"build": {
"beforeDevCommand": "npm run dev",