from __future__ import annotations import subprocess from PySide6.QtCore import QTimer from PySide6.QtWidgets import QApplication, QMessageBox class RuntimeAuthMixin: def on_auth_button(self) -> None: def work(): view = self.ctrl.get_login_view() if view.logged_in: self.on_logout() else: # при логине всегда переходим на вкладку AdGuardVPN и # показываем страницу логина self.tabs.setCurrentWidget(self.tab_vpn) self._show_vpn_page("login") self.on_start_login() self._safe(work, title="Auth error") def on_login_banner_clicked(self) -> None: def work(): txt = self.ctrl.login_banner_cli_text() QMessageBox.information(self, "AdGuard VPN", txt) self._safe(work, title="Login banner error") # ---------------- LOGIN FLOW ACTIONS ---------------- def on_start_login(self) -> None: def work(): self.ctrl.log_gui("Top Login clicked") self._show_vpn_page("login") self._login_flow_reset_ui() start = self.ctrl.login_flow_start() self._login_cursor = int(start.cursor) self.lbl_login_flow_status.setText( f"Status: {start.status_text or '—'}" ) self.lbl_login_flow_email.setText( f"User: {start.email}" if start.email else "" ) self.edit_login_url.setText(start.url or "") self._login_flow_set_buttons( can_open=start.can_open, can_check=start.can_check, can_cancel=start.can_cancel, ) if start.lines: cleaned = self._clean_ui_lines(start.lines) if cleaned: self._append_text(self.txt_login_flow, cleaned + "\n") if not start.alive: self._login_flow_autopoll_stop() self._login_flow_set_buttons( can_open=False, can_check=False, can_cancel=False ) self.btn_login_stop.setEnabled(False) QTimer.singleShot(250, self.refresh_login_banner) return self._login_flow_autopoll_start() self._safe(work, title="Login start error") def _login_flow_reset_ui(self) -> None: self._login_cursor = 0 self._login_url_opened = False self.edit_login_url.setText("") self.lbl_login_flow_status.setText("Status: —") self.lbl_login_flow_email.setText("") self._set_text(self.txt_login_flow, "") def _login_flow_set_buttons( self, *, can_open: bool, can_check: bool, can_cancel: bool, ) -> None: self.btn_login_open.setEnabled(bool(can_open)) self.btn_login_copy.setEnabled(bool(self.edit_login_url.text().strip())) self.btn_login_check.setEnabled(bool(can_check)) self.btn_login_close.setEnabled(bool(can_cancel)) self.btn_login_stop.setEnabled(True) def _login_flow_autopoll_start(self) -> None: self._login_flow_active = True if not self.login_poll_timer.isActive(): self.login_poll_timer.start() def _login_flow_autopoll_stop(self) -> None: self._login_flow_active = False if self.login_poll_timer.isActive(): self.login_poll_timer.stop() def _login_poll_tick(self) -> None: if not self._login_flow_active: return def work(): view = self.ctrl.login_flow_poll(self._login_cursor) self._login_cursor = int(view.cursor) self.lbl_login_flow_status.setText( f"Status: {view.status_text or '—'}" ) self.lbl_login_flow_email.setText( f"User: {view.email}" if view.email else "" ) if view.url: self.edit_login_url.setText(view.url) self._login_flow_set_buttons( can_open=view.can_open, can_check=view.can_check, can_cancel=view.can_cancel, ) cleaned = self._clean_ui_lines(view.lines) if cleaned: self._append_text(self.txt_login_flow, cleaned + "\n") if (not self._login_url_opened) and view.url: self._login_url_opened = True try: subprocess.Popen(["xdg-open", view.url]) except Exception: pass phase = (view.phase or "").strip().lower() if (not view.alive) or phase in ( "success", "failed", "cancelled", "already_logged", ): self._login_flow_autopoll_stop() self._login_flow_set_buttons( can_open=False, can_check=False, can_cancel=False ) self.btn_login_stop.setEnabled(False) QTimer.singleShot(250, self.refresh_login_banner) self._safe(work, title="Login flow error") def on_login_copy(self) -> None: def work(): u = self.edit_login_url.text().strip() if u: QApplication.clipboard().setText(u) self.ctrl.log_gui("Login flow: copy-url") self._safe(work, title="Login copy error") def on_login_open(self) -> None: def work(): u = self.edit_login_url.text().strip() if u: try: subprocess.Popen(["xdg-open", u]) except Exception: pass self.ctrl.log_gui("Login flow: open") self._safe(work, title="Login open error") def on_login_check(self) -> None: def work(): # если ещё ничего не запущено — считаем это стартом логина if ( not self._login_flow_active and self._login_cursor == 0 and not self.edit_login_url.text().strip() and not self.txt_login_flow.toPlainText().strip() ): self.on_start_login() return self.ctrl.login_flow_action("check") self.ctrl.log_gui("Login flow: check") self._safe(work, title="Login check error") def on_login_cancel(self) -> None: def work(): self.ctrl.login_flow_action("cancel") self.ctrl.log_gui("Login flow: cancel") self._safe(work, title="Login cancel error") def on_login_stop(self) -> None: def work(): self.ctrl.login_flow_stop() self.ctrl.log_gui("Login flow: stop") self._login_flow_autopoll_stop() QTimer.singleShot(250, self.refresh_login_banner) self._safe(work, title="Login stop error") def on_logout(self) -> None: def work(): self.ctrl.log_gui("Top Logout clicked") res = self.ctrl.vpn_logout() self._set_text(self.txt_vpn, res.pretty_text or str(res)) QTimer.singleShot(250, self.refresh_login_banner) self._safe(work, title="Logout error")