mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-27 07:52:03 +00:00
Improve Nostr sync failure messaging for offline mode
This commit is contained in:
1 parent
6cfd13e858
commit
7ec462a589
5 files changed
+57
No files matched your search
@@ -25,3 +25,15 @@
|
||||
- Added `docs/nostr_namespace_reset.md` documenting menu options `8` (reset sync state) and `9` (start fresh namespace), plus validation steps for robust publish/restore.
|
||||
- Linked the new guide from `docs/nostr_setup.md`, `docs/README.md`, and root `README.md`.
|
||||
- Exposed the guide in website docs navigation via `landing/docs.html` (`Nostr Namespace Reset`).
|
||||
|
||||
## Nostr sync failure after namespace increment
|
||||
- Root-cause pattern: when profile `offline_mode` is enabled, `sync_vault_async()` exits early and previously returned `None` without a helpful message, so UI showed only `❌ Sync failed…`.
|
||||
- Fixes:
|
||||
- `PasswordManager.sync_vault_async()` now sets `nostr_client.last_error` for early-return cases (`offline_mode`, missing encrypted index, and missing publish result).
|
||||
- `main.handle_post_to_nostr()` now explicitly reports offline mode when no detailed error is present.
|
||||
- Regression tests added:
|
||||
- `src/tests/test_post_sync_messages.py::test_handle_post_failure_offline_mode_message`
|
||||
- `src/tests/test_background_vault_sync_paths.py::test_sync_vault_async_sets_offline_error`
|
||||
- Verified with local venv:
|
||||
- `./.venv/bin/pytest -q src/tests/test_post_sync_messages.py`
|
||||
- `./.venv/bin/pytest -q src/tests/test_background_vault_sync_paths.py`
|
||||
@@ -431,6 +431,10 @@ def handle_post_to_nostr(
|
||||
if detail:
|
||||
print(colored(f"\N{CROSS MARK} Sync failed… {detail}", "red"))
|
||||
logging.error("Failed to post encrypted index to Nostr: %s", detail)
|
||||
elif getattr(password_manager, "offline_mode", False):
|
||||
detail = "Offline mode is enabled. Disable it in Settings to sync."
|
||||
print(colored(f"\N{CROSS MARK} Sync failed… {detail}", "red"))
|
||||
logging.error("Failed to post encrypted index to Nostr: %s", detail)
|
||||
else:
|
||||
print(colored("\N{CROSS MARK} Sync failed…", "red"))
|
||||
logging.error("Failed to post encrypted index to Nostr.")
|
||||
|
||||
@@ -3930,11 +3930,20 @@ class PasswordManager:
|
||||
) -> dict[str, list[str] | str] | None:
|
||||
"""Publish the current vault contents to Nostr and return event IDs."""
|
||||
try:
|
||||
client = getattr(self, "nostr_client", None)
|
||||
if getattr(self, "offline_mode", False):
|
||||
if client is not None and hasattr(client, "last_error"):
|
||||
client.last_error = (
|
||||
"Offline mode is enabled. Disable it in Settings to sync."
|
||||
)
|
||||
return None
|
||||
encrypted = self.get_encrypted_data()
|
||||
if not encrypted:
|
||||
if client is not None and hasattr(client, "last_error"):
|
||||
client.last_error = "No encrypted index data available to sync."
|
||||
return None
|
||||
if client is not None and hasattr(client, "last_error"):
|
||||
client.last_error = None
|
||||
pub_snap = getattr(self.nostr_client, "publish_snapshot", None)
|
||||
manifest = None
|
||||
event_id = None
|
||||
@@ -3948,6 +3957,14 @@ class PasswordManager:
|
||||
event_id = await self.nostr_client.publish_json_to_nostr(encrypted)
|
||||
self.is_dirty = False
|
||||
if event_id is None:
|
||||
if (
|
||||
client is not None
|
||||
and hasattr(client, "last_error")
|
||||
and not client.last_error
|
||||
):
|
||||
client.last_error = (
|
||||
"Failed to publish encrypted index to configured relays."
|
||||
)
|
||||
return None
|
||||
chunk_ids: list[str] = []
|
||||
if manifest is not None:
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import asyncio
|
||||
from types import SimpleNamespace
|
||||
|
||||
from seedpass.core.manager import PasswordManager
|
||||
from seedpass.core import manager as manager_module
|
||||
@@ -56,3 +57,16 @@ def test_start_background_vault_sync_async_worker_path(monkeypatch):
|
||||
|
||||
assert ("sync_started",) in events
|
||||
assert ("sync_finished", {"alt_summary": "async-path"}) in events
|
||||
|
||||
|
||||
def test_sync_vault_async_sets_offline_error():
|
||||
pm = PasswordManager.__new__(PasswordManager)
|
||||
pm.offline_mode = True
|
||||
pm.nostr_client = SimpleNamespace(last_error=None)
|
||||
|
||||
result = asyncio.run(pm.sync_vault_async())
|
||||
|
||||
assert result is None
|
||||
assert pm.nostr_client.last_error == (
|
||||
"Offline mode is enabled. Disable it in Settings to sync."
|
||||
)
|
||||
@@ -41,6 +41,16 @@ def test_handle_post_failure_shows_nostr_error(capsys):
|
||||
assert "❌ Sync failed… Manifest out of date" in out
|
||||
|
||||
|
||||
def test_handle_post_failure_offline_mode_message(capsys):
|
||||
pm = SimpleNamespace(
|
||||
sync_vault=lambda alt_summary=None: None,
|
||||
offline_mode=True,
|
||||
)
|
||||
main.handle_post_to_nostr(pm)
|
||||
out = capsys.readouterr().out
|
||||
assert "Offline mode is enabled. Disable it in Settings to sync." in out
|
||||
|
||||
|
||||
def test_handle_post_prints_all_ids(capsys):
|
||||
pm = SimpleNamespace(
|
||||
sync_vault=lambda alt_summary=None: {
|
||||
|
||||
Reference in new issue
Block a user