feat(tray): добавлен статус прокси в GUI и обновлены настройки

This commit is contained in:
deexsed 2026-03-27 14:08:51 +03:00
parent bd5056a64c
commit a11b634ba7
7 changed files with 84 additions and 17 deletions

View File

@ -39,13 +39,20 @@ Telegram Desktop → SOCKS5 (127.0.0.1:1080) → TG WS Proxy → WSS → Telegra
**Меню трея:**
- **Открыть в Telegram** — автоматически настроить прокси через `tg://socks` ссылку
- **Статус и проверка TCP…** — диалог с фазой прокси (запуск / слушает / ошибка), uptime и локальной проверкой TCP до `host:port`
- **Перезапустить прокси** — перезапуск без выхода из приложения
- **Настройки...** — GUI-редактор конфигурации (в т.ч. версия приложения, опциональная проверка обновлений с GitHub)
- **Настройки...** — GUI-редактор конфигурации (см. ниже)
- **Открыть логи** — открыть файл логов
- **Выход** — остановить прокси и закрыть приложение
**Иконка в трее:** цветной индикатор на иконке — **зелёный** прокси слушает порт, **красный** — ошибка, **жёлтый** — запуск / остановка / ожидание. Подсказка при наведении: адрес, состояние и при работе — uptime.
Повторный запуск приложения, пока оно уже работает, блокируется (один экземпляр); при конфликте порта показывается сообщение об ошибке.
При первом запуске после старта может появиться запрос об открытии страницы релиза, если на GitHub вышла новая версия (отключается в настройках).
**Окно настроек (Windows / Linux):** секция **«Статус»** — цветной индикатор, текст состояния и uptime (обновляется автоматически). Полная проверка TCP и детали — в меню трея **«Статус и проверка TCP…»**. В блоке **«Обновления»** — время последней проверки GitHub; без интернета имеет смысл отключить **«Проверять обновления при запуске»**.
### macOS
Перейдите на [страницу релизов](https://github.com/Flowseal/tg-ws-proxy/releases) и скачайте **`TgWsProxy_macos_universal.dmg`** — универсальная сборка для Apple Silicon и Intel.
@ -54,6 +61,8 @@ Telegram Desktop → SOCKS5 (127.0.0.1:1080) → TG WS Proxy → WSS → Telegra
2. Перенести **TG WS Proxy.app** в папку **Applications**
3. При первом запуске macOS может попросить подтвердить открытие: **Системные настройки → Конфиденциальность и безопасность → Всё равно открыть**
В строке меню доступны те же действия, что и в трее Windows/Linux (в т.ч. статус и проверка TCP); иконка в меню обновляется с цветным индикатором состояния. Настройки на macOS задаются через системные диалоги, не через окно CustomTkinter.
### Linux
Для Debian/Ubuntu скачайте со [страницы релизов](https://github.com/Flowseal/tg-ws-proxy/releases) пакет **`TgWsProxy_linux_amd64.deb`**.
@ -158,7 +167,7 @@ tg-ws-proxy-tray-linux = "linux:main"
## Структура исходников (tray)
Общая логика tray-приложений (пути данных, один экземпляр процесса, конфиг, логирование, поток с прокси, IPv6, фоновая проверка релизов) находится в `utils/tray_*.py`; вспомогательные части UI — в `ui/tray_*.py`. Точки входа по ОС: `windows.py`, `linux.py`, `macos.py`.
Общая логика tray-приложений (пути данных, один экземпляр процесса, конфиг, логирование, поток с прокси, состояние для UI, локальная диагностика порта/TCP, IPv6, фоновая проверка релизов) находится в `utils/tray_*.py`; вспомогательные части UI — в `ui/tray_*.py` и `ui/ctk_tray_ui.py`. Точки входа по ОС: `windows.py`, `linux.py`, `macos.py`.
Для согласованных окончаний строк в репозитории используются `.editorconfig` и `.gitattributes` (LF).

View File

@ -275,6 +275,7 @@ def _edit_config_dialog():
cfg,
DEFAULT_CONFIG,
show_autostart=False,
proxy_state=_proxy_state,
)
def on_save():

View File

@ -50,6 +50,8 @@ class CtkTheme:
field_border: str = "#d6d9dc"
text_primary: str = "#000000"
text_secondary: str = "#707579"
status_pill_bg: str = "#f4f6fa"
status_pill_border: str = "#e2e6ed"
ui_font_family: str = "Sans"
mono_font_family: str = "Monospace"

View File

@ -12,6 +12,8 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
import proxy.tg_ws_proxy as tg_ws_proxy
from proxy import __version__
from ui.tray_icons import badge_rgb_for_phase
from utils.tray_proxy_state import format_uptime_short, phase_label_ru
from utils.update_check import RELEASES_PAGE_URL, get_status
from ui.ctk_theme import (
@ -138,6 +140,7 @@ def install_tray_config_form(
*,
show_autostart: bool = False,
autostart_value: bool = False,
proxy_state: Optional[Any] = None,
) -> TrayConfigFormWidgets:
"""Поля настроек прокси внутри уже созданного `frame`."""
header = ctk.CTkFrame(frame, fg_color="transparent")
@ -216,6 +219,67 @@ def install_tray_config_form(
port_entry.pack(anchor="w")
attach_tooltip_to_widgets([port_lbl, port_entry, port_col], _TIP_PORT)
if proxy_state is not None:
stat_inner = _config_section(ctk, frame, theme, "Статус")
pill = ctk.CTkFrame(
stat_inner,
fg_color=theme.status_pill_bg,
corner_radius=12,
border_width=1,
border_color=theme.status_pill_border,
)
pill.pack(fill="x", pady=(2, 0))
row = ctk.CTkFrame(pill, fg_color="transparent")
row.pack(fill="x", padx=14, pady=12)
dot = ctk.CTkFrame(
row,
width=12,
height=12,
corner_radius=6,
fg_color="#eab308",
)
dot.pack(side="left", padx=(0, 12))
dot.pack_propagate(False)
text_col = ctk.CTkFrame(row, fg_color="transparent")
text_col.pack(side="left", fill="x", expand=True)
status_main = ctk.CTkLabel(
text_col,
text="",
font=(theme.ui_font_family, 14),
text_color=theme.text_primary,
anchor="w",
)
status_main.pack(side="left")
status_uptime = ctk.CTkLabel(
text_col,
text="",
font=(theme.ui_font_family, 13),
text_color=theme.text_secondary,
anchor="w",
)
status_uptime.pack(side="left")
def _mini_status_tick() -> None:
if not frame.winfo_exists():
return
try:
snap = proxy_state.snapshot()
phase = snap["phase"]
r, g, b = badge_rgb_for_phase(phase)
dot.configure(fg_color=f"#{r:02x}{g:02x}{b:02x}")
status_main.configure(text=phase_label_ru(phase))
ls = snap.get("listening_since")
if phase == "listening" and ls is not None:
status_uptime.configure(text=f" · {format_uptime_short(ls)}")
else:
status_uptime.configure(text="")
except Exception:
pass
if frame.winfo_exists():
frame.after(1000, _mini_status_tick)
_mini_status_tick()
dc_inner = _config_section(ctk, frame, theme, "Датацентры Telegram (DC → IP)")
dc_lbl = ctk.CTkLabel(
dc_inner,
@ -591,7 +655,7 @@ def populate_first_run_window(
"порт занят — другой процесс или старый экземпляр; смените порт в настройках;",
"IPv6 — трафик может идти мимо прокси; см. предупреждение при первом запуске;",
"брандмауэр / антивирус — разрешите локальное прослушивание;",
"меню трея: «Статус» — без поиска по логам.",
"меню трея: «Статус и проверка TCP…» — без поиска по логам.",
):
ctk.CTkLabel(
frame,

View File

@ -6,12 +6,6 @@ from typing import Any, List, Tuple
from PIL import Image, ImageDraw, ImageFont
# Подсказка для tooltip (согласована с цветами бейджа)
BADGE_TOOLTIP_HINT = (
"Бейдж: зелёный — работает, красный — ошибка, жёлтый — запуск/ожидание/остановка"
)
def _resample_lanczos() -> int:
try:
return Image.Resampling.LANCZOS # type: ignore[attr-defined]

View File

@ -90,8 +90,6 @@ def build_tray_tooltip(
port: int,
state: ProxyRuntimeState,
) -> str:
from ui.tray_icons import BADGE_TOOLTIP_HINT
snap = state.snapshot()
phase = snap["phase"]
addr = f"{host}:{port}"
@ -99,12 +97,10 @@ def build_tray_tooltip(
if phase == "listening" and snap["listening_since"] is not None:
up = format_uptime_short(snap["listening_since"])
base = f"TG WS Proxy | {addr} | {label} | {up}"
elif phase == "error" and snap["detail"]:
return f"TG WS Proxy | {addr} | {label} | {up}"
if phase == "error" and snap["detail"]:
short = snap["detail"]
if len(short) > 80:
short = short[:77] + ""
base = f"TG WS Proxy | {addr} | {label}: {short}"
else:
base = f"TG WS Proxy | {addr} | {label}"
return f"{base}\n{BADGE_TOOLTIP_HINT}"
return f"TG WS Proxy | {addr} | {label}: {short}"
return f"TG WS Proxy | {addr} | {label}"

View File

@ -394,6 +394,7 @@ def _edit_config_dialog():
DEFAULT_CONFIG,
show_autostart=_supports_autostart(),
autostart_value=cfg.get("autostart", False),
proxy_state=_proxy_state,
)
def on_save():