Merge pull request #664 from PR0M3TH3AN/32y2sb-codex/add-background-vault-sync-method

Add vault sync scheduling to GUI
This commit is contained in:
thePR0M3TH3AN
2025-07-19 18:22:33 -04:00
committed by GitHub
2 changed files with 89 additions and 0 deletions

View File

@@ -102,6 +102,7 @@ class MainWindow(toga.Window):
search_button = toga.Button("Search", on_press=self.search_entries)
relay_button = toga.Button("Relays", on_press=self.manage_relays)
totp_button = toga.Button("TOTP", on_press=self.show_totp_codes)
sync_button = toga.Button("Sync", on_press=self.start_vault_sync)
button_box = toga.Box(style=Pack(direction=ROW, padding_top=5))
button_box.add(add_button)
@@ -109,6 +110,7 @@ class MainWindow(toga.Window):
button_box.add(search_button)
button_box.add(relay_button)
button_box.add(totp_button)
button_box.add(sync_button)
self.status = toga.Label("Last sync: never", style=Pack(padding_top=5))
@@ -168,6 +170,14 @@ class MainWindow(toga.Window):
win = TotpViewerWindow(self.controller, self.entries)
win.show()
def start_vault_sync(self, widget: toga.Widget | None = None) -> None:
"""Schedule a background vault synchronization."""
async def _runner() -> None:
self.nostr.start_background_vault_sync()
self.controller.loop.create_task(_runner())
# --- PubSub callbacks -------------------------------------------------
def sync_started(self, *args: object, **kwargs: object) -> None:
self.status.text = "Syncing..."
@@ -307,6 +317,8 @@ class EntryDialog(toga.Window):
break
self.close()
# schedule vault sync after saving
getattr(self.main, "start_vault_sync", lambda *_: None)()
class SearchDialog(toga.Window):

View File

@@ -0,0 +1,77 @@
import os
import types
import asyncio
import toga
import pytest
from seedpass.core.pubsub import bus
from seedpass_gui.app import MainWindow
class DummyEntries:
def list_entries(self, sort_by="index", filter_kind=None, include_archived=False):
return []
def search_entries(self, q):
return []
class DummyNostr:
def __init__(self):
self.called = False
def start_background_vault_sync(self):
self.called = True
def list_relays(self):
return []
class DummyController:
def __init__(self, loop):
self.loop = loop
self.lock_window = types.SimpleNamespace(show=lambda: None)
self.main_window = None
self.vault_service = None
self.entry_service = None
self.nostr_service = None
@pytest.fixture(autouse=True)
def set_backend():
os.environ["TOGA_BACKEND"] = "toga_dummy"
asyncio.set_event_loop(asyncio.new_event_loop())
def test_start_vault_sync_schedules_task():
toga.App("T", "o")
tasks = []
def create_task(coro):
tasks.append(coro)
loop = types.SimpleNamespace(create_task=create_task)
ctrl = DummyController(loop)
nostr = DummyNostr()
win = MainWindow(ctrl, None, DummyEntries(), nostr)
win.start_vault_sync()
assert tasks
asyncio.get_event_loop().run_until_complete(tasks[0])
assert nostr.called
win.cleanup()
def test_status_updates_on_bus_events():
toga.App("T2", "o2")
loop = types.SimpleNamespace(create_task=lambda c: None)
ctrl = DummyController(loop)
nostr = DummyNostr()
win = MainWindow(ctrl, None, DummyEntries(), nostr)
bus.publish("sync_started")
assert win.status.text == "Syncing..."
bus.publish("sync_finished")
assert "Last sync:" in win.status.text
win.cleanup()