Add click-to-copy animation on TOTP code display
- Click anywhere on the code area copies to clipboard - Visual feedback: green flash + checkmark for 400ms - Hand cursor on code frame, label, and timer - Copy button still works as before Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -36,27 +36,32 @@ class TOTPTab(ctk.CTkFrame):
|
||||
)
|
||||
self.server_label.pack(fill="x", padx=15, pady=(0, 10))
|
||||
|
||||
# Code display frame
|
||||
code_frame = ctk.CTkFrame(self, fg_color="#1e1e2e", corner_radius=12)
|
||||
code_frame.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.pack(fill="x", padx=15, pady=(0, 10))
|
||||
|
||||
self.code_label = ctk.CTkLabel(
|
||||
code_frame, text="------",
|
||||
self.code_frame, text="------",
|
||||
font=ctk.CTkFont(family="Consolas", size=42, weight="bold"),
|
||||
text_color="#22c55e"
|
||||
text_color="#22c55e", cursor="hand2"
|
||||
)
|
||||
self.code_label.pack(pady=(20, 5))
|
||||
|
||||
self.timer_label = ctk.CTkLabel(
|
||||
code_frame, text="",
|
||||
self.code_frame, text="",
|
||||
font=ctk.CTkFont(size=12), text_color="#9ca3af"
|
||||
)
|
||||
self.timer_label.pack(pady=(0, 5))
|
||||
|
||||
self.progress_bar = ctk.CTkProgressBar(code_frame, width=300, height=6)
|
||||
self.progress_bar = ctk.CTkProgressBar(self.code_frame, width=300, height=6)
|
||||
self.progress_bar.pack(pady=(0, 15))
|
||||
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())
|
||||
|
||||
# Copy button
|
||||
self.copy_btn = ctk.CTkButton(
|
||||
self, text=t("totp_copy"), width=200, height=40,
|
||||
@@ -205,12 +210,30 @@ class TOTPTab(ctk.CTkFrame):
|
||||
if code_text and code_text != "------" and code_text != "ERROR":
|
||||
self.clipboard_clear()
|
||||
self.clipboard_append(code_text)
|
||||
self._animate_copy()
|
||||
self.status_label.configure(text=t("totp_copied"), text_color="#22c55e")
|
||||
self.after(2000, lambda: self.status_label.configure(text=""))
|
||||
else:
|
||||
self.status_label.configure(text=t("totp_no_code"), text_color="#ef4444")
|
||||
self.after(2000, lambda: self.status_label.configure(text=""))
|
||||
|
||||
def _animate_copy(self):
|
||||
"""Flash the code frame and briefly show 'Copied' feedback."""
|
||||
# Save original state
|
||||
orig_fg = self.code_frame.cget("fg_color")
|
||||
orig_text = self.code_label.cget("text")
|
||||
orig_color = self.code_label.cget("text_color")
|
||||
|
||||
# Flash: green background + "Copied!" text
|
||||
self.code_frame.configure(fg_color="#164e36")
|
||||
self.code_label.configure(text="✓", text_color="#4ade80")
|
||||
|
||||
def restore():
|
||||
self.code_frame.configure(fg_color=orig_fg)
|
||||
self.code_label.configure(text=orig_text, text_color=orig_color)
|
||||
|
||||
self.after(400, restore)
|
||||
|
||||
def _toggle_secret(self):
|
||||
self._secret_visible = not self._secret_visible
|
||||
self.secret_entry.configure(show="" if self._secret_visible else "*")
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user