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 ────────────────────────────────────────────────────────────────