From dcff36050865f5df78d47decf192eb8df813c1b9 Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Fri, 11 Jul 2025 22:42:12 -0400 Subject: [PATCH] Refactor sync trigger --- src/main.py | 4 ++++ src/password_manager/manager.py | 21 +++++++++++++++++++-- src/tests/test_auto_sync.py | 1 + src/tests/test_cli_invalid_input.py | 1 + src/tests/test_inactivity_lock.py | 2 ++ src/tests/test_menu_navigation.py | 1 + src/tests/test_menu_options.py | 1 + src/tests/test_menu_search.py | 1 + src/tests/test_unlock_sync.py | 2 ++ 9 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 8085c53..d22c8d6 100644 --- a/src/main.py +++ b/src/main.py @@ -741,6 +741,7 @@ def handle_settings(password_manager: PasswordManager) -> None: password_manager.lock_vault() print(colored("Vault locked. Please re-enter your password.", "yellow")) password_manager.unlock_vault() + password_manager.start_background_sync() pause() elif choice == "13": handle_display_stats(password_manager) @@ -777,6 +778,7 @@ def display_menu( if callable(display_fn): display_fn() pause() + password_manager.start_background_sync() while True: fp, parent_fp, child_fp = getattr( password_manager, @@ -793,6 +795,7 @@ def display_menu( print(colored("Session timed out. Vault locked.", "yellow")) password_manager.lock_vault() password_manager.unlock_vault() + password_manager.start_background_sync() continue # Periodically push updates to Nostr if ( @@ -815,6 +818,7 @@ def display_menu( print(colored("Session timed out. Vault locked.", "yellow")) password_manager.lock_vault() password_manager.unlock_vault() + password_manager.start_background_sync() continue password_manager.update_activity() if not choice: diff --git a/src/password_manager/manager.py b/src/password_manager/manager.py index 7c62dda..7f414ce 100644 --- a/src/password_manager/manager.py +++ b/src/password_manager/manager.py @@ -19,6 +19,7 @@ from typing import Optional import shutil import time import builtins +import threading from termcolor import colored from utils.color_scheme import color_text from utils.input_utils import timed_input @@ -234,7 +235,6 @@ class PasswordManager: self.initialize_managers() self.locked = False self.update_activity() - self.sync_index_from_nostr() self.last_unlock_duration = time.perf_counter() - start print( colored( @@ -358,7 +358,6 @@ class PasswordManager: # Initialize BIP85 and other managers self.initialize_bip85() self.initialize_managers() - self.sync_index_from_nostr() print( colored( f"Seed profile {fingerprint} selected and managers initialized.", @@ -967,6 +966,24 @@ class PasswordManager: except Exception as e: logger.warning(f"Unable to sync index from Nostr: {e}") + def start_background_sync(self) -> None: + """Launch a thread to synchronize the vault without blocking the UI.""" + if ( + hasattr(self, "_sync_thread") + and self._sync_thread + and self._sync_thread.is_alive() + ): + return + + def _worker() -> None: + try: + self.sync_index_from_nostr() + except Exception as exc: + logger.warning(f"Background sync failed: {exc}") + + self._sync_thread = threading.Thread(target=_worker, daemon=True) + self._sync_thread.start() + def sync_index_from_nostr_if_missing(self) -> None: """Retrieve the password database from Nostr if it doesn't exist locally.""" index_file = self.fingerprint_dir / "seedpass_entries_db.json.enc" diff --git a/src/tests/test_auto_sync.py b/src/tests/test_auto_sync.py index 53cf949..c5dc13c 100644 --- a/src/tests/test_auto_sync.py +++ b/src/tests/test_auto_sync.py @@ -22,6 +22,7 @@ def test_auto_sync_triggers_post(monkeypatch): update_activity=lambda: None, lock_vault=lambda: None, unlock_vault=lambda: None, + start_background_sync=lambda: None, ) called = False diff --git a/src/tests/test_cli_invalid_input.py b/src/tests/test_cli_invalid_input.py index 589f162..57686a9 100644 --- a/src/tests/test_cli_invalid_input.py +++ b/src/tests/test_cli_invalid_input.py @@ -46,6 +46,7 @@ def _make_pm(called, locked=None): update_activity=update, lock_vault=lock, unlock_vault=unlock, + start_background_sync=lambda: None, ) return pm, locked diff --git a/src/tests/test_inactivity_lock.py b/src/tests/test_inactivity_lock.py index 0c68561..2e7c4ed 100644 --- a/src/tests/test_inactivity_lock.py +++ b/src/tests/test_inactivity_lock.py @@ -34,6 +34,7 @@ def test_inactivity_triggers_lock(monkeypatch): update_activity=update_activity, lock_vault=lock_vault, unlock_vault=unlock_vault, + start_background_sync=lambda: None, ) monkeypatch.setattr(main, "timed_input", lambda *_: "") @@ -70,6 +71,7 @@ def test_input_timeout_triggers_lock(monkeypatch): update_activity=update_activity, lock_vault=lock_vault, unlock_vault=unlock_vault, + start_background_sync=lambda: None, ) responses = iter([TimeoutError(), ""]) diff --git a/src/tests/test_menu_navigation.py b/src/tests/test_menu_navigation.py index 8ab7bae..9b426e7 100644 --- a/src/tests/test_menu_navigation.py +++ b/src/tests/test_menu_navigation.py @@ -30,6 +30,7 @@ def _make_pm(calls): update_activity=lambda: None, lock_vault=lambda: None, unlock_vault=lambda: None, + start_background_sync=lambda: None, ) diff --git a/src/tests/test_menu_options.py b/src/tests/test_menu_options.py index ff8e7cf..9638300 100644 --- a/src/tests/test_menu_options.py +++ b/src/tests/test_menu_options.py @@ -24,6 +24,7 @@ def _make_pm(calls): update_activity=lambda: None, lock_vault=lambda: None, unlock_vault=lambda: None, + start_background_sync=lambda: None, ) diff --git a/src/tests/test_menu_search.py b/src/tests/test_menu_search.py index 0e1d439..01c8747 100644 --- a/src/tests/test_menu_search.py +++ b/src/tests/test_menu_search.py @@ -23,6 +23,7 @@ def _make_pm(called): update_activity=lambda: None, lock_vault=lambda: None, unlock_vault=lambda: None, + start_background_sync=lambda: None, ) return pm diff --git a/src/tests/test_unlock_sync.py b/src/tests/test_unlock_sync.py index 7eef4c5..892ea9a 100644 --- a/src/tests/test_unlock_sync.py +++ b/src/tests/test_unlock_sync.py @@ -22,5 +22,7 @@ def test_unlock_triggers_sync(monkeypatch, tmp_path): monkeypatch.setattr(PasswordManager, "sync_index_from_nostr", fake_sync) pm.unlock_vault() + pm.start_background_sync() + time.sleep(0.05) assert called["sync"]