Simplify menus with Enter navigation

This commit is contained in:
thePR0M3TH3AN
2025-07-06 07:57:02 -04:00
parent d40a64f6da
commit 876ed71f74
8 changed files with 31 additions and 44 deletions

View File

@@ -577,8 +577,7 @@ def handle_profiles_menu(password_manager: PasswordManager) -> None:
print(color_text("2. Add a New Seed Profile", "menu"))
print(color_text("3. Remove an Existing Seed Profile", "menu"))
print(color_text("4. List All Seed Profiles", "menu"))
print(color_text("5. Back", "menu"))
choice = input("Select an option: ").strip()
choice = input("Select an option or press Enter to go back: ").strip()
password_manager.update_activity()
if choice == "1":
if not password_manager.handle_switch_fingerprint():
@@ -589,7 +588,7 @@ def handle_profiles_menu(password_manager: PasswordManager) -> None:
handle_remove_fingerprint(password_manager)
elif choice == "4":
handle_list_fingerprints(password_manager)
elif choice == "5":
elif not choice:
break
else:
print(colored("Invalid choice.", "red"))
@@ -617,8 +616,7 @@ def handle_nostr_menu(password_manager: PasswordManager) -> None:
print(color_text("5. Remove a relay by number", "menu"))
print(color_text("6. Reset to default relays", "menu"))
print(color_text("7. Display Nostr Public Key", "menu"))
print(color_text("8. Back", "menu"))
choice = input("Select an option: ").strip()
choice = input("Select an option or press Enter to go back: ").strip()
password_manager.update_activity()
if choice == "1":
handle_post_to_nostr(password_manager)
@@ -634,7 +632,7 @@ def handle_nostr_menu(password_manager: PasswordManager) -> None:
handle_reset_relays(password_manager)
elif choice == "7":
handle_display_npub(password_manager)
elif choice == "8":
elif not choice:
break
else:
print(colored("Invalid choice.", "red"))
@@ -659,8 +657,7 @@ def handle_settings(password_manager: PasswordManager) -> None:
print(color_text("12. Lock Vault", "menu"))
print(color_text("13. Stats", "menu"))
print(color_text("14. Toggle Secret Mode", "menu"))
print(color_text("15. Back", "menu"))
choice = input("Select an option: ").strip()
choice = input("Select an option or press Enter to go back: ").strip()
if choice == "1":
handle_profiles_menu(password_manager)
pause()
@@ -707,7 +704,7 @@ def handle_settings(password_manager: PasswordManager) -> None:
elif choice == "14":
handle_toggle_secret_mode(password_manager)
pause()
elif choice == "15":
elif not choice:
break
else:
print(colored("Invalid choice.", "red"))
@@ -730,7 +727,6 @@ def display_menu(
5. Modify an Existing Entry
6. 2FA Codes
7. Settings
8. Exit
"""
display_fn = getattr(password_manager, "display_stats", None)
if callable(display_fn):
@@ -757,7 +753,8 @@ def display_menu(
print(color_text(menu, "menu"))
try:
choice = timed_input(
"Enter your choice (1-8): ", inactivity_timeout
"Enter your choice (1-7) or press Enter to exit: ",
inactivity_timeout,
).strip()
except TimeoutError:
print(colored("Session timed out. Vault locked.", "yellow"))
@@ -766,13 +763,10 @@ def display_menu(
continue
password_manager.update_activity()
if not choice:
print(
colored(
"No input detected. Please enter a number between 1 and 8.",
"yellow",
)
)
continue # Re-display the menu without marking as invalid
logging.info("Exiting the program.")
print(colored("Exiting the program.", "green"))
password_manager.nostr_client.close_client_pool()
sys.exit(0)
if choice == "1":
while True:
print(color_text("\nAdd Entry:", "menu"))
@@ -782,8 +776,9 @@ def display_menu(
print(color_text("4. Seed Phrase", "menu"))
print(color_text("5. Nostr Key Pair", "menu"))
print(color_text("6. PGP Key", "menu"))
print(color_text("7. Back", "menu"))
sub_choice = input("Select entry type: ").strip()
sub_choice = input(
"Select entry type or press Enter to go back: "
).strip()
password_manager.update_activity()
if sub_choice == "1":
password_manager.handle_add_password()
@@ -803,7 +798,7 @@ def display_menu(
elif sub_choice == "6":
password_manager.handle_add_pgp()
break
elif sub_choice == "7":
elif not sub_choice:
break
else:
print(colored("Invalid choice.", "red"))
@@ -826,11 +821,6 @@ def display_menu(
elif choice == "7":
password_manager.update_activity()
handle_settings(password_manager)
elif choice == "8":
logging.info("Exiting the program.")
print(colored("Exiting the program.", "green"))
password_manager.nostr_client.close_client_pool()
sys.exit(0)
else:
print(colored("Invalid choice. Please select a valid option.", "red"))

View File

@@ -978,8 +978,7 @@ class PasswordManager:
print("\nAdd TOTP:")
print("1. Make 2FA (derive from seed)")
print("2. Import 2FA (paste otpauth URI or secret)")
print("3. Back")
choice = input("Select option: ").strip()
choice = input("Select option or press Enter to go back: ").strip()
if choice == "1":
label = input("Label: ").strip()
if not label:
@@ -1062,7 +1061,7 @@ class PasswordManager:
break
except ValueError as err:
print(colored(f"Error: {err}", "red"))
elif choice == "3":
elif not choice:
return
else:
print(colored("Invalid choice.", "red"))
@@ -1978,8 +1977,7 @@ class PasswordManager:
print(color_text("5. Seed Phrase", "menu"))
print(color_text("6. Nostr Key Pair", "menu"))
print(color_text("7. PGP", "menu"))
print(color_text("8. Back", "menu"))
choice = input("Select entry type: ").strip()
choice = input("Select entry type or press Enter to go back: ").strip()
if choice == "1":
filter_kind = None
elif choice == "2":
@@ -1994,7 +1992,7 @@ class PasswordManager:
filter_kind = EntryType.NOSTR.value
elif choice == "7":
filter_kind = EntryType.PGP.value
elif choice == "8":
elif not choice:
return
else:
print(colored("Invalid choice.", "red"))

View File

@@ -31,7 +31,7 @@ def test_auto_sync_triggers_post(monkeypatch):
called = True
monkeypatch.setattr(main, "handle_post_to_nostr", fake_post)
monkeypatch.setattr(main, "timed_input", lambda *_: "8")
monkeypatch.setattr(main, "timed_input", lambda *_: "")
with pytest.raises(SystemExit):
main.display_menu(pm, sync_interval=0.1)

View File

@@ -52,12 +52,11 @@ def _make_pm(called, locked=None):
def test_empty_and_non_numeric_choice(monkeypatch, capsys):
called = {"add": False, "retrieve": False, "modify": False}
pm, _ = _make_pm(called)
inputs = iter(["", "abc", "8"])
inputs = iter(["abc", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
with pytest.raises(SystemExit):
main.display_menu(pm, sync_interval=1000, inactivity_timeout=1000)
out = capsys.readouterr().out
assert "No input detected" in out
assert "Invalid choice. Please select a valid option." in out
assert not any(called.values())
@@ -65,7 +64,7 @@ def test_empty_and_non_numeric_choice(monkeypatch, capsys):
def test_out_of_range_menu(monkeypatch, capsys):
called = {"add": False, "retrieve": False, "modify": False}
pm, _ = _make_pm(called)
inputs = iter(["9", "8"])
inputs = iter(["9", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
with pytest.raises(SystemExit):
main.display_menu(pm, sync_interval=1000, inactivity_timeout=1000)
@@ -77,7 +76,7 @@ def test_out_of_range_menu(monkeypatch, capsys):
def test_invalid_add_entry_submenu(monkeypatch, capsys):
called = {"add": False, "retrieve": False, "modify": False}
pm, _ = _make_pm(called)
inputs = iter(["1", "8", "7", "8"])
inputs = iter(["1", "8", "", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
monkeypatch.setattr("builtins.input", lambda *_: next(inputs))
with pytest.raises(SystemExit):
@@ -92,7 +91,7 @@ def test_inactivity_timeout_loop(monkeypatch, capsys):
pm, locked = _make_pm(called)
pm.last_activity = 0
monkeypatch.setattr(time, "time", lambda: 100.0)
monkeypatch.setattr(main, "timed_input", lambda *_: "8")
monkeypatch.setattr(main, "timed_input", lambda *_: "")
with pytest.raises(SystemExit):
main.display_menu(pm, sync_interval=1000, inactivity_timeout=0.1)
out = capsys.readouterr().out

View File

@@ -36,7 +36,7 @@ def test_inactivity_triggers_lock(monkeypatch):
unlock_vault=unlock_vault,
)
monkeypatch.setattr(main, "timed_input", lambda *_: "8")
monkeypatch.setattr(main, "timed_input", lambda *_: "")
with pytest.raises(SystemExit):
main.display_menu(pm, sync_interval=1000, inactivity_timeout=0.1)
@@ -72,7 +72,7 @@ def test_input_timeout_triggers_lock(monkeypatch):
unlock_vault=unlock_vault,
)
responses = iter([TimeoutError(), "8"])
responses = iter([TimeoutError(), ""])
def fake_input(*_args, **_kwargs):
val = next(responses)

View File

@@ -30,7 +30,7 @@ def _make_pm(calls):
def test_menu_totp_option(monkeypatch):
calls = []
pm = _make_pm(calls)
inputs = iter(["6", "8"])
inputs = iter(["6", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
monkeypatch.setattr(main, "handle_settings", lambda *_: None)
with pytest.raises(SystemExit):
@@ -41,7 +41,7 @@ def test_menu_totp_option(monkeypatch):
def test_menu_settings_option(monkeypatch):
calls = []
pm = _make_pm(calls)
inputs = iter(["7", "8"])
inputs = iter(["7", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
monkeypatch.setattr(main, "handle_settings", lambda *_: calls.append("settings"))
with pytest.raises(SystemExit):

View File

@@ -30,7 +30,7 @@ def _make_pm(called):
def test_menu_search_option(monkeypatch):
called = []
pm = _make_pm(called)
inputs = iter(["3", "8"])
inputs = iter(["3", ""])
monkeypatch.setattr(main, "timed_input", lambda *_: next(inputs))
monkeypatch.setattr("builtins.input", lambda *_: "query")
with pytest.raises(SystemExit):

View File

@@ -93,7 +93,7 @@ def test_settings_menu_additional_backup(monkeypatch):
tmp_path = Path(tmpdir)
pm, cfg_mgr, fp_mgr = setup_pm(tmp_path, monkeypatch)
inputs = iter(["10", "15"])
inputs = iter(["10", ""])
with patch("main.handle_set_additional_backup_location") as handler:
with patch("builtins.input", side_effect=lambda *_: next(inputs)):
main.handle_settings(pm)