Add custom seed profile names

This commit is contained in:
thePR0M3TH3AN
2025-07-15 21:56:31 -04:00
parent 40bd009b6e
commit 113fd1181a
6 changed files with 111 additions and 22 deletions

View File

@@ -151,7 +151,8 @@ def handle_switch_fingerprint(password_manager: PasswordManager):
print(colored("Available Seed Profiles:", "cyan"))
for idx, fp in enumerate(fingerprints, start=1):
print(colored(f"{idx}. {fp}", "cyan"))
label = password_manager.fingerprint_manager.display_name(fp)
print(colored(f"{idx}. {label}", "cyan"))
choice = input("Select a seed profile by number to switch: ").strip()
if not choice.isdigit() or not (1 <= int(choice) <= len(fingerprints)):
@@ -195,7 +196,8 @@ def handle_remove_fingerprint(password_manager: PasswordManager):
print(colored("Available Seed Profiles:", "cyan"))
for idx, fp in enumerate(fingerprints, start=1):
print(colored(f"{idx}. {fp}", "cyan"))
label = password_manager.fingerprint_manager.display_name(fp)
print(colored(f"{idx}. {label}", "cyan"))
choice = input("Select a seed profile by number to remove: ").strip()
if not choice.isdigit() or not (1 <= int(choice) <= len(fingerprints)):
@@ -239,7 +241,8 @@ def handle_list_fingerprints(password_manager: PasswordManager):
print(colored("Available Seed Profiles:", "cyan"))
for fp in fingerprints:
print(colored(f"- {fp}", "cyan"))
label = password_manager.fingerprint_manager.display_name(fp)
print(colored(f"- {label}", "cyan"))
pause()
except Exception as e:
logging.error(f"Error listing seed profiles: {e}", exc_info=True)
@@ -641,6 +644,25 @@ def handle_set_additional_backup_location(pm: PasswordManager) -> None:
print(colored(f"Error: {e}", "red"))
def handle_set_profile_name(pm: PasswordManager) -> None:
"""Set or clear the custom name for the current seed profile."""
fp = getattr(pm.fingerprint_manager, "current_fingerprint", None)
if not fp:
print(colored("No seed profile selected.", "red"))
return
current = pm.fingerprint_manager.get_name(fp)
if current:
print(colored(f"Current name: {current}", "cyan"))
else:
print(colored("No custom name set.", "cyan"))
value = input("Enter new name (leave blank to remove): ").strip()
if pm.fingerprint_manager.set_name(fp, value or None):
if value:
print(colored("Name updated.", "green"))
else:
print(colored("Name removed.", "green"))
def handle_toggle_secret_mode(pm: PasswordManager) -> None:
"""Toggle secret mode and adjust clipboard delay."""
cfg = pm.config_manager
@@ -756,6 +778,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. Set Seed Profile Name", "menu"))
choice = input("Select an option or press Enter to go back: ").strip()
password_manager.update_activity()
if choice == "1":
@@ -767,6 +790,8 @@ def handle_profiles_menu(password_manager: PasswordManager) -> None:
handle_remove_fingerprint(password_manager)
elif choice == "4":
handle_list_fingerprints(password_manager)
elif choice == "5":
handle_set_profile_name(password_manager)
elif not choice:
break
else:

View File

@@ -329,8 +329,13 @@ class PasswordManager:
print(colored("\nAvailable Seed Profiles:", "cyan"))
for idx, fp in enumerate(fingerprints, start=1):
label = (
self.fingerprint_manager.display_name(fp)
if hasattr(self.fingerprint_manager, "display_name")
else fp
)
marker = " *" if fp == current else ""
print(colored(f"{idx}. {fp}{marker}", "cyan"))
print(colored(f"{idx}. {label}{marker}", "cyan"))
print(colored(f"{len(fingerprints)+1}. Add a new seed profile", "cyan"))
@@ -532,7 +537,12 @@ class PasswordManager:
print(colored("\nAvailable Seed Profiles:", "cyan"))
fingerprints = self.fingerprint_manager.list_fingerprints()
for idx, fp in enumerate(fingerprints, start=1):
print(colored(f"{idx}. {fp}", "cyan"))
display = (
self.fingerprint_manager.display_name(fp)
if hasattr(self.fingerprint_manager, "display_name")
else fp
)
print(colored(f"{idx}. {display}", "cyan"))
choice = input("Select a seed profile by number to switch: ").strip()
if not choice.isdigit() or not (1 <= int(choice) <= len(fingerprints)):
@@ -680,7 +690,12 @@ class PasswordManager:
print(colored("Available Seed Profiles:", "cyan"))
for idx, fp in enumerate(fingerprints, start=1):
print(colored(f"{idx}. {fp}", "cyan"))
label = (
self.fingerprint_manager.display_name(fp)
if hasattr(self.fingerprint_manager, "display_name")
else fp
)
print(colored(f"{idx}. {label}", "cyan"))
choice = input("Select a seed profile by number: ").strip()
if not choice.isdigit() or not (1 <= int(choice) <= len(fingerprints)):

View File

