mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-29 08:52:04 +00:00
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:
1 parent
ca31abf33e
commit
50d7b1827d
6 files changed
+42
-40
No files matched your search
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
|
||||
@@ -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":
|
||||
|
||||
@@ -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"))
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user