diff --git a/crates/tauri-app/src/lib.rs b/crates/tauri-app/src/lib.rs index 8cac71c..5268ac8 100644 --- a/crates/tauri-app/src/lib.rs +++ b/crates/tauri-app/src/lib.rs @@ -2497,6 +2497,34 @@ async fn export_data( paths.join(", "))) } +/// Clear the duplicate identity flag and start sync tasks that were skipped. +#[tauri::command] +async fn clear_duplicate_flag(state: State<'_, AppNode>) -> Result<(), String> { + let node = get_node(&state).await; + node.network.duplicate_detected.store(false, std::sync::atomic::Ordering::Relaxed); + // Start the sync tasks that were skipped during bootstrap + node.start_accept_loop(); + node.start_pull_cycle(300); + node.start_diff_cycle(120); + node.start_rebalance_cycle(600); + node.start_growth_loop(); + node.start_recovery_loop(); + node.start_social_checkin_cycle(3600); + node.start_anchor_register_cycle(600); + node.start_upnp_renewal_cycle(); + node.start_upnp_tcp_renewal_cycle(); + node.start_http_server(); + node.start_bootstrap_connectivity_check(); + node.start_replication_cycle(600); + let cache_max_bytes: u64 = { + let storage = node.storage.get().await; + storage.get_setting("cache_size_bytes").ok().flatten() + .and_then(|s| s.parse().ok()).unwrap_or(1_073_741_824u64) + }; + Node::start_eviction_cycle(Arc::clone(&node), 300, cache_max_bytes); + Ok(()) +} + /// On Android: save a file from the app's internal storage to a user-chosen location via SAF. /// On desktop: no-op (files are already in ~/Downloads). #[tauri::command] @@ -2803,6 +2831,7 @@ pub fn run() { get_active_identity, export_data, share_file, + clear_duplicate_flag, import_summary, import_public_posts, import_as_new_identity, diff --git a/frontend/app.js b/frontend/app.js index 00af266..697e6f8 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -3918,10 +3918,14 @@ async function init() { if (info && info.duplicateDetected) { _duplicateWarningShown = true; const banner = document.createElement('div'); - banner.style.cssText = 'position:fixed;top:0;left:0;right:0;background:#c0392b;color:#fff;padding:0.5rem;text-align:center;font-size:0.8rem;z-index:999;'; - banner.textContent = 'This identity is active on another device. Sync paused to prevent data conflicts.'; + banner.style.cssText = 'position:fixed;top:0;left:0;right:0;background:#c0392b;color:#fff;padding:0.5rem;text-align:center;font-size:0.8rem;z-index:999;display:flex;align-items:center;justify-content:center;gap:0.5rem;'; + banner.innerHTML = 'This identity may be active on another device. Sync paused.'; document.body.prepend(banner); - toast('Duplicate identity detected — sync paused'); + banner.querySelector('#dup-override-btn').addEventListener('click', async () => { + try { await invoke('clear_duplicate_flag'); } catch (_) {} + banner.remove(); + toast('Sync resumed'); + }); } } catch (_) {} }