Compare commits

...

3 Commits

Author SHA1 Message Date
reya
a5255fa503 chore: bump version 2024-07-31 12:51:41 +07:00
reya
954a17b541 fix: build on linux 2024-07-31 12:51:17 +07:00
reya
a55b31b0e6 feat: add keyring support for linux and windows 2024-07-31 10:59:54 +07:00
10 changed files with 201 additions and 190 deletions

View File

@@ -18,10 +18,10 @@ jobs:
args: "--target x86_64-apple-darwin" args: "--target x86_64-apple-darwin"
- platform: "macos-latest" # for Intel based macs. - platform: "macos-latest" # for Intel based macs.
args: "--target universal-apple-darwin" args: "--target universal-apple-darwin"
#- platform: 'ubuntu-22.04' - platform: 'ubuntu-22.04'
# args: '' args: ''
#- platform: 'windows-latest' - platform: 'windows-latest'
# args: '--target x86_64-pc-windows-msvc' args: '--target x86_64-pc-windows-msvc'
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View File

@@ -4,12 +4,7 @@ import { type Result, commands } from "./commands";
export const NostrAccount = { export const NostrAccount = {
getAccounts: async () => { getAccounts: async () => {
const query = await commands.getAccounts(); const query = await commands.getAccounts();
return query;
if (query.status === "ok") {
return query.data;
} else {
return [];
}
}, },
loadAccount: async (npub: string) => { loadAccount: async (npub: string) => {
const bunker: string = localStorage.getItem(`${npub}_bunker`); const bunker: string = localStorage.getItem(`${npub}_bunker`);

View File

@@ -44,13 +44,8 @@ try {
else return { status: "error", error: e as any }; else return { status: "error", error: e as any };
} }
}, },
async getAccounts() : Promise<Result<string[], string>> { async getAccounts() : Promise<string[]> {
try { return await TAURI_INVOKE("get_accounts");
return { status: "ok", data: await TAURI_INVOKE("get_accounts") };
} catch (e) {
if(e instanceof Error) throw e;
else return { status: "error", error: e as any };
}
}, },
async createAccount() : Promise<Result<Account, string>> { async createAccount() : Promise<Result<Account, string>> {
try { try {

51
src-tauri/Cargo.lock generated
View File

@@ -1136,6 +1136,30 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a" checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
[[package]]
name = "dbus"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b"
dependencies = [
"libc",
"libdbus-sys",
"winapi",
]
[[package]]
name = "dbus-secret-service"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1caa0c241c01ad8d99a78d553567d38f873dd3ac16eca33a5370d650ab25584e"
dependencies = [
"dbus",
"futures-util",
"num",
"once_cell",
"rand 0.8.5",
]
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.11" version = "0.3.11"
@@ -2602,23 +2626,21 @@ dependencies = [
[[package]] [[package]]
name = "keyring" name = "keyring"
version = "2.3.3" version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "363387f0019d714aa60cc30ab4fe501a747f4c08fc58f069dd14be971bd495a0" checksum = "c118b1bc529b034aad851808f41f49a69a337d10e112039e7f342e5fd514635b"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"lazy_static", "dbus-secret-service",
"linux-keyutils",
"secret-service",
"security-framework", "security-framework",
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "keyring-search" name = "keyring-search"
version = "0.2.2" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61d87b1244397d73833b1ba785317621049558a9755026dc947b411e05eb9bd6" checksum = "8fba83ff0a0efb658afeaaa6de89c7abd3ccd34333f5a36d5dae417334fcd488"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"lazy_static", "lazy_static",
@@ -2684,6 +2706,15 @@ version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "libdbus-sys"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72"
dependencies = [
"pkg-config",
]
[[package]] [[package]]
name = "libloading" name = "libloading"
version = "0.7.4" version = "0.7.4"
@@ -4653,9 +4684,9 @@ dependencies = [
[[package]] [[package]]
name = "secret-service" name = "secret-service"
version = "3.1.0" version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5204d39df37f06d1944935232fd2dfe05008def7ca599bf28c0800366c8a8f9" checksum = "e4d35ad99a181be0a60ffcbe85d680d98f87bdc4d7644ade319b87076b9dbfd4"
dependencies = [ dependencies = [
"aes", "aes",
"cbc", "cbc",
@@ -4667,7 +4698,7 @@ dependencies = [
"rand 0.8.5", "rand 0.8.5",
"serde", "serde",
"sha2", "sha2",
"zbus 3.15.2", "zbus 4.3.1",
] ]
[[package]] [[package]]

View File

@@ -16,11 +16,11 @@ tokio = { version = "1", features = ["full"] }
serde_json = "1.0" serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
tauri = { version = "2.0.0-beta", features = [ tauri = { version = "2.0.0-beta", features = [
"unstable", "unstable",
"tray-icon", "tray-icon",
"macos-private-api", "macos-private-api",
"native-tls-vendored", "native-tls-vendored",
"protocol-asset", "protocol-asset",
] } ] }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
@@ -34,18 +34,22 @@ tauri-plugin-shell = { git = "https://github.com/tauri-apps/plugins-workspace",
tauri-plugin-updater = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-updater = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" } tauri-plugin-upload = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-specta = { git = "https://github.com/reyamir/tauri-specta", branch = "feat/tauri-v2", features = [ tauri-specta = { git = "https://github.com/reyamir/tauri-specta", branch = "feat/tauri-v2", features = [
"typescript", "typescript",
] } ] }
tauri-plugin-theme = "0.4.1" tauri-plugin-theme = "0.4.1"
tauri-plugin-decorum = { git = "https://github.com/reyamir/tauri-plugin-decorum", branch = "feat/tauri-v2" } tauri-plugin-decorum = { git = "https://github.com/reyamir/tauri-plugin-decorum", branch = "feat/tauri-v2" }
specta = "^2.0.0-rc.12" specta = "^2.0.0-rc.12"
keyring = "2"
keyring-search = "0.2.0"
reqwest = "0.12.4" reqwest = "0.12.4"
url = "2.5.0" url = "2.5.0"
futures = "0.3.30" futures = "0.3.30"
linkify = "0.10.0" linkify = "0.10.0"
regex = "1.10.4" regex = "1.10.4"
keyring = { version = "3", features = [
"apple-native",
"windows-native",
"sync-secret-service",
] }
keyring-search = "1.2.0"
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.25.0" cocoa = "0.25.0"

View File

@@ -198,7 +198,7 @@ pub fn open_window(window: Window, app_handle: tauri::AppHandle) -> Result<(), S
&window.label, &window.label,
WebviewUrl::App(PathBuf::from(window.url)), WebviewUrl::App(PathBuf::from(window.url)),
) )
.title(title) .title(&window.title)
.min_inner_size(window.width, window.height) .min_inner_size(window.width, window.height)
.inner_size(window.width, window.height) .inner_size(window.width, window.height)
.minimizable(window.minimizable) .minimizable(window.minimizable)
@@ -218,7 +218,7 @@ pub fn open_window(window: Window, app_handle: tauri::AppHandle) -> Result<(), S
&window.label, &window.label,
WebviewUrl::App(PathBuf::from(window.url)), WebviewUrl::App(PathBuf::from(window.url)),
) )
.title(title) .title(&window.title)
.min_inner_size(window.width, window.height) .min_inner_size(window.width, window.height)
.inner_size(window.width, window.height) .inner_size(window.width, window.height)
.minimizable(window.minimizable) .minimizable(window.minimizable)
@@ -227,6 +227,7 @@ pub fn open_window(window: Window, app_handle: tauri::AppHandle) -> Result<(), S
.unwrap(); .unwrap();
// Set decoration // Set decoration
#[cfg(not(target_os = "linux"))]
window.create_overlay_titlebar().unwrap(); window.create_overlay_titlebar().unwrap();
// Restore native border // Restore native border

View File

@@ -140,7 +140,13 @@ fn main() {
builder.build().unwrap() builder.build().unwrap()
}; };
tauri::Builder::default() #[cfg(target_os = "macos")]
let builder = tauri::Builder::default().plugin(tauri_nspanel::init());
#[cfg(not(target_os = "macos"))]
let builder = tauri::Builder::default();
builder
.setup(|app| { .setup(|app| {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
app.handle().plugin(tauri_nspanel::init()).unwrap(); app.handle().plugin(tauri_nspanel::init()).unwrap();
@@ -239,8 +245,6 @@ fn main() {
Ok(()) Ok(())
}) })
.enable_macos_default_menu(false)
.plugin(tauri_nspanel::init())
.plugin(tauri_plugin_theme::init(ctx.config_mut())) .plugin(tauri_plugin_theme::init(ctx.config_mut()))
.plugin(tauri_plugin_decorum::init()) .plugin(tauri_plugin_decorum::init())
.plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_clipboard_manager::init())

