feat: rework multi account
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
use async_utility::thread::sleep;
|
||||
use keyring::Entry;
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use std::{str::FromStr, time::Duration};
|
||||
use tauri::{Emitter, State};
|
||||
use std::{fs, str::FromStr, time::Duration};
|
||||
use tauri::{Emitter, Manager, State};
|
||||
|
||||
use crate::{common::get_all_accounts, Nostr};
|
||||
|
||||
use super::sync::sync_account;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
|
||||
struct Account {
|
||||
secret_key: String,
|
||||
@@ -21,16 +24,27 @@ pub fn get_accounts() -> Vec<String> {
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn watch_account(id: String, state: State<'_, Nostr>) -> Result<String, String> {
|
||||
pub async fn watch_account(
|
||||
id: String,
|
||||
state: State<'_, Nostr>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<String, String> {
|
||||
let public_key = PublicKey::from_str(&id).map_err(|e| e.to_string())?;
|
||||
let npub = public_key.to_bech32().map_err(|e| e.to_string())?;
|
||||
let keyring = Entry::new("Lume Safe Storage", &npub).map_err(|e| e.to_string())?;
|
||||
|
||||
// Set empty password
|
||||
keyring.set_password("").map_err(|e| e.to_string())?;
|
||||
|
||||
// Run sync for this account
|
||||
sync_account(public_key, app_handle);
|
||||
|
||||
// Update state
|
||||
state.accounts.lock().unwrap().push(npub.clone());
|
||||
|
||||
// Fake loading
|
||||
sleep(Duration::from_secs(4)).await;
|
||||
|
||||
Ok(npub)
|
||||
}
|
||||
|
||||
@@ -40,6 +54,7 @@ pub async fn import_account(
|
||||
key: String,
|
||||
password: Option<String>,
|
||||
state: State<'_, Nostr>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
|
||||
@@ -54,10 +69,8 @@ pub async fn import_account(
|
||||
let hex = secret_key.to_secret_hex();
|
||||
let keys = Keys::new(secret_key);
|
||||
|
||||
let npub = keys
|
||||
.public_key()
|
||||
.to_bech32()
|
||||
.map_err(|err| err.to_string())?;
|
||||
let public_key = keys.public_key();
|
||||
let npub = public_key.to_bech32().map_err(|err| err.to_string())?;
|
||||
|
||||
let signer = NostrSigner::Keys(keys);
|
||||
let keyring = Entry::new("Lume Safe Storage", &npub).map_err(|e| e.to_string())?;
|
||||
@@ -73,6 +86,13 @@ pub async fn import_account(
|
||||
|
||||
// Update signer
|
||||
client.set_signer(Some(signer)).await;
|
||||
|
||||
// Run sync for this account
|
||||
sync_account(public_key, app_handle);
|
||||
|
||||
// Fake loading
|
||||
sleep(Duration::from_secs(4)).await;
|
||||
|
||||
// Update state
|
||||
state.accounts.lock().unwrap().push(npub.clone());
|
||||
|
||||
@@ -81,7 +101,11 @@ pub async fn import_account(
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn connect_account(uri: String, state: State<'_, Nostr>) -> Result<String, String> {
|
||||
pub async fn connect_account(
|
||||
uri: String,
|
||||
state: State<'_, Nostr>,
|
||||
app_handle: tauri::AppHandle,
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
|
||||
match NostrConnectURI::parse(uri.clone()) {
|
||||
@@ -94,6 +118,9 @@ pub async fn connect_account(uri: String, state: State<'_, Nostr>) -> Result<Str
|
||||
let remote_user = bunker_uri.signer_public_key().unwrap();
|
||||
let remote_npub = remote_user.to_bech32().unwrap();
|
||||
|
||||
// Run sync for this account
|
||||
sync_account(remote_user, app_handle);
|
||||
|
||||
match Nip46Signer::new(bunker_uri, app_keys, Duration::from_secs(120), None) {
|
||||
Ok(signer) => {
|
||||
let mut url = Url::parse(&uri).unwrap();
|
||||
@@ -117,6 +144,7 @@ pub async fn connect_account(uri: String, state: State<'_, Nostr>) -> Result<Str
|
||||
|
||||
// Update signer
|
||||
let _ = client.set_signer(Some(signer.into())).await;
|
||||
|
||||
// Update state
|
||||
state.accounts.lock().unwrap().push(remote_npub.clone());
|
||||
|
||||
@@ -170,6 +198,24 @@ pub fn delete_account(id: String) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn is_new_account(id: String, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
||||
let config_dir = app_handle.path().config_dir().map_err(|e| e.to_string())?;
|
||||
let exist = fs::metadata(config_dir.join(id)).is_ok();
|
||||
|
||||
Ok(!exist)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn toggle_new_account(id: String, app_handle: tauri::AppHandle) -> Result<(), String> {
|
||||
let config_dir = app_handle.path().config_dir().map_err(|e| e.to_string())?;
|
||||
fs::File::create(config_dir.join(id)).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn has_signer(id: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||
@@ -200,6 +246,11 @@ pub async fn set_signer(
|
||||
let account = match keyring.get_password() {
|
||||
Ok(pw) => {
|
||||
let account: Account = serde_json::from_str(&pw).map_err(|e| e.to_string())?;
|
||||
|
||||
if account.secret_key.is_empty() {
|
||||
return Err("Watch Only account".into());
|
||||
};
|
||||
|
||||
account
|
||||
}
|
||||
Err(e) => return Err(e.to_string()),
|
||||
|
||||
@@ -290,7 +290,7 @@ pub async fn publish(
|
||||
warning: Option<String>,
|
||||
difficulty: Option<u8>,
|
||||
state: State<'_, Nostr>,
|
||||
) -> Result<bool, String> {
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
|
||||
// Create event tags from content
|
||||
@@ -320,13 +320,8 @@ pub async fn publish(
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
// Save to local database
|
||||
match client.database().save_event(&event).await {
|
||||
Ok(status) => {
|
||||
// Add event to queue to broadcast it later.
|
||||
state.send_queue.lock().unwrap().insert(event);
|
||||
// Return
|
||||
Ok(status)
|
||||
}
|
||||
match client.send_event(event).await {
|
||||
Ok(output) => Ok(output.to_hex()),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
@@ -338,7 +333,7 @@ pub async fn reply(
|
||||
to: String,
|
||||
root: Option<String>,
|
||||
state: State<'_, Nostr>,
|
||||
) -> Result<bool, String> {
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
|
||||
// Create event tags from content
|
||||
@@ -380,39 +375,20 @@ pub async fn reply(
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
// Save to local database
|
||||
match client.database().save_event(&event).await {
|
||||
Ok(status) => {
|
||||
// Add event to queue to broadcast it later.
|
||||
state.send_queue.lock().unwrap().insert(event);
|
||||
// Return
|
||||
Ok(status)
|
||||
}
|
||||
match client.send_event(event).await {
|
||||
Ok(output) => Ok(output.to_hex()),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn repost(raw: String, state: State<'_, Nostr>) -> Result<bool, String> {
|
||||
pub async fn repost(raw: String, state: State<'_, Nostr>) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
let event = Event::from_json(raw).map_err(|err| err.to_string())?;
|
||||
let builder = EventBuilder::repost(&event, None);
|
||||
|
||||
// Sign event
|
||||
let event = client
|
||||
.sign_event_builder(builder)
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
// Save to local database
|
||||
match client.database().save_event(&event).await {
|
||||
Ok(status) => {
|
||||
// Add event to queue to broadcast it later.
|
||||
state.send_queue.lock().unwrap().insert(event);
|
||||
// Return
|
||||
Ok(status)
|
||||
}
|
||||
match client.repost(&event, None).await {
|
||||
Ok(output) => Ok(output.to_hex()),
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ pub async fn set_group(
|
||||
users: Vec<String>,
|
||||
state: State<'_, Nostr>,
|
||||
handle: tauri::AppHandle,
|
||||
) -> Result<bool, String> {
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
let public_keys: Vec<PublicKey> = users
|
||||
.iter()
|
||||
@@ -225,12 +225,8 @@ pub async fn set_group(
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
// Save to local database
|
||||
match client.database().save_event(&event).await {
|
||||
Ok(status) => {
|
||||
// Add event to queue to broadcast it later.
|
||||
state.send_queue.lock().unwrap().insert(event);
|
||||
|
||||
match client.send_event(event).await {
|
||||
Ok(output) => {
|
||||
// Sync event
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let state = handle.state::<Nostr>();
|
||||
@@ -247,8 +243,7 @@ pub async fn set_group(
|
||||
};
|
||||
});
|
||||
|
||||
// Return
|
||||
Ok(status)
|
||||
Ok(output.to_hex())
|
||||
}
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
@@ -302,7 +297,7 @@ pub async fn set_interest(
|
||||
hashtags: Vec<String>,
|
||||
state: State<'_, Nostr>,
|
||||
handle: tauri::AppHandle,
|
||||
) -> Result<bool, String> {
|
||||
) -> Result<String, String> {
|
||||
let client = &state.client;
|
||||
let label = title.to_lowercase().replace(" ", "-");
|
||||
let mut tags: Vec<Tag> = vec![Tag::title(title)];
|
||||
@@ -324,12 +319,8 @@ pub async fn set_interest(
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
// Save to local database
|
||||
match client.database().save_event(&event).await {
|
||||
Ok(status) => {
|
||||
// Add event to queue to broadcast it later.
|
||||
state.send_queue.lock().unwrap().insert(event);
|
||||
|
||||
match client.send_event(event).await {
|
||||
Ok(output) => {
|
||||
// Sync event
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let state = handle.state::<Nostr>();
|
||||
@@ -346,8 +337,7 @@ pub async fn set_interest(
|
||||
};
|
||||
});
|
||||
|
||||
// Return
|
||||
Ok(status)
|
||||
Ok(output.to_hex())
|
||||
}
|
||||
Err(err) => Err(err.to_string()),
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ pub enum NegentropyKind {
|
||||
Others,
|
||||
}
|
||||
|
||||
pub fn run_fast_sync(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
pub fn sync_all(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
if accounts.is_empty() {
|
||||
return;
|
||||
};
|
||||
@@ -45,51 +45,70 @@ pub fn run_fast_sync(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
let client = &state.client;
|
||||
let bootstrap_relays = state.bootstrap_relays.lock().unwrap().clone();
|
||||
|
||||
// NEG: Sync profile
|
||||
// NEG: Sync metadata
|
||||
//
|
||||
let profile = Filter::new()
|
||||
.authors(public_keys.clone())
|
||||
.kind(Kind::Metadata)
|
||||
.limit(4);
|
||||
let metadata = Filter::new().authors(public_keys.clone()).kinds(vec![
|
||||
Kind::Metadata,
|
||||
Kind::ContactList,
|
||||
Kind::Interests,
|
||||
Kind::InterestSet,
|
||||
Kind::FollowSet,
|
||||
Kind::EventDeletion,
|
||||
Kind::TextNote,
|
||||
Kind::Repost,
|
||||
Kind::Custom(30315),
|
||||
]);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, profile, NegentropyOptions::default())
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Profile,
|
||||
kind: NegentropyKind::Others,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// NEG: Sync contact list
|
||||
// NEG: Sync notification
|
||||
//
|
||||
let contact_list = Filter::new()
|
||||
.authors(public_keys.clone())
|
||||
.kind(Kind::ContactList)
|
||||
.limit(4);
|
||||
let notification = Filter::new()
|
||||
.pubkeys(public_keys)
|
||||
.kinds(vec![
|
||||
Kind::TextNote,
|
||||
Kind::Repost,
|
||||
Kind::Reaction,
|
||||
Kind::ZapReceipt,
|
||||
])
|
||||
.limit(5000);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(
|
||||
&bootstrap_relays,
|
||||
contact_list.clone(),
|
||||
notification,
|
||||
NegentropyOptions::default(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Metadata,
|
||||
kind: NegentropyKind::Notification,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// NEG: Sync events from contact list
|
||||
// NEG: Sync events for all pubkeys in local database
|
||||
//
|
||||
if let Ok(events) = client.database().query(vec![contact_list]).await {
|
||||
let pubkey_filter = Filter::new().kinds(vec![
|
||||
Kind::ContactList,
|
||||
Kind::Repost,
|
||||
Kind::TextNote,
|
||||
Kind::FollowSet,
|
||||
]);
|
||||
|
||||
if let Ok(events) = client.database().query(vec![pubkey_filter]).await {
|
||||
let pubkeys: Vec<PublicKey> = events
|
||||
.iter()
|
||||
.flat_map(|ev| ev.tags.public_keys().copied())
|
||||
@@ -107,7 +126,7 @@ pub fn run_fast_sync(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
let events = Filter::new()
|
||||
.authors(authors.clone())
|
||||
.kinds(vec![Kind::TextNote, Kind::Repost])
|
||||
.limit(1000);
|
||||
.limit(5000);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, events, NegentropyOptions::default())
|
||||
@@ -125,8 +144,7 @@ pub fn run_fast_sync(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
//
|
||||
let metadata = Filter::new()
|
||||
.authors(authors)
|
||||
.kind(Kind::Metadata)
|
||||
.limit(1000);
|
||||
.kinds(vec![Kind::Metadata, Kind::ContactList]);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
@@ -141,40 +159,116 @@ pub fn run_fast_sync(accounts: Vec<String>, app_handle: AppHandle) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NEG: Sync other metadata
|
||||
pub fn sync_account(public_key: PublicKey, app_handle: AppHandle) {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let state = app_handle.state::<Nostr>();
|
||||
let client = &state.client;
|
||||
let bootstrap_relays = state.bootstrap_relays.lock().unwrap().clone();
|
||||
|
||||
// NEG: Sync all user's metadata
|
||||
//
|
||||
let others = Filter::new().authors(public_keys.clone()).kinds(vec![
|
||||
let metadata = Filter::new().author(public_key).kinds(vec![
|
||||
Kind::Metadata,
|
||||
Kind::ContactList,
|
||||
Kind::Interests,
|
||||
Kind::InterestSet,
|
||||
Kind::FollowSet,
|
||||
Kind::RelayList,
|
||||
Kind::RelaySet,
|
||||
Kind::EventDeletion,
|
||||
Kind::Custom(30315),
|
||||
]);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, others, NegentropyOptions::default())
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Others,
|
||||
kind: NegentropyKind::Metadata,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// NEG: Sync notification
|
||||
if let Ok(contact_list) = client.database().contacts_public_keys(public_key).await {
|
||||
// NEG: Sync all contact's metadata
|
||||
//
|
||||
let metadata = Filter::new()
|
||||
.authors(contact_list.clone())
|
||||
.kinds(vec![Kind::Metadata, Kind::RelaySet, Kind::Custom(30315)])
|
||||
.limit(1000);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Metadata,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// NEG: Sync all contact's events
|
||||
//
|
||||
let metadata = Filter::new()
|
||||
.authors(contact_list.clone())
|
||||
.kinds(vec![Kind::TextNote, Kind::Repost])
|
||||
.limit(1000);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Events,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// NEG: Sync all contact's other metadata
|
||||
//
|
||||
let metadata = Filter::new()
|
||||
.authors(contact_list)
|
||||
.kinds(vec![
|
||||
Kind::Interests,
|
||||
Kind::InterestSet,
|
||||
Kind::FollowSet,
|
||||
Kind::EventDeletion,
|
||||
])
|
||||
.limit(1000);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(&bootstrap_relays, metadata, NegentropyOptions::default())
|
||||
.await
|
||||
{
|
||||
NegentropyEvent {
|
||||
kind: NegentropyKind::Metadata,
|
||||
total_event: report.received.len() as i32,
|
||||
}
|
||||
.emit(&app_handle)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// NEG: Sync all user's metadata
|
||||
//
|
||||
let notification = Filter::new()
|
||||
.pubkeys(public_keys)
|
||||
.pubkey(public_key)
|
||||
.kinds(vec![
|
||||
Kind::Reaction,
|
||||
Kind::TextNote,
|
||||
Kind::Repost,
|
||||
Kind::Reaction,
|
||||
Kind::ZapReceipt,
|
||||
])
|
||||
.limit(10000);
|
||||
.limit(500);
|
||||
|
||||
if let Ok(report) = client
|
||||
.sync_with(
|
||||
|
||||
@@ -5,7 +5,14 @@
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use border::WebviewWindowExt as BorderWebviewWindowExt;
|
||||
use commands::{account::*, event::*, metadata::*, relay::*, sync::NegentropyEvent, window::*};
|
||||
use commands::{
|
||||
account::*,
|
||||
event::*,
|
||||
metadata::*,
|
||||
relay::*,
|
||||
sync::{sync_all, NegentropyEvent},
|
||||
window::*,
|
||||
};
|
||||
use common::{get_all_accounts, parse_event};
|
||||
use nostr_sdk::prelude::{Profile as DatabaseProfile, *};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -19,7 +26,7 @@ use std::{
|
||||
sync::Mutex,
|
||||
time::Duration,
|
||||
};
|
||||
use tauri::{path::BaseDirectory, Emitter, EventTarget, Manager, WindowEvent};
|
||||
use tauri::{path::BaseDirectory, Emitter, EventTarget, Manager};
|
||||
use tauri_plugin_decorum::WebviewWindowExt;
|
||||
use tauri_plugin_notification::{NotificationExt, PermissionState};
|
||||
use tauri_specta::{collect_commands, collect_events, Builder, Event as TauriEvent};
|
||||
@@ -33,7 +40,6 @@ pub struct Nostr {
|
||||
accounts: Mutex<Vec<String>>,
|
||||
bootstrap_relays: Mutex<Vec<Url>>,
|
||||
subscriptions: Mutex<HashSet<SubscriptionId>>,
|
||||
send_queue: Mutex<HashSet<Event>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Type)]
|
||||
@@ -86,7 +92,7 @@ struct Sync {
|
||||
id: String,
|
||||
}
|
||||
|
||||
pub const DEFAULT_DIFFICULTY: u8 = 21;
|
||||
pub const DEFAULT_DIFFICULTY: u8 = 0;
|
||||
pub const FETCH_LIMIT: usize = 50;
|
||||
pub const NOTIFICATION_SUB_ID: &str = "lume_notification";
|
||||
|
||||
@@ -105,6 +111,8 @@ fn main() {
|
||||
get_private_key,
|
||||
delete_account,
|
||||
reset_password,
|
||||
is_new_account,
|
||||
toggle_new_account,
|
||||
has_signer,
|
||||
set_signer,
|
||||
get_profile,
|
||||
@@ -175,6 +183,7 @@ fn main() {
|
||||
let handle = app.handle();
|
||||
let handle_clone = handle.clone();
|
||||
let handle_clone_child = handle_clone.clone();
|
||||
let handle_clone_child_child = handle_clone_child.clone();
|
||||
let main_window = app.get_webview_window("main").unwrap();
|
||||
|
||||
let config_dir = handle
|
||||
@@ -260,6 +269,8 @@ fn main() {
|
||||
});
|
||||
|
||||
let accounts = get_all_accounts();
|
||||
// Run sync for all accounts
|
||||
sync_all(accounts.clone(), handle_clone_child_child);
|
||||
|
||||
// Create global state
|
||||
app.manage(Nostr {
|
||||
@@ -268,7 +279,6 @@ fn main() {
|
||||
settings: Mutex::new(Settings::default()),
|
||||
bootstrap_relays: Mutex::new(bootstrap_relays),
|
||||
subscriptions: Mutex::new(HashSet::new()),
|
||||
send_queue: Mutex::new(HashSet::new()),
|
||||
});
|
||||
|
||||
// Handle subscription request
|
||||
@@ -540,39 +550,6 @@ fn main() {
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.on_window_event(|window, event| match event {
|
||||
WindowEvent::CloseRequested { api, .. } => {
|
||||
api.prevent_close();
|
||||
// Just hide window not close
|
||||
window.hide().unwrap();
|
||||
|
||||
let state = window.state::<Nostr>();
|
||||
let client = &state.client;
|
||||
let queue: Vec<Event> = state
|
||||
.send_queue
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.into_iter()
|
||||
.collect();
|
||||
|
||||
if !queue.is_empty() {
|
||||
tauri::async_runtime::block_on(async {
|
||||
println!("Sending total {} events to relays", queue.len());
|
||||
match client.batch_event(queue, RelaySendOptions::default()).await {
|
||||
Ok(_) => window.destroy().unwrap(),
|
||||
Err(_) => window.emit("batch-event", ()).unwrap(),
|
||||
}
|
||||
});
|
||||
} else {
|
||||
window.destroy().unwrap()
|
||||
}
|
||||
}
|
||||
WindowEvent::Focused(_focused) => {
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.plugin(prevent_default())
|
||||
.plugin(tauri_plugin_theme::init(ctx.config_mut()))
|
||||
.plugin(tauri_plugin_decorum::init())
|
||||
|
||||
Reference in New Issue
Block a user