mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-02 02:42:04 +00:00
feat(tui_v3): full end-to-end slice implemented for managed sub-accounts including UI breadcrumbs and mock test validations
This commit is contained in:
1 parent
be69e3e52d
commit
33e727841c
4 files changed
+46
-7
No files matched your search
+3
-1
@@ -86,8 +86,10 @@ To finalize v3, we must verify 100% functional parity with the **Legacy TUI**.
|
||||
- Updated `derive_pgp_key` and API to support armored PGP Public Key retrieval/copying.
|
||||
- Aligned copy/reveal semantics with mockup hints (e.g., SSH/PGP copy Pub by default).
|
||||
- **Managed Sessions:**
|
||||
- Added `action_managed_load` (`m`) and `action_managed_exit` (`Shift+M`) to v3.
|
||||
- Added `action_managed_load` (`m`) and `action_managed_exit` (`Shift+M`) to v3 with mock service support.
|
||||
- Wired `ml` and `mx` commands to the palette.
|
||||
- Extended `SeedPlusScreen` to manage accurate sub-account derivation correctly.
|
||||
- Added fully functioning dynamic breadcrumb UI via `BrandFingerprint` and `active_breadcrumb`.
|
||||
- **Search & Filters:**
|
||||
- Integrated `SemanticIndexService` into `EntryDataTable`.
|
||||
- Added `filter <kind>` (secrets, docs, keys, 2fa) and `archived` view toggle.
|
||||
|
||||
@@ -10,3 +10,4 @@
|
||||
- Direct configuration modification of arrays (like `relays`) should favor using dedicated service adapters over direct `ConfigService` modifications if they aren't fully wrapped for list operations. Using `app.services["nostr"]` for relay additions/removals is the preferred pattern.
|
||||
- The cohesive retro palette across the TUI v3 mockups hinges on high-contrast `#999999` backgrounds, `#000000` text/borders, and crisp `#ffffff` inputs. All standalone screens (`SettingsScreen`, `MaximizedInspectorScreen`, `AddEntryScreen`, etc.) must strictly conform to these CSS constants rather than the legacy v2 neon green (`#58f29d`, `#080a0c`).
|
||||
- In automated Textual UI interactive parity testing (`interactive_agent_tui_test.py`), avoid explicitly sending `await pilot.press('ctrl+p')` if standard textual palettes shadow custom `CommandPalette` widgets. Directly calling `app.action_open_palette()` guarantees stable integration assertions.
|
||||
- When mirroring nested manager logic (like BIP-85 sub-account loads), UI "breadcrumbs" should derive their explicit path strings from parsing the manager's `profile_stack` via a decoupled reactive property (e.g. `active_breadcrumb`), rather than mutating the core `active_fingerprint` references used for caching and view filtering.
|
||||
@@ -38,7 +38,11 @@ class AgentMockService:
|
||||
self.is_managed = False
|
||||
self.nostr_index = 0
|
||||
self.offline = False
|
||||
self._manager = SimpleNamespace(parent_seed="MOCK_PARENT_SEED")
|
||||
self._manager = SimpleNamespace(
|
||||
parent_seed="MOCK_PARENT_SEED",
|
||||
current_fingerprint="EFBE51E70ED1",
|
||||
profile_stack=[]
|
||||
)
|
||||
|
||||
# --- EntryService Interface ---
|
||||
def search_entries(self, query="", kinds=None, include_archived=False, archived_only=False):
|
||||
@@ -119,8 +123,16 @@ class AgentMockService:
|
||||
self.nostr_index += 1
|
||||
return self.nostr_index
|
||||
|
||||
def load_managed_account(self, entry_id): self.is_managed = True
|
||||
def exit_managed_account(self): self.is_managed = False
|
||||
def load_managed_account(self, entry_id):
|
||||
self.is_managed = True
|
||||
self._manager.profile_stack.append((self._manager.current_fingerprint, "path", "seed"))
|
||||
self._manager.current_fingerprint = f"SUBACCT{entry_id}"
|
||||
|
||||
def exit_managed_account(self):
|
||||
self.is_managed = False
|
||||
if self._manager.profile_stack:
|
||||
fp, _, _ = self._manager.profile_stack.pop()
|
||||
self._manager.current_fingerprint = fp
|
||||
|
||||
# --- Secret Data ---
|
||||
def get_totp_code(self, entry_id): return "888999"
|
||||
@@ -252,10 +264,17 @@ async def run_full_walkthrough(v="v3"):
|
||||
await pilot.pause(0.5)
|
||||
print(f" [OK] Profile Loaded: {service.is_managed == True}")
|
||||
|
||||
# Verify breadcrumb display
|
||||
brand_label = str(app.screen.query_one("#brand-fingerprint").render())
|
||||
print(f" [DEBUG] Breadcrumb text: {brand_label}")
|
||||
print(f" [OK] Sub-account breadcrumb structure visible: {'>' in brand_label and 'SUBACCT3' in brand_label}")
|
||||
|
||||
# Press 'shift+m' to exit profile
|
||||
await pilot.press('shift+m')
|
||||
await pilot.pause(0.5)
|
||||
print(f" [OK] Profile Exited: {service.is_managed == False}")
|
||||
brand_label_exit = str(app.screen.query_one("#brand-fingerprint").render())
|
||||
print(f" [OK] Breadcrumb reverted: {'>' not in brand_label_exit}")
|
||||
|
||||
# 6. Data I/O and Command Palette
|
||||
if v == "v3":
|
||||
|
||||
@@ -139,11 +139,11 @@ class BrandFingerprint(Static):
|
||||
"""Placeholder for the top left fingerprint block matching mockups."""
|
||||
def render(self) -> str:
|
||||
app = self.app
|
||||
fp = app.active_fingerprint or "No Profile"
|
||||
return f"{fp[:24]}"
|
||||
fp = app.active_breadcrumb or "No Profile"
|
||||
return f"{fp}"
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.watch(self.app, "active_fingerprint", self.refresh)
|
||||
self.watch(self.app, "active_breadcrumb", self.refresh)
|
||||
|
||||
class MainScreen(Screen):
|
||||
def compose(self) -> ComposeResult:
|
||||
@@ -207,6 +207,7 @@ class SeedPassTuiV3(App[None]):
|
||||
|
||||
# Shared Reactive State
|
||||
active_fingerprint = reactive("")
|
||||
active_breadcrumb = reactive("")
|
||||
selected_entry_id = reactive[int | None](None)
|
||||
session_locked = reactive(False)
|
||||
search_mode = reactive("keyword")
|
||||
@@ -287,6 +288,22 @@ class SeedPassTuiV3(App[None]):
|
||||
"""Refresh components when the profile changes."""
|
||||
if not new_fp:
|
||||
return
|
||||
|
||||
try:
|
||||
mgr = self.services["vault"]._manager
|
||||
paths = []
|
||||
for fp, _, _ in getattr(mgr, "profile_stack", []):
|
||||
paths.append(fp[:8])
|
||||
current = mgr.current_fingerprint[:8] if mgr.current_fingerprint else "???"
|
||||
|
||||
if paths:
|
||||
paths.append(current)
|
||||
self.active_breadcrumb = " > ".join(paths)
|
||||
else:
|
||||
self.active_breadcrumb = mgr.current_fingerprint[:24] if mgr.current_fingerprint else "No Profile"
|
||||
except Exception:
|
||||
self.active_breadcrumb = new_fp[:24]
|
||||
|
||||
# Notify sidebar and grid to refresh
|
||||
try:
|
||||
self.screen.query_one("#profile-tree")._refresh_tree()
|
||||
|
||||
Reference in new issue
Block a user