diff --git a/icloud_gui.py b/icloud_gui.py
index 6180281..f03c493 100644
--- a/icloud_gui.py
+++ b/icloud_gui.py
@@ -1150,27 +1150,41 @@ class AuthPage(Gtk.Box):
card.pack_start(self.status_label, False, False, 0)
self.pack_start(card, False, False, 0)
- # 2FA section (hidden until needed)
- self.tfa_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
- self.tfa_box.get_style_context().add_class("card")
- self.tfa_box.set_no_show_all(True)
+ # 2FA section — always visible so user can enter code any time
+ tfa_card = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
+ tfa_card.get_style_context().add_class("card")
+ tfa_card.set_margin_top(4)
tfa_lbl = Gtk.Label()
- tfa_lbl.set_markup("Two-Factor Code")
+ tfa_lbl.set_markup("Two-Factor Authentication")
tfa_lbl.set_halign(Gtk.Align.START)
+ tfa_sub = Gtk.Label(label="If Apple sent a code to your device, enter it here.")
+ tfa_sub.set_halign(Gtk.Align.START)
+
+ code_row = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
self.tfa_entry = Gtk.Entry()
- self.tfa_entry.set_placeholder_text("Enter 6-digit code from your device")
+ self.tfa_entry.set_placeholder_text("6-digit code")
self.tfa_entry.set_max_length(6)
self.tfa_entry.set_input_purpose(Gtk.InputPurpose.DIGITS)
+ self.tfa_entry.set_hexpand(True)
+ self.tfa_entry.connect("activate", self._on_tfa) # Enter key submits
+
btn_tfa = Gtk.Button(label="Verify Code")
btn_tfa.get_style_context().add_class("action-btn")
btn_tfa.get_style_context().add_class("btn-primary")
btn_tfa.connect("clicked", self._on_tfa)
- self.tfa_box.pack_start(tfa_lbl, False, False, 0)
- self.tfa_box.pack_start(self.tfa_entry, False, False, 0)
- self.tfa_box.pack_start(btn_tfa, False, False, 0)
- self.pack_start(self.tfa_box, False, False, 0)
+ code_row.pack_start(self.tfa_entry, True, True, 0)
+ code_row.pack_start(btn_tfa, False, False, 0)
+
+ self.tfa_status = Gtk.Label(label="")
+ self.tfa_status.set_halign(Gtk.Align.START)
+
+ tfa_card.pack_start(tfa_lbl, False, False, 0)
+ tfa_card.pack_start(tfa_sub, False, False, 0)
+ tfa_card.pack_start(code_row, False, False, 0)
+ tfa_card.pack_start(self.tfa_status, False, False, 0)
+ self.pack_start(tfa_card, False, False, 0)
def _on_auth(self, _):
args = ["auth"]
@@ -1186,21 +1200,23 @@ class AuthPage(Gtk.Box):
threading.Thread(target=_worker, daemon=True).start()
def _auth_result(self, rc, output):
- if "two-factor" in output.lower() or "verification" in output.lower():
+ if "two-factor" in output.lower() or "verification" in output.lower() or "2fa" in output.lower():
self.status_label.set_markup(
- '2FA required - enter code from your Apple device.'
+ 'A code was sent to your Apple device — enter it below.'
)
- self.tfa_box.show()
+ self.tfa_entry.grab_focus()
elif rc == 0:
self.status_label.set_markup('Authentication successful!')
else:
- msg = GLib.markup_escape_text(output[:200])
- self.status_label.set_markup(f'Error: {msg}')
+ msg = GLib.markup_escape_text(output[:300])
+ self.status_label.set_markup(f'{msg}')
def _on_tfa(self, _):
code = self.tfa_entry.get_text().strip()
- if not code:
+ if len(code) < 6:
+ self.tfa_status.set_markup('Please enter the full 6-digit code.')
return
+ self.tfa_status.set_markup('Verifying…')
def _worker():
rc, out, err = icloudctl("auth", input_data=code + "\n")
@@ -1208,15 +1224,12 @@ class AuthPage(Gtk.Box):
threading.Thread(target=_worker, daemon=True).start()
def _tfa_result(self, rc, output):
- if rc == 0:
- self.status_label.set_markup(
- 'Verification complete! You can now start the service.'
- )
- self.tfa_box.hide()
+ if rc == 0 or "authenticated" in output.lower() or "success" in output.lower():
+ self.tfa_status.set_markup('Verified! You can now start the service.')
+ self.tfa_entry.set_text("")
else:
- self.status_label.set_markup(
- 'Verification failed. Try again.'
- )
+ msg = GLib.markup_escape_text(output[:200]) if output.strip() else f"exit code {rc}"
+ self.tfa_status.set_markup(f'Failed: {msg}')
# ── Main window ────────────────────────────────────────────────────────────────