diff --git a/src/seedpass/tui_v3/screens/maintenance.py b/src/seedpass/tui_v3/screens/maintenance.py index be1bc40f..07ebd1e6 100644 --- a/src/seedpass/tui_v3/screens/maintenance.py +++ b/src/seedpass/tui_v3/screens/maintenance.py @@ -8,39 +8,39 @@ MAINTENANCE_CSS = """ text-style: bold; text-align: center; height: 3; - border: solid #000000; + border: solid #333333; padding: 0 1; margin: 1 2; } .maintenance-footer { - background: #000000; - color: #ffffff; + background: #111111; + color: #aaaaaa; text-align: center; height: 3; - border: solid #000000; + border: solid #333333; padding: 0 1; - margin: 1 2; + margin: 0 2 1 2; } .maintenance-panel-dark { padding: 1 2; - border: heavy black; + border: heavy #444444; background: #000000; - margin: 1 2; + margin: 0 2 1 2; } .maintenance-panel-light { padding: 1 2; - border: heavy #000000; + border: heavy #444444; background: #f3f3f3; - margin: 1 2; + margin: 0 2 1 2; } .maintenance-intro-dark { color: #d7d7d7; background: #111111; - border: solid #666666; + border: round #555555; padding: 1; margin-bottom: 1; } @@ -48,7 +48,7 @@ MAINTENANCE_CSS = """ .maintenance-intro-light { color: #222222; background: #e6e6e6; - border: solid #666666; + border: round #555555; padding: 1; margin-bottom: 1; } @@ -56,7 +56,7 @@ MAINTENANCE_CSS = """ .maintenance-status-dark { color: #ffffff; background: #111111; - border: solid #666666; + border: solid #444444; padding: 1; margin-top: 1; min-height: 3; @@ -65,7 +65,7 @@ MAINTENANCE_CSS = """ .maintenance-status-light { color: #000000; background: #e6e6e6; - border: solid #666666; + border: solid #444444; padding: 1; margin-top: 1; min-height: 3; @@ -103,9 +103,9 @@ MAINTENANCE_CSS = """ } .maintenance-danger { - background: #000000; + background: #880000; color: #ffffff; - border: solid #ffffff; + border: solid #ff4444; } .maintenance-secondary { diff --git a/src/seedpass/tui_v3/screens/profile.py b/src/seedpass/tui_v3/screens/profile.py index 9cc23c55..3066d83a 100644 --- a/src/seedpass/tui_v3/screens/profile.py +++ b/src/seedpass/tui_v3/screens/profile.py @@ -46,17 +46,17 @@ class ProfileManagementScreen(Screen): yield Static("SeedPass ◈ Profile Management", classes="maintenance-title") with Container(id="profile-container", classes="maintenance-panel-dark"): yield Static( - "Switch profiles from inside the active session, or remove a non-active profile after confirming the action.", + "Switch between profiles or remove unused ones. The active profile is marked with *. Removing a profile requires confirmation.", id="profile-intro", classes="maintenance-intro-dark", ) yield Static("", id="profile-list", classes="maintenance-intro-dark") - yield Label("Profile Number", classes="maintenance-label") - yield Input(placeholder="1", id="profile-choice", classes="maintenance-input") - yield Label("Password (optional for switch)", classes="maintenance-label") + yield Label("Select Profile", classes="maintenance-label") + yield Input(placeholder="Profile number", id="profile-choice", classes="maintenance-input") + yield Label("Password (required for switch)", classes="maintenance-label") yield Input(password=True, id="profile-password", classes="maintenance-input") yield Static( - format_status("ready", "Select a profile number, then switch or remove it."), + format_status("ready", "Choose a profile number, then use Switch or Remove."), id="profile-status", classes="maintenance-status-dark", ) @@ -65,7 +65,7 @@ class ProfileManagementScreen(Screen): yield Button("Remove", id="profile-remove", classes="maintenance-danger") yield Button("Back", id="profile-back", classes="maintenance-secondary") yield Static( - "ESC: Back | Ctrl+R: Refresh | Switch/Remove use the selected profile number", + "ESC: Back | Ctrl+R: Refresh | Select a profile number to switch or remove", classes="maintenance-footer", ) @@ -101,7 +101,7 @@ class ProfileManagementScreen(Screen): return current = self.app.active_fingerprint profiles = self._available_profiles() - lines = ["Available Profiles:"] + lines = ["Profiles"] for idx, profile in enumerate(profiles, start=1): fingerprint = profile["fingerprint"] label = profile["label"] @@ -113,7 +113,7 @@ class ProfileManagementScreen(Screen): if profiles: self.query_one("#profile-choice", Input).value = "1" self._set_status( - format_status("ready", "Select a profile number, then switch or remove it.") + format_status("ready", "Choose a profile number, then use Switch or Remove.") ) def _selected_profile(self) -> dict[str, str] | None: @@ -160,7 +160,7 @@ class ProfileManagementScreen(Screen): self._pending_remove_fingerprint = fingerprint self._set_status( format_status( - "warning", f"Press Remove again to delete profile '{label}'." + "warning", f"Confirm: press Remove again to permanently delete profile '{label}'." ) ) return diff --git a/src/seedpass/tui_v3/screens/pubkey.py b/src/seedpass/tui_v3/screens/pubkey.py index 81ce597d..4808ec55 100644 --- a/src/seedpass/tui_v3/screens/pubkey.py +++ b/src/seedpass/tui_v3/screens/pubkey.py @@ -16,7 +16,7 @@ class NostrPubkeyScreen(Screen): ("c", "copy_pubkey", "Copy npub"), ] - DEFAULT_CSS = ( + CSS = ( MAINTENANCE_CSS + """ NostrPubkeyScreen { @@ -41,7 +41,7 @@ class NostrPubkeyScreen(Screen): yield Static("SeedPass ◈ Active Profile npub", classes="maintenance-title") with Vertical(id="pubkey-container", classes="maintenance-panel-light"): yield Static( - "This is the active profile's public Nostr identifier and QR payload. Sharing the npub is safe; do not share private keys.", + "Your active profile public Nostr identifier (npub). This is safe to share. Never share private keys.", id="pubkey-intro", classes="maintenance-intro-light", ) @@ -52,7 +52,7 @@ class NostrPubkeyScreen(Screen): ) with Horizontal(id="pubkey-actions", classes="maintenance-actions"): yield Button("Copy npub", id="pubkey-copy", classes="maintenance-primary") - yield Static("ESC: Back | C: Copy npub", classes="maintenance-footer") + yield Static("ESC: Back | C: Copy npub to clipboard", classes="maintenance-footer") def on_mount(self) -> None: self._refresh_view() diff --git a/src/seedpass/tui_v3/screens/relays.py b/src/seedpass/tui_v3/screens/relays.py index 333706d9..2dd977d7 100644 --- a/src/seedpass/tui_v3/screens/relays.py +++ b/src/seedpass/tui_v3/screens/relays.py @@ -24,7 +24,7 @@ class RelaysScreen(Screen): ("s", "sync_now", "Sync Now"), ] - DEFAULT_CSS = ( + CSS = ( MAINTENANCE_CSS + """ RelaysScreen { @@ -58,6 +58,11 @@ class RelaysScreen(Screen): def compose(self) -> ComposeResult: yield Static("SeedPass ◈ Nostr Relay Management", classes="maintenance-title") with Vertical(id="relays-container", classes="maintenance-panel-light"): + yield Static( + "Manage Nostr relay endpoints for this profile. Add new relays or remove existing ones. Deletions require a second confirmation press.", + id="relays-intro", + classes="maintenance-intro-light", + ) yield DataTable(id="relays-table") with Horizontal(id="relays-controls"): yield Input( @@ -67,15 +72,12 @@ class RelaysScreen(Screen): ) yield Button("Add Relay", id="add-button", classes="maintenance-primary") yield Static( - format_status( - "ready", - "Manage relay endpoints for this profile. Deleting a relay requires a second confirm action.", - ), + format_status("ready", "Select a relay or add a new endpoint."), id="relays-status", classes="maintenance-status-light", ) yield Static( - "ESC: Exit | R: Refresh | D: Delete Selected | S: Sync Now", + "ESC: Back | R: Refresh | D: Delete selected | S: Sync now", classes="maintenance-footer", ) diff --git a/src/seedpass/tui_v3/screens/security.py b/src/seedpass/tui_v3/screens/security.py index a811ef51..8bfc5816 100644 --- a/src/seedpass/tui_v3/screens/security.py +++ b/src/seedpass/tui_v3/screens/security.py @@ -37,7 +37,7 @@ class ChangePasswordScreen(Screen): yield Static("SeedPass ◈ Change Vault Password", classes="maintenance-title") with Container(id="change-password-container", classes="maintenance-panel-dark"): yield Static( - "Update the active vault password for this profile. The current password is required to re-encrypt the vault.", + "Change the vault password for the active profile. You must provide the current password to authorize re-encryption.", id="change-password-intro", classes="maintenance-intro-dark", ) @@ -55,7 +55,7 @@ class ChangePasswordScreen(Screen): with Horizontal(id="change-password-actions", classes="maintenance-actions"): yield Button("Cancel", id="change-password-cancel", classes="maintenance-danger") yield Button("Update Password", id="change-password-submit", classes="maintenance-primary") - yield Static("ESC: Cancel | Ctrl+S: Update Password", classes="maintenance-footer") + yield Static("ESC: Cancel | Ctrl+S: Submit", classes="maintenance-footer") def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "change-password-submit": @@ -108,7 +108,7 @@ class BackupParentSeedScreen(Screen): yield Static("SeedPass ◈ Backup Parent Seed", classes="maintenance-title") with Container(id="backup-seed-container", classes="maintenance-panel-dark"): yield Static( - "Export an encrypted backup of the parent seed. Store the destination path and backup password securely.", + "Export an encrypted copy of the parent seed. Choose a destination path and an optional backup password. Store both securely.", id="backup-seed-intro", classes="maintenance-intro-dark", ) @@ -124,7 +124,7 @@ class BackupParentSeedScreen(Screen): with Horizontal(id="backup-seed-actions", classes="maintenance-actions"): yield Button("Cancel", id="backup-seed-cancel", classes="maintenance-danger") yield Button("Export Backup", id="backup-seed-submit", classes="maintenance-primary") - yield Static("ESC: Cancel | Ctrl+S: Export Backup", classes="maintenance-footer") + yield Static("ESC: Cancel | Ctrl+S: Submit", classes="maintenance-footer") def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "backup-seed-submit": diff --git a/src/tests/test_tui_v3_smoke.py b/src/tests/test_tui_v3_smoke.py index e984d887..d66ebdd6 100644 --- a/src/tests/test_tui_v3_smoke.py +++ b/src/tests/test_tui_v3_smoke.py @@ -648,7 +648,7 @@ async def test_tui3_change_password_and_seed_backup_flows_use_vault_service() -> await pilot.pause() assert isinstance(app.screen, ChangePasswordScreen) assert ( - "current password is required" + "current password to authorize" in str( app.screen.query_one("#change-password-intro", Static).render() ).lower() @@ -691,7 +691,7 @@ async def test_tui3_profile_management_switch_and_remove_flow_use_profile_servic await pilot.pause() assert isinstance(app.screen, ProfileManagementScreen) intro = str(app.screen.query_one("#profile-intro", Static).render()).lower() - assert "remove a non-active profile" in intro + assert "removing a profile requires confirmation" in intro listing = str(app.screen.query_one("#profile-list", Static).render()) assert "Primary Ops Seed" in listing assert "Recovery Seed" in listing @@ -711,7 +711,7 @@ async def test_tui3_profile_management_switch_and_remove_flow_use_profile_servic await pilot.pause() assert profile.remove_calls == [] status = str(app.screen.query_one("#profile-status", Static).render()) - assert "Press Remove again" in status + assert "press Remove again" in status app.screen.on_button_pressed( SimpleNamespace(button=SimpleNamespace(id="profile-remove")) )