Polish TUI v3 maintenance and profile screens

- maintenance.py: refine CSS visual hierarchy (rounded intro card borders,
  red-tinted danger buttons, consistent panel/footer margins)
- profile.py: clearer label text, improved intro and confirmation messages
- security.py: updated intro text and footer hints for both screens
- pubkey.py: rename DEFAULT_CSS to CSS, update intro and footer text
- relays.py: rename DEFAULT_CSS to CSS, add intro card, update footer/status
- test_tui_v3_smoke.py: update assertions to match new text

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Sonnet 4.6 committed 2026-03-06 13:30:08 -05:00
1 parent ca31abf33e
commit 50d7b1827d
6 files changed
+42 -40

No files matched your search

+15 -15
View File
@@ -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 {
+9 -9
View File
@@ -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
+3 -3
View File
@@ -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()
+8 -6
View File
@@ -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",
)
+4 -4
View File
@@ -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":
+3 -3
View File
@@ -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"))
)