@@ -34,7 +34,11 @@ class FingerprintManager:
self.app_dir = app_dir
self.fingerprints_file = self.app_dir / "fingerprints.json"
self._ensure_app_directory()
self.fingerprints, self.current_fingerprint = self._load_fingerprints()
(
self.fingerprints,
self.current_fingerprint,
self.names,
) = self._load_fingerprints()
def get_current_fingerprint_dir(self) -> Optional[Path]:
"""
@@ -62,25 +66,26 @@ class FingerprintManager:
)
raise
def _load_fingerprints(self) -> tuple[list[str], Optional[str]]:
"""Return stored fingerprints and the last used fingerprint."""
def _load_fingerprints(self) -> tuple[list[str], Optional[str], dict[str, str]]:
"""Return stored fingerprints, the last used fingerprint, and name mapping."""
try:
if self.fingerprints_file.exists():
with open(self.fingerprints_file, "r") as f:
data = json.load(f)
fingerprints = data.get("fingerprints", [])
current = data.get("last_used")
names = data.get("names", {})
logger.debug(
f"Loaded fingerprints: {fingerprints} (last used: {current})"
)
return fingerprints, current
return fingerprints, current, names
logger.debug(
"fingerprints.json not found. Initializing empty fingerprint list."
)
return [], None
return [], None, {}
except Exception as e:
logger.error(f"Failed to load fingerprints: {e}", exc_info=True)
return [], None
return [], None, {}
def _save_fingerprints(self):
"""
@@ -92,6 +97,7 @@ class FingerprintManager:
{
"fingerprints": self.fingerprints,
"last_used": self.current_fingerprint,
"names": self.names,
},
f,
indent=4,
@@ -116,6 +122,7 @@ class FingerprintManager:
fingerprint = generate_fingerprint(seed_phrase)
if fingerprint and fingerprint not in self.fingerprints:
self.fingerprints.append(fingerprint)
self.names.setdefault(fingerprint, "")
self.current_fingerprint = fingerprint
self._save_fingerprints()
logger.info(f"Fingerprint {fingerprint} added successfully.")
@@ -144,6 +151,7 @@ class FingerprintManager:
if fingerprint in self.fingerprints:
try:
self.fingerprints.remove(fingerprint)
self.names.pop(fingerprint, None)
if self.current_fingerprint == fingerprint:
self.current_fingerprint = (
self.fingerprints[0] if self.fingerprints else None
@@ -198,6 +206,26 @@ class FingerprintManager:
logger.error(f"Fingerprint {fingerprint} not found.")
return False
def set_name(self, fingerprint: str, name: str | None) -> bool:
"""Set a custom name for a fingerprint."""
if fingerprint not in self.fingerprints:
return False
if name:
self.names[fingerprint] = name
else:
self.names.pop(fingerprint, None)
self._save_fingerprints()
return True
def get_name(self, fingerprint: str) -> Optional[str]:
"""Return the custom name for ``fingerprint`` if set."""
return self.names.get(fingerprint) or None
def display_name(self, fingerprint: str) -> str:
"""Return name and fingerprint for display."""
name = self.get_name(fingerprint)
return f"{name} ({fingerprint})" if name else fingerprint
def get_fingerprint_directory(self, fingerprint: str) -> Optional[Path]:
"""
Retrieves the directory path for a given fingerprint.

View File

@@ -8,6 +8,20 @@ from termcolor import colored
from utils.color_scheme import color_text
def format_profile(fingerprint: str | None, pm=None) -> str | None:
"""Return display string for a fingerprint with optional custom name."""
if not fingerprint:
return None
if pm and getattr(pm, "fingerprint_manager", None):
try:
name = pm.fingerprint_manager.get_name(fingerprint)
if name:
return f"{name} ({fingerprint})"
except Exception:
pass
return fingerprint
def clear_screen() -> None:
"""Clear the terminal screen using an ANSI escape code."""
print("\033c", end="")
@@ -18,16 +32,17 @@ def clear_and_print_fingerprint(
breadcrumb: str | None = None,
parent_fingerprint: str | None = None,
child_fingerprint: str | None = None,
pm=None,
) -> None:
"""Clear the screen and optionally display the current fingerprint and path."""
clear_screen()
header_fp = None
if parent_fingerprint and child_fingerprint:
header_fp = f"{parent_fingerprint} > Managed Account > {child_fingerprint}"
header_fp = f"{format_profile(parent_fingerprint, pm)} > Managed Account > {format_profile(child_fingerprint, pm)}"
elif fingerprint:
header_fp = fingerprint
header_fp = format_profile(fingerprint, pm)
elif parent_fingerprint or child_fingerprint:
header_fp = parent_fingerprint or child_fingerprint
header_fp = format_profile(parent_fingerprint or child_fingerprint, pm)
if header_fp:
header = f"Seed Profile: {header_fp}"
if breadcrumb:
@@ -36,15 +51,15 @@ def clear_and_print_fingerprint(
def clear_and_print_profile_chain(
fingerprints: list[str] | None, breadcrumb: str | None = None
fingerprints: list[str] | None, breadcrumb: str | None = None, pm=None
) -> None:
"""Clear the screen and display a chain of fingerprints."""
clear_screen()
if not fingerprints:
return
chain = fingerprints[0]
chain = format_profile(fingerprints[0], pm)
for fp in fingerprints[1:]:
chain += f" > Managed Account > {fp}"
chain += f" > Managed Account > {format_profile(fp, pm)}"
header = f"Seed Profile: {chain}"
if breadcrumb:
header += f" > {breadcrumb}"
@@ -63,11 +78,11 @@ def clear_header_with_notification(
clear_screen()
header_fp = None
if parent_fingerprint and child_fingerprint:
header_fp = f"{parent_fingerprint} > Managed Account > {child_fingerprint}"
header_fp = f"{format_profile(parent_fingerprint, pm)} > Managed Account > {format_profile(child_fingerprint, pm)}"
elif fingerprint:
header_fp = fingerprint
header_fp = format_profile(fingerprint, pm)
elif parent_fingerprint or child_fingerprint:
header_fp = parent_fingerprint or child_fingerprint
header_fp = format_profile(parent_fingerprint or child_fingerprint, pm)
if header_fp:
header = f"Seed Profile: {header_fp}"
if breadcrumb: