zapret-kvn/xray_fluent/application/selection_source.py
loop-uh 9edbcf4c6b
Some checks failed
Windows project source guards / test (push) Failing after 32s
Смена сервера всегда называет источник: [select] в логе, «Следующий» без фокуса
Инцидент 28.09.2026: сервер сменился Tiraru → Titiru (мёртвый Hysteria), а в
логе был только [core-switch] без причины — явное действие (кнопка
«Следующий», трей, таблица) было неотличимо от сбоя программы.

- SelectionSource (application/selection_source.py): кто сменил сервер и
  ручной ли это выбор. set_selected_node/switch_next_node принимают
  обязательный source= вместо reset_auto_switch; ручной источник сбрасывает
  учёт авто-переключения, автоматика (auto/smart/rotation) — нет.
- Каждая смена пишет одну строку
  [select] source=<код> (<описание>): «было» node_ref=… → «стало» node_ref=…
  node_ref совпадает с [runtime-map] и строками ядер. Покрыты и неявные
  смены: импорт, удаление, скрытие, подписка, восстановление Hysteria.
- UI передаёт жест: двойной клик/Enter/меню таблицы, трей, главная;
  сигнал NodesPage.selected_node_changed → connect_node_requested(id, source).
- Кнопка «Следующий» на главной не берёт фокус клавиатуры: пробел/Enter
  «мимо» больше не меняют сервер.
- tests/test_selection_source.py: AST-инвариант — каждый вызов команды смены
  передаёт source=, а .selected_node_id присваивают только функции из
  белого списка, которые пишут [select]. switch_prev_node (мёртвый) удалён.
2026-09-28 21:35:12 +03:00

44 lines
2.7 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.

"""Источник смены выбранного сервера.
Каждая смена ``state.selected_node_id`` называет свой источник и пишет в лог
одну строку ``[select] source=…``. Без этого явное действие пользователя
(кнопка «Следующий», трей, таблица) в диагностике неотличимо от сбоя
программы: инцидент 28.09.2026 — в логе был только ``[core-switch]`` без
причины.
Модуль-лист без импортов проекта: его импортируют и application-, и UI-слой.
"""
from __future__ import annotations
from enum import Enum
class SelectionSource(Enum):
"""Кто сменил выбранный сервер.
``manual`` — выбор сделал пользователь: он сбрасывает учёт анти-дребезга
авто-переключения и фиксирует сервер (manual hold). Автоматические
источники этот учёт не трогают.
"""
# Явные действия пользователя.
DASHBOARD_NEXT = ("dashboard-next", "кнопка «Следующий» на главной", True)
TRAY_NEXT = ("tray-next", "трей → «Следующий сервер»", True)
NODES_DOUBLE_CLICK = ("nodes-double-click", "двойной клик в таблице серверов", True)
NODES_ENTER = ("nodes-enter", "Enter в таблице серверов", True)
NODES_MENU = ("nodes-menu", "меню таблицы серверов → «Подключить»", True)
NODES_IMPORTED = ("nodes-imported", "импорт серверов: выбран первый новый", True)
# Автоматика.
AUTO_SWITCH = ("auto-switch", "авто-переключение: сервер недоступен", False)
SMART_SWITCH = ("smart-switch", "умная проверка: сервер медленный", False)
ROTATION = ("rotation", "ротация серверов", False)
HYSTERIA_RECOVERY = ("hysteria-recovery", "отказ Hysteria: резервный сервер", False)
# Выбранный сервер исчез из списка — выбран первый оставшийся.
NODE_REMOVED = ("node-removed", "выбранный сервер удалён", False)
SUBSCRIPTION = ("subscription", "подписка: выбранного сервера больше нет", False)
def __init__(self, code: str, label: str, manual: bool) -> None:
self.code = code
self.label = label
self.manual = manual