Redesign TOTP code display: larger timer, thicker progress bar, color sync
- Code font: 42 → 52pt - Timer: separate big seconds (28pt bold) + "sec" unit label - Progress bar: 300×6 → 400×10, rounded corners, dark track (#2a2a3e) - Timer + progress bar color syncs with code (green → yellow → red) - Code frame corner radius 12 → 16, more padding Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -37,30 +37,47 @@ class TOTPTab(ctk.CTkFrame):
|
||||
self.server_label.pack(fill="x", padx=15, pady=(0, 10))
|
||||
|
||||
# Code display frame — clickable
|
||||
self.code_frame = ctk.CTkFrame(self, fg_color="#1e1e2e", corner_radius=12, cursor="hand2")
|
||||
self.code_frame = ctk.CTkFrame(self, fg_color="#1e1e2e", corner_radius=16, cursor="hand2")
|
||||
self.code_frame.pack(fill="x", padx=15, pady=(0, 10))
|
||||
|
||||
self.code_label = ctk.CTkLabel(
|
||||
self.code_frame, text="------",
|
||||
font=ctk.CTkFont(family="Consolas", size=42, weight="bold"),
|
||||
font=ctk.CTkFont(family="Consolas", size=52, weight="bold"),
|
||||
text_color="#22c55e", cursor="hand2"
|
||||
)
|
||||
self.code_label.pack(pady=(20, 5))
|
||||
self.code_label.pack(pady=(25, 2))
|
||||
|
||||
self.timer_label = ctk.CTkLabel(
|
||||
self.code_frame, text="",
|
||||
font=ctk.CTkFont(size=12), text_color="#9ca3af"
|
||||
# Timer: big seconds number + label
|
||||
timer_row = ctk.CTkFrame(self.code_frame, fg_color="transparent", cursor="hand2")
|
||||
timer_row.pack(pady=(0, 8))
|
||||
|
||||
self.timer_sec_label = ctk.CTkLabel(
|
||||
timer_row, text="",
|
||||
font=ctk.CTkFont(family="Consolas", size=28, weight="bold"),
|
||||
text_color="#22c55e"
|
||||
)
|
||||
self.timer_label.pack(pady=(0, 5))
|
||||
self.timer_sec_label.pack(side="left")
|
||||
|
||||
self.progress_bar = ctk.CTkProgressBar(self.code_frame, width=300, height=6)
|
||||
self.progress_bar.pack(pady=(0, 15))
|
||||
self.timer_unit_label = ctk.CTkLabel(
|
||||
timer_row, text="",
|
||||
font=ctk.CTkFont(size=14),
|
||||
text_color="#6b7280"
|
||||
)
|
||||
self.timer_unit_label.pack(side="left", padx=(4, 0), pady=(6, 0))
|
||||
|
||||
self.progress_bar = ctk.CTkProgressBar(
|
||||
self.code_frame, width=400, height=10,
|
||||
corner_radius=5,
|
||||
progress_color="#22c55e",
|
||||
fg_color="#2a2a3e"
|
||||
)
|
||||
self.progress_bar.pack(pady=(0, 20), padx=40)
|
||||
self.progress_bar.set(1.0)
|
||||
|
||||
# Click anywhere on the code frame → copy
|
||||
self.code_frame.bind("<Button-1>", lambda e: self._copy_code())
|
||||
self.code_label.bind("<Button-1>", lambda e: self._copy_code())
|
||||
self.timer_label.bind("<Button-1>", lambda e: self._copy_code())
|
||||
for widget in (self.code_frame, self.code_label, timer_row,
|
||||
self.timer_sec_label, self.timer_unit_label):
|
||||
widget.bind("<Button-1>", lambda e: self._copy_code())
|
||||
|
||||
# Copy button
|
||||
self.copy_btn = ctk.CTkButton(
|
||||
@@ -131,9 +148,11 @@ class TOTPTab(ctk.CTkFrame):
|
||||
|
||||
if not alias:
|
||||
self.server_label.configure(text=t("no_server_selected"))
|
||||
self.code_label.configure(text="------")
|
||||
self.timer_label.configure(text="")
|
||||
self.code_label.configure(text="------", text_color="#22c55e")
|
||||
self.timer_sec_label.configure(text="")
|
||||
self.timer_unit_label.configure(text="")
|
||||
self.progress_bar.set(1.0)
|
||||
self.progress_bar.configure(progress_color="#6b7280")
|
||||
self.secret_entry.delete(0, "end")
|
||||
self.status_label.configure(text="")
|
||||
return
|
||||
@@ -150,8 +169,10 @@ class TOTPTab(ctk.CTkFrame):
|
||||
self._start_timer()
|
||||
else:
|
||||
self.code_label.configure(text="------")
|
||||
self.timer_label.configure(text=t("totp_no_secret"))
|
||||
self.timer_sec_label.configure(text="")
|
||||
self.timer_unit_label.configure(text=t("totp_no_secret"))
|
||||
self.progress_bar.set(1.0)
|
||||
self.progress_bar.configure(progress_color="#6b7280")
|
||||
|
||||
def _start_timer(self):
|
||||
self._stop_timer()
|
||||
@@ -173,8 +194,10 @@ class TOTPTab(ctk.CTkFrame):
|
||||
secret = server.get("totp_secret", "")
|
||||
if not secret:
|
||||
self.code_label.configure(text="------")
|
||||
self.timer_label.configure(text=t("totp_no_secret"))
|
||||
self.timer_sec_label.configure(text="")
|
||||
self.timer_unit_label.configure(text=t("totp_no_secret"))
|
||||
self.progress_bar.set(1.0)
|
||||
self.progress_bar.configure(progress_color="#6b7280")
|
||||
return
|
||||
|
||||
try:
|
||||
@@ -187,20 +210,26 @@ class TOTPTab(ctk.CTkFrame):
|
||||
# Format code with space in middle: "123 456"
|
||||
formatted = f"{code[:3]} {code[3:]}"
|
||||
self.code_label.configure(text=formatted)
|
||||
self.timer_label.configure(text=t("totp_remaining").format(sec=remaining))
|
||||
self.timer_sec_label.configure(text=str(remaining))
|
||||
self.timer_unit_label.configure(text="sec")
|
||||
self.progress_bar.set(progress)
|
||||
|
||||
# Color based on time remaining
|
||||
# Color based on time remaining — code, timer, progress bar
|
||||
if remaining <= 5:
|
||||
self.code_label.configure(text_color="#ef4444")
|
||||
color = "#ef4444"
|
||||
elif remaining <= 10:
|
||||
self.code_label.configure(text_color="#f59e0b")
|
||||
color = "#f59e0b"
|
||||
else:
|
||||
self.code_label.configure(text_color="#22c55e")
|
||||
color = "#22c55e"
|
||||
|
||||
self.code_label.configure(text_color=color)
|
||||
self.timer_sec_label.configure(text_color=color)
|
||||
self.progress_bar.configure(progress_color=color)
|
||||
|
||||
except Exception as e:
|
||||
self.code_label.configure(text="ERROR")
|
||||
self.timer_label.configure(text=str(e))
|
||||
self.timer_sec_label.configure(text="")
|
||||
self.timer_unit_label.configure(text=str(e))
|
||||
|
||||
# Schedule next update in 1 second
|
||||
self._timer_id = self.after(1000, self._update_code)
|
||||
@@ -278,8 +307,10 @@ class TOTPTab(ctk.CTkFrame):
|
||||
self.secret_entry.delete(0, "end")
|
||||
self._stop_timer()
|
||||
self.code_label.configure(text="------", text_color="#22c55e")
|
||||
self.timer_label.configure(text="")
|
||||
self.timer_sec_label.configure(text="")
|
||||
self.timer_unit_label.configure(text="")
|
||||
self.progress_bar.set(1.0)
|
||||
self.progress_bar.configure(progress_color="#6b7280")
|
||||
self.status_label.configure(text=t("totp_secret_removed"), text_color="#9ca3af")
|
||||
self.after(2000, lambda: self.status_label.configure(text=""))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user