vpn/app/screens/white_lists.py
2026-09-23 01:19:36 +00:00

155 lines
6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import flet as ft
import flet_webview as fwv
from app.models import FreeTurnProfile
from app.screens.components import connection_card, section_title
from app.services.controller import RuntimeController
from app.services.settings_registry import SettingsRegistry
from app.theme import card
PRESET_TEXT = {
1: "4/4 · для сообщений",
2: "8/4 · для простого интернет-сёрфинга",
3: "12/6 · для видео в невысоком качестве",
4: "24/6 · для всего · ультра скорость, повышенная нагрузка",
}
CAPTCHA_ENTRY_URL = "https://vk.com"
def build_white_lists_screen(
page: ft.Page,
controller: RuntimeController,
registry: SettingsRegistry,
on_theme: callable,
) -> ft.Control:
content = ft.Column(expand=True, scroll=ft.ScrollMode.AUTO, spacing=14)
async def slide(event: ft.ControlEvent) -> None:
if float(event.control.value or 0) < 0.8:
return
try:
controller.select_freeturn()
await controller.connect()
except Exception as exc:
controller.snapshot = controller.snapshot.model_copy(
update={"state": "error", "message": controller.error_text(exc)}
)
render()
async def stop(_: ft.ControlEvent) -> None:
await controller.stop()
render()
def preset_change(event: ft.ControlEvent) -> None:
controller.freeturn.preset = int(round(float(event.control.value)))
render()
def stability_change(event: ft.ControlEvent) -> None:
controller.freeturn.stability_over_load = bool(event.control.value)
render()
def captcha_settings() -> ft.Control:
captcha_url = controller.snapshot.captcha_url or CAPTCHA_ENTRY_URL
def open_captcha(_: ft.ControlEvent, in_browser: bool = False) -> None:
if in_browser or controller.freeturn.captcha_always_browser:
page.launch_url(captcha_url)
return
dialog = ft.AlertDialog(
modal=True,
title=ft.Text("CAPTCHA"),
content=ft.Container(
fwv.WebView(url=captcha_url, expand=True),
width=520,
height=620,
),
actions=[
ft.TextButton(
"Открыть в браузере",
on_click=lambda _: page.launch_url(captcha_url),
),
ft.TextButton("Закрыть", on_click=lambda _: page.close(dialog)),
],
)
page.open(dialog)
return card(
ft.Column(
[
ft.Text("CAPTCHA", weight=ft.FontWeight.W_600),
ft.Text(
"Встроенное окно доступно на Android. На desktop используйте браузер.",
color=ft.Colors.OUTLINE,
),
ft.Switch(
label="Всегда открывать CAPTCHA в браузере",
value=controller.freeturn.captcha_always_browser,
on_change=lambda e: setattr(
controller.freeturn, "captcha_always_browser", bool(e.control.value)
),
),
ft.Row(
[
ft.FilledButton(
"Открыть внутри приложения",
on_click=open_captcha,
),
ft.OutlinedButton(
"Открыть в браузере",
on_click=lambda e: open_captcha(e, True),
),
]
),
],
spacing=8,
)
)
def render() -> None:
profile: FreeTurnProfile = controller.freeturn
threads, per_credential = profile.stream_settings
content.controls = [
section_title("Белые списки", "FreeTurn · отдельный runtime"),
connection_card(controller.snapshot.state, controller.mode, "FreeTurn", slide),
card(
ft.Column(
[
ft.Text("Скорость", weight=ft.FontWeight.W_600),
ft.Text(
PRESET_TEXT[profile.preset],
color=ft.Colors.ERROR if profile.preset == 4 else None,
),
ft.Slider(
min=1,
max=4,
divisions=3,
value=profile.preset,
label="Уровень {value}",
on_change=preset_change,
),
ft.Text(f"Потоки: {threads}/{per_credential}", color=ft.Colors.OUTLINE),
ft.Switch(
label="Повысить стабильность ценой нагрузки",
value=profile.stability_over_load,
disabled=profile.preset < 3,
on_change=stability_change,
),
],
spacing=8,
)
),
captcha_settings(),
ft.OutlinedButton("Остановить", icon=ft.Icons.STOP, on_click=stop),
ft.Text(
controller.snapshot.message or "",
color=ft.Colors.ERROR if controller.snapshot.message else None,
),
]
page.update()
registry.register("white-lists", "Белые списки", lambda: content)
controller.add_listener(render)
render()
return content