From 37242294ed81efe98398ed83b771f6d0d3521d6c Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Mon, 2 Mar 2026 08:43:46 -0500 Subject: [PATCH] tui2: add archived scope filter parity and tests --- docs/dev_control_center.md | 2 +- docs/tui_v2_legacy_parity_matrix.md | 9 ++- memory-update.md | 34 ++++++++++ src/seedpass/core/api.py | 14 ++++- src/seedpass/tui_v2/app.py | 63 ++++++++++++++++++- src/tests/test_core_api_services.py | 24 +++++++ src/tests/test_tui_v2_action_matrix.py | 24 ++++++- src/tests/test_tui_v2_kb_scale_stress.py | 16 ++++- src/tests/test_tui_v2_parity_scenarios.py | 16 ++++- src/tests/test_tui_v2_textual_interactions.py | 58 +++++++++++++++-- 10 files changed, 238 insertions(+), 22 deletions(-) diff --git a/docs/dev_control_center.md b/docs/dev_control_center.md index 20fd21ce..2241c9e3 100644 --- a/docs/dev_control_center.md +++ b/docs/dev_control_center.md @@ -92,7 +92,7 @@ Progress update (2026-03-02): - `nostr-fresh-namespace` - service wrappers and tests added - Current next implementation target: - - archived-only entry view/filter parity + - dedicated utility-style `npub` display command parity ## 6) Working Rule diff --git a/docs/tui_v2_legacy_parity_matrix.md b/docs/tui_v2_legacy_parity_matrix.md index bcf27de3..90f95955 100644 --- a/docs/tui_v2_legacy_parity_matrix.md +++ b/docs/tui_v2_legacy_parity_matrix.md @@ -9,7 +9,7 @@ Purpose: map legacy interactive workflows to Textual TUI v2 equivalents and isol - Implemented: core daily workflows are covered in TUI v2 (add/retrieve/search/modify/archive, reveal/QR, 2FA board, settings/profile/relay/sync, export/import/checksum paths). - Partial: a few legacy menu affordances are represented differently in v2 (palette-first vs nested menus). -- Gaps: remaining high-value gaps are mostly around managed-account session operations and a few settings/Nostr maintenance affordances. +- Gaps: remaining high-value gaps are low-volume utility affordances rather than core workflows. ## Matrix @@ -51,7 +51,7 @@ Purpose: map legacy interactive workflows to Textual TUI v2 equivalents and isol | Export TOTP codes | Settings | `totp-export` | Implemented | | | Backup/reveal parent seed | Settings | `parent-seed-backup [path] [password]` | Implemented | | | Display npub | Main utility flow | No direct dedicated command | Partial | Possible via entry reveal for nostr entry; direct utility-style command absent. | -| View archived-only list | Settings/List flow | No dedicated archived-only pane/command | Gap | Archived state visible in list; archive-only view affordance missing. | +| View archived-only list | Settings/List flow | `h` cycle archive scope or `archive-filter ` | Implemented | Supports active-only/default, all, and archived-only views. | | Reset Nostr sync state | Settings > Nostr | `nostr-reset-sync-state` | Implemented | Added to TUI v2 palette + tests. | | Start fresh Nostr namespace | Settings > Nostr | `nostr-fresh-namespace` | Implemented | Added to TUI v2 palette + tests. | | Load managed-account session | Retrieve managed account action | `managed-load (optional: entry_id)` | Implemented | Added in TUI v2 palette + tests. | @@ -59,9 +59,8 @@ Purpose: map legacy interactive workflows to Textual TUI v2 equivalents and isol ## Prioritized Gap Queue -1. Medium: archived-only list/view affordance parity. -2. Low: dedicated utility-style npub display command in v2. +1. Low: dedicated utility-style npub display command in v2. ## Suggested implementation order -1. Archived-only view filter/command + tests. +1. Dedicated `npub` utility command + tests. diff --git a/memory-update.md b/memory-update.md index 179712b9..9714b0d3 100644 --- a/memory-update.md +++ b/memory-update.md @@ -617,3 +617,37 @@ - Updated planning docs: - `docs/tui_v2_legacy_parity_matrix.md` marks Nostr maintenance parity as implemented. - `docs/dev_control_center.md` now points to archived-only view/filter as the next parity target. + +## 2026-03-02 Next parity slice landed: archived view/filter parity in TUI v2 +- Added archive-scope support across TUI v2 entry browsing with three modes: + - `active` (default, excludes archived entries) + - `all` (includes active + archived) + - `archived` (archived-only) +- TUI v2 updates in `src/seedpass/tui_v2/app.py`: + - new keybinding: `h` (`action_cycle_archive_scope`) + - new palette command: `archive-filter ` + - left filter panel now shows `Archive: ` + - search loads now pass archive scope to service search. +- Core wrapper updates in `src/seedpass/core/api.py`: + - `EntryService.search_entries(...)` now accepts + - `include_archived: bool = False` + - `archived_only: bool = False` + - wrapper filters archived rows deterministically on top of entry-manager search results. +- UX parity fix bundled: + - palette `archive`/`restore` branch now returns correctly after success. + - archive/restore flows preserve selected-entry context when an archived item leaves the active view, enabling immediate restore roundtrip without forced reselection. +- Test coverage updates: + - `src/tests/test_core_api_services.py`: archive include/exclude/only behavior for `EntryService.search_entries`. + - `src/tests/test_tui_v2_textual_interactions.py`: new archive-scope interaction test. + - updated TUI fake services across + - `test_tui_v2_textual_interactions.py` + - `test_tui_v2_action_matrix.py` + - `test_tui_v2_kb_scale_stress.py` + - `test_tui_v2_parity_scenarios.py` + to accept archive-scope args. +- Validation run: + - `pytest -q src/tests/test_core_api_services.py src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py src/tests/test_tui_v2_kb_scale_stress.py src/tests/test_tui_v2_parity_scenarios.py` + - Result: `96 passed, 1 skipped`. +- Planning docs updated: + - `docs/tui_v2_legacy_parity_matrix.md` marks archived-only view parity implemented. + - `docs/dev_control_center.md` next target updated to dedicated `npub` utility command parity. diff --git a/src/seedpass/core/api.py b/src/seedpass/core/api.py index 63026b8a..69cc8507 100644 --- a/src/seedpass/core/api.py +++ b/src/seedpass/core/api.py @@ -285,7 +285,12 @@ class EntryService: ) def search_entries( - self, query: str, kinds: list[str] | None = None + self, + query: str, + kinds: list[str] | None = None, + *, + include_archived: bool = False, + archived_only: bool = False, ) -> list[tuple[int, str, str | None, str | None, bool, EntryType]]: """Search entries optionally filtering by ``kinds``. @@ -298,7 +303,12 @@ class EntryService: """ with self._lock: - return self._manager.entry_manager.search_entries(query, kinds=kinds) + rows = self._manager.entry_manager.search_entries(query, kinds=kinds) + if not include_archived: + return [row for row in rows if not bool(row[4])] + if archived_only: + return [row for row in rows if bool(row[4])] + return rows def retrieve_entry(self, entry_id: int): with self._lock: diff --git a/src/seedpass/tui_v2/app.py b/src/seedpass/tui_v2/app.py index 4bb8b04f..b4c75491 100644 --- a/src/seedpass/tui_v2/app.py +++ b/src/seedpass/tui_v2/app.py @@ -252,6 +252,7 @@ def launch_tui2( ("2", "focus_center", "Center"), ("3", "focus_right", "Right"), ("f", "cycle_filter", "Filter"), + ("h", "cycle_archive_scope", "Archive View"), ("p", "prev_page", "Prev Page"), ("n", "next_page", "Next Page"), ("l", "cycle_link_filter", "Link Filter"), @@ -269,6 +270,7 @@ def launch_tui2( ] filter_kind: reactive[str] = reactive("all") + archive_scope: reactive[str] = reactive("active") link_relation_filter: reactive[str] = reactive("all") editing_document: reactive[bool] = reactive(False) palette_open: reactive[bool] = reactive(False) @@ -281,6 +283,7 @@ def launch_tui2( placeholder=( "Command palette: help | open | search | " "filter | archive | restore | " + "archive-filter | " "add-password