mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 07:18:47 +00:00
Merge pull request #664 from PR0M3TH3AN/32y2sb-codex/add-background-vault-sync-method
Add vault sync scheduling to GUI
This commit is contained in:
@@ -102,6 +102,7 @@ class MainWindow(toga.Window):
|
|||||||
search_button = toga.Button("Search", on_press=self.search_entries)
|
search_button = toga.Button("Search", on_press=self.search_entries)
|
||||||
relay_button = toga.Button("Relays", on_press=self.manage_relays)
|
relay_button = toga.Button("Relays", on_press=self.manage_relays)
|
||||||
totp_button = toga.Button("TOTP", on_press=self.show_totp_codes)
|
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 = toga.Box(style=Pack(direction=ROW, padding_top=5))
|
||||||
button_box.add(add_button)
|
button_box.add(add_button)
|
||||||
@@ -109,6 +110,7 @@ class MainWindow(toga.Window):
|
|||||||
button_box.add(search_button)
|
button_box.add(search_button)
|
||||||
button_box.add(relay_button)
|
button_box.add(relay_button)
|
||||||
button_box.add(totp_button)
|
button_box.add(totp_button)
|
||||||
|
button_box.add(sync_button)
|
||||||
|
|
||||||
self.status = toga.Label("Last sync: never", style=Pack(padding_top=5))
|
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 = TotpViewerWindow(self.controller, self.entries)
|
||||||
win.show()
|
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 -------------------------------------------------
|
# --- PubSub callbacks -------------------------------------------------
|
||||||
def sync_started(self, *args: object, **kwargs: object) -> None:
|
def sync_started(self, *args: object, **kwargs: object) -> None:
|
||||||
self.status.text = "Syncing..."
|
self.status.text = "Syncing..."
|
||||||
@@ -307,6 +317,8 @@ class EntryDialog(toga.Window):
|
|||||||
break
|
break
|
||||||
|
|
||||||
self.close()
|
self.close()
|
||||||
|
# schedule vault sync after saving
|
||||||
|
getattr(self.main, "start_vault_sync", lambda *_: None)()
|
||||||
|
|
||||||
|
|
||||||
class SearchDialog(toga.Window):
|
class SearchDialog(toga.Window):
|
||||||
|
77
src/tests/test_gui_sync.py
Normal file
77
src/tests/test_gui_sync.py
Normal 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()
|
Reference in New Issue
Block a user