Repository navigation
Beta v1.8.4 Release
✨ НОВОЕ
Чат поддержки
- Чат с техподдержкой - новый экран, доступный из drawer. Единый для обоих сервисов, URL из .env (CHAT_API_URL).
- Cookie-сессия чата сохраняется в SharedPreferences и подхватывается между запусками приложения.
- Автополлинг новых сообщений каждые N секунд (интервал задаёт бэкенд).
- Оптимистичная отправка - сообщение сразу появляется в списке, потом уходит на сервер.
- Дедупликация сообщений при poll - серверные и локальные не дублируются.
- Кнопка «Поделиться логами» показывается под сообщением агента, содержащим триггерное слово. По нажатию логи тихо уходят в чат, а в UI появляется локальное сообщение «Отправлены логи ошибок приложения».
- Тихая отправка логов из настроек - кнопка «Отправить логи в поддержку» с описанием «Это поможет нам исправить ошибки». Пользователь видит только «Спасибо! Логи отправлены».
Логирование
- Три режима логирования с понятными названиями:
- Отключено - пишется только errors.log (последние 100 строк ошибок).
- Логи Xray - логи Xray и flutter_vless + errors.log.
- Полные логи - все критичные логи приложения + errors.log.
- errors.log пишется всегда, независимо от режима. Это кольцевой буфер на 100 строк с автоперезаписью.
- Ротация session-файлов - хранятся последние 3 файла сессий. Старые удаляются автоматически.
- Фильтр шума - из Полных логов вырезаны:
[AppConfig] dump всех цветов при старте,
[ChatService] GET/POST ...,
[UpdateService] CACHE HIT ...,
[Bedolaga] retry N/M через ...,
[MinionGuard] retry N/M через ...,
[Bedolaga] baseUrl=....
При этом всё, что содержит error/exception/failed/timeout/refused и т.п., проходит фильтр всегда. - Перехватчики ошибок Flutter перенесены в LogService.installErrorHandlers() - FlutterError.onError, PlatformDispatcher.onError, runZonedGuarded.
- Просмотр логов в приложении - LogViewerScreen с кнопками «Назад» и «Поделиться» (share_plus на Android/iOS/Windows/macOS).
- Файл errors.log в списке логов помечен отдельной иконкой и всегда показан первым.
Раздельное туннелирование
- Windows - полный набор: global, include (только выбранные), exclude (все, кроме выбранных), bypass local networks.
- Android - global, exclude (per-app VPN через blockedApps), bypass local networks.
- iOS/macOS/Linux - секция скрыта полностью.
Общее
- Оптимизация AppListService на Windows - PowerShell OutputEncoding принудительно UTF-8, чтобы русские буквы в путях не превращались в кракозябры.
- Детеминированный HWID - на Windows берётся MachineGuid из реестра, на Linux - /etc/machine-id, на macOS - IOPlatformUUID. Одно устройство = один HWID.
- Сохранение выбранного сервера между запусками - SessionService.selectedServerFor() хранит remark, при загрузке выбирается тот же сервер.
- Автосохранение настроек туннеля - без кнопки «Сохранить», каждое изменение сразу пишется в SharedPreferences.
- Drawer закрывается через 1 секунду при навигации и переключении сервиса (не только при смене сервиса).
- Кнопки и рамки сервисов используют цвета из .env во всех экранах (главная, тарифы, настройки, чат, drawer).
🐛 БАГ-ФИКСЫ
VPN / туннелирование
- Исправлен refresh-токен ExoWPN. Замыкание send в BedolagaApiClient._request() захватывало HTTP-заголовки один раз при создании, поэтому повторный запрос после refresh уходил со старым Bearer. Теперь send принимает headers параметром и пересобирает их на каждом вызове.
- Устранена гонка refresh-токена. Добавлен мьютекс _refreshFuture - параллельные 401 ждут один refresh вместо двух одновременных вызовов /cabinet/auth/refresh (бэкенд инвалидирует refresh после первого использования, второй запрос ронял сессию).
- Плашка «Сессия истекла» больше не появляется ложно. Причина - гонка refresh между getProfile() и getSubscription() на главном экране. Мьютекс устраняет сценарий, когда второй запрос получает 401 из-за израсходованного refresh.
- TUN-режим теперь работает на macOS через flutter_vless. Раньше usesNativeTun возвращал true только для Windows, а isMobile не включал macOS - на macOS TUN падал в proxy. Теперь usesFlutterVlessTun покрывает Android/iOS/macOS.
- Переключение сервера корректно работает для flutter_vless-платформ. Учтён случай, когда активен TUN через flutter_vless (не только Windows-нативный).
Чат поддержки
- Исправлено отображение ответов поддержки. Регулярка/логика нормализации автора не распознавала support/operator/manager/admin → они попадали в visitor и отображались справа как твои. Теперь ChatMessage._normalizeAuthor() приводит все варианты к agent/visitor/system.
- Появилось первое сообщение в чате. Если бэкенд не вернул сообщений, но прислал greeting - он показывается как системное сообщение. Если и greeting пуст - используется дефолтное приветствие (ChatService.defaultGreeting).
- Исправлен триггер кнопки «Поделиться логами». \b в Dart с unicode: true не работает с кириллицей. Заменено на (?<!\p{L})...(?!\p{L}) - теперь «логи», «логов», «LOGS», «log» ловятся, а «логирование» и «каталог» - нет.
- Автоконтекст в первом сообщении. При первом send() в чат добавляется шапка с сервисом, username, email, платформой и версией приложения.
Логирование
- Исправлено чтение hex-цветов из .env. flutter_dotenv обрезает значение по #, если оно не в кавычках. Теперь _parseColor() корректно обрабатывает #RRGGBB / RRGGBB / #RGB / inline-комментарии. В .env цвета рекомендуется оборачивать в кавычки.
UI / темы
- Убраны баннеры о недоступных функциях. На iOS/Linux/macOS больше не показывается «Раздельное туннелирование недоступно» и «На этой платформе доступен только TUN». Недоступные секции просто скрыты через TunnelCapabilities.showXxx.
- Раздел маршрутизации скрывается целиком там, где он не работает (iOS/Linux/macOS), а не отображается серым.
- Выбор режима подключения скрыт на Linux - там всегда proxy.
🔧 ИЗМЕНЕНИЯ
Архитектура
- LogService расширен - теперь единственный источник правды по логам, включая errors.log и перехватчики ошибок Flutter.
- Удалён lib/services/error_log_service.dart - вся его логика перенесена в LogService.
- VpnController - добавлены геттеры usesFlutterVlessTun, usesFlutterVless, расширен isMobile (включая macOS), переписан startTun() с разветвлением Windows / flutter_vless / Linux.
- BedolagaApiClient - _sendWithRetry и _request принимают функцию от headers вместо готового замыкания. Все публичные методы переписаны под новый контракт.
- TunnelCapabilities - новые геттеры showConnectionModeSelector, showRoutingSection, showBypassLocalNetworks для декларативной видимости секций.
UI
- TunnelSettingsScreen - режим логирования теперь DropdownButtonFormField (компактнее, чем RadioListTile).
- ChatScreen - разделение на _bootstrap (загрузка + приветствие), _poll (дедупликация), _send (оптимистичная вставка), _shareErrorLogs.
- LogViewerScreen - новый экран для просмотра одного лог-файла.