View File

@@ -1,3 +1,4 @@
#[cfg(target_os = "macos")]
use crate::commands::tray::create_tray_panel; use crate::commands::tray::create_tray_panel;
use crate::nostr::event::RichEvent; use crate::nostr::event::RichEvent;
use crate::nostr::internal::{get_user_settings, init_nip65}; use crate::nostr::internal::{get_user_settings, init_nip65};
@@ -22,22 +23,17 @@ pub struct Account {
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub fn get_accounts() -> Result<Vec<String>, String> { pub fn get_accounts() -> Vec<String> {
let search = Search::new().map_err(|e| e.to_string())?; let search = Search::new().expect("Unexpected.");
let results = search.by("Account", "nostr_secret"); let results = search.by_service("Lume");
let list = List::list_credentials(&results, Limit::All);
let accounts: HashSet<String> = list
.split_whitespace()
.filter(|v| v.starts_with("npub1"))
.map(String::from)
.collect();
match List::list_credentials(results, Limit::All) { accounts.into_iter().collect()
Ok(list) => {
let accounts: HashSet<String> = list
.split_whitespace()
.filter(|v| v.starts_with("npub1"))
.map(String::from)
.collect();
Ok(accounts.into_iter().collect())
}
Err(_) => Err("Empty.".into()),
}
} }
#[tauri::command] #[tauri::command]
@@ -58,7 +54,7 @@ pub fn create_account() -> Result<Account, String> {
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub fn get_private_key(npub: &str) -> Result<String, String> { pub fn get_private_key(npub: &str) -> Result<String, String> {
let keyring = Entry::new(npub, "nostr_secret").unwrap(); let keyring = Entry::new("Lume", npub).unwrap();
if let Ok(nsec) = keyring.get_password() { if let Ok(nsec) = keyring.get_password() {
let secret_key = SecretKey::from_bech32(nsec).unwrap(); let secret_key = SecretKey::from_bech32(nsec).unwrap();
@@ -90,7 +86,7 @@ pub async fn save_account(
let npub = nostr_keys.public_key().to_bech32().unwrap(); let npub = nostr_keys.public_key().to_bech32().unwrap();
let nsec = nostr_keys.secret_key().unwrap().to_bech32().unwrap(); let nsec = nostr_keys.secret_key().unwrap().to_bech32().unwrap();
let keyring = Entry::new(&npub, "nostr_secret").unwrap(); let keyring = Entry::new("Lume", &npub).unwrap();
let _ = keyring.set_password(&nsec); let _ = keyring.set_password(&nsec);
let signer = NostrSigner::Keys(nostr_keys); let signer = NostrSigner::Keys(nostr_keys);
@@ -121,7 +117,7 @@ pub async fn connect_remote_account(uri: &str, state: State<'_, Nostr>) -> Resul
match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(120), None).await { match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(120), None).await {
Ok(signer) => { Ok(signer) => {
let keyring = Entry::new(&remote_npub, "nostr_secret").unwrap(); let keyring = Entry::new("Lume", &remote_npub).unwrap();
let _ = keyring.set_password(&app_secret); let _ = keyring.set_password(&app_secret);
// Update signer // Update signer
@@ -139,7 +135,7 @@ pub async fn connect_remote_account(uri: &str, state: State<'_, Nostr>) -> Resul
#[tauri::command] #[tauri::command]
#[specta::specta] #[specta::specta]
pub async fn get_encrypted_key(npub: &str, password: &str) -> Result<String, String> { pub async fn get_encrypted_key(npub: &str, password: &str) -> Result<String, String> {
let keyring = Entry::new(npub, "nostr_secret").unwrap(); let keyring = Entry::new("Lume", npub).unwrap();
if let Ok(nsec) = keyring.get_password() { if let Ok(nsec) = keyring.get_password() {
let secret_key = SecretKey::from_bech32(nsec).unwrap(); let secret_key = SecretKey::from_bech32(nsec).unwrap();
@@ -165,7 +161,7 @@ pub async fn load_account(
) -> Result<bool, String> { ) -> Result<bool, String> {
let handle = app.clone(); let handle = app.clone();
let client = &state.client; let client = &state.client;
let keyring = Entry::new(npub, "nostr_secret").unwrap(); let keyring = Entry::new("Lume", npub).unwrap();
let password = match keyring.get_password() { let password = match keyring.get_password() {
Ok(pw) => pw, Ok(pw) => pw,

View File

@@ -359,7 +359,7 @@ pub async fn remove_wallet(state: State<'_, Nostr>) -> Result<(), ()> {
let client = &state.client; let client = &state.client;
let keyring = Entry::new("Lume Secret", "Bitcoin Connect").unwrap(); let keyring = Entry::new("Lume Secret", "Bitcoin Connect").unwrap();
match keyring.delete_password() { match keyring.delete_credential() {
Ok(_) => { Ok(_) => {
client.unset_zapper().await; client.unset_zapper().await;
Ok(()) Ok(())

View File

@@ -1,131 +1,116 @@
{ {
"$schema": "../node_modules/@tauri-apps/cli/schema.json", "$schema": "../node_modules/@tauri-apps/cli/schema.json",
"productName": "Lume", "productName": "Lume",
"version": "4.0.14", "version": "4.0.15",
"identifier": "nu.lume.Lume", "identifier": "nu.lume.Lume",
"build": { "build": {
"beforeBuildCommand": "pnpm desktop:build", "beforeBuildCommand": "pnpm desktop:build",
"beforeDevCommand": "pnpm desktop:dev", "beforeDevCommand": "pnpm desktop:dev",
"devUrl": "http://localhost:3000", "devUrl": "http://localhost:3000",
"frontendDist": "../dist" "frontendDist": "../dist"
}, },
"app": { "app": {
"macOSPrivateApi": true, "macOSPrivateApi": true,
"withGlobalTauri": true, "withGlobalTauri": true,
"security": { "security": {
"assetProtocol": { "assetProtocol": {
"enable": true, "enable": true,
"scope": [ "scope": [
"$APPDATA/*", "$APPDATA/*",
"$DATA/*", "$DATA/*",
"$LOCALDATA/*", "$LOCALDATA/*",
"$DESKTOP/*", "$DESKTOP/*",
"$DOCUMENT/*", "$DOCUMENT/*",
"$DOWNLOAD/*", "$DOWNLOAD/*",
"$HOME/*", "$HOME/*",
"$PICTURE/*", "$PICTURE/*",
"$PUBLIC/*", "$PUBLIC/*",
"$VIDEO/*", "$VIDEO/*",
"$APPCONFIG/*", "$APPCONFIG/*",
"$RESOURCE/*" "$RESOURCE/*"
] ]
} }
} }
}, },
"bundle": { "bundle": {
"licenseFile": "../LICENSE", "licenseFile": "../LICENSE",
"homepage": "https://lume.nu", "homepage": "https://lume.nu",
"longDescription": "nostr client for desktop", "longDescription": "nostr client for desktop",
"shortDescription": "nostr client", "shortDescription": "nostr client",
"targets": "all", "targets": "all",
"active": true, "active": true,
"category": "SocialNetworking", "category": "SocialNetworking",
"resources": [ "resources": [
"resources/*", "resources/*",
"locales/*" "locales/*"
], ],
"icon": [ "icon": [
"icons/32x32.png", "icons/32x32.png",
"icons/128x128.png", "icons/128x128.png",
"icons/128x128@2x.png", "icons/128x128@2x.png",
"icons/icon.icns", "icons/icon.icns",
"icons/icon.ico" "icons/icon.ico"
], ],
"linux": { "linux": {
"appimage": { "appimage": {
"bundleMediaFramework": true, "bundleMediaFramework": true,
"files": {} "files": {}
}, },
"deb": { "deb": {
"files": {} "files": {}
}, },
"rpm": { "rpm": {
"epoch": 0, "epoch": 0,
"files": {}, "files": {},
"release": "1" "release": "1"
} }
}, },
"macOS": { "macOS": {
"dmg": { "minimumSystemVersion": "10.15"
"appPosition": { },
"x": 180, "windows": {
"y": 170 "allowDowngrades": true,
}, "certificateThumbprint": null,
"applicationFolderPosition": { "digestAlgorithm": "sha256",
"x": 480, "nsis": null,
"y": 170 "timestampUrl": null,
}, "tsp": false,
"windowSize": { "webviewFixedRuntimePath": null,
"height": 400, "webviewInstallMode": {
"width": 660 "silent": true,
} "type": "downloadBootstrapper"
}, },
"files": {}, "wix": null
"minimumSystemVersion": "10.15" },
}, "fileAssociations": [
"windows": { {
"allowDowngrades": true, "name": "bech32",
"certificateThumbprint": null, "description": "Nostr BECH32",
"digestAlgorithm": "sha256", "ext": [
"nsis": null, "npub",
"timestampUrl": null, "nsec",
"tsp": false, "nprofile",
"webviewFixedRuntimePath": null, "nevent",
"webviewInstallMode": { "naddr",
"silent": true, "nrelay"
"type": "downloadBootstrapper" ],
}, "role": "Viewer"
"wix": null }
}, ],
"fileAssociations": [ "createUpdaterArtifacts": true
{ },
"name": "bech32", "plugins": {
"description": "Nostr BECH32", "updater": {
"ext": [ "active": true,
"npub", "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK",
"nsec", "windows": {
"nprofile", "installMode": "quiet"
"nevent", },
"naddr", "endpoints": [
"nrelay" "https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}",
], "https://lus.reya3772.workers.dev/{{target}}/{{current_version}}",
"role": "Viewer" "https://github.com/lumehq/lume/releases/latest/download/latest.json"
} ]
], }
"createUpdaterArtifacts": true }
},
"plugins": {
"updater": {
"active": true,
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU3OTdCMkM3RjU5QzE2NzkKUldSNUZwejF4N0tYNTVHYjMrU0JkL090SlEyNUVLYU5TM2hTU3RXSWtEWngrZWJ4a0pydUhXZHEK",
"windows": {
"installMode": "quiet"
},
"endpoints": [
"https://lus.reya3772.workers.dev/v1/{{target}}/{{arch}}/{{current_version}}",
"https://lus.reya3772.workers.dev/{{target}}/{{current_version}}",
"https://github.com/lumehq/lume/releases/latest/download/latest.json"
]
}
}
} }