platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
209
selective-vpn-gui/main_window/runtime_auth_mixin.py
Normal file
209
selective-vpn-gui/main_window/runtime_auth_mixin.py
Normal file
@@ -0,0 +1,209 @@
|
||||
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")
|
||||
Reference in New Issue
Block a user