Commit Graph

5 Commits

Author SHA1 Message Date
c0mrade
a451a129fe fix(geocheck): убрать скачивание отчёта в Telegram Mini App
В webview Telegram атрибут `download` игнорируется: вместо сохранения файла
webview уходит на blob-ссылку и подменяет собой Mini App, вернуться можно
только кнопкой «Назад». То есть кнопка не просто не работала, а выкидывала
администратора из приложения.

Штатный путь тут не подходит. `downloadFile` из Bot API 8.0 требует HTTPS-URL
файла с заголовками `Content-Disposition: attachment` и CORS для
web.telegram.org, а отчёт приходит base64 внутри JSON-ответа бота — ссылки на
него не существует. Отдать её можно только новым эндпоинтом бота, причём
подписанным: `downloadFile` скачивает URL сам, без заголовка Authorization.
Это отдельная работа, а не правка кнопки.

Пока кнопка скрыта в Mini App тем же признаком платформы, что и полный экран.
Данные из отчёта там по-прежнему достаются копированием JSON, а на десктопе
скачивание работает как раньше.

Проверено рендером обеих платформ: в Telegram тулбар — отчёт, JSON,
копирование, перезапуск, зум; в вебе к ним добавляются полный экран и
скачивание.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 18:11:58 +03:00
c0mrade
5c3031f5f5 fix(geocheck): скелетон до отрисовки отчёта и сброс зума на новом отчёте
Отчёт весит сотни килобайт вместе со встроенным шрифтом, поэтому между
приходом данных и первой отрисовкой есть заметная пауза. Всё это время на
экране была пустая тёмная коробка, зато с готовыми кнопками зума, которым
нечего масштабировать. Теперь до отрисовки показывается скелетон, повторяющий
ритм отчёта, а панель зума появляется вместе с картинкой.

Перезапуск проверки наследовал зум и сдвиг от предыдущего отчёта. Новый отчёт
должен открываться в исходном масштабе, поэтому его подпись входит в ключ
просмотрщика.

Подпись — хеш всей строки, посчитанный один раз на отчёт. Первая попытка
брала длину и хвост base64, и этого оказалось мало: отчёты одного узла
кончаются одинаково, подписи совпадали, зум не сбрасывался. Поймано
проверкой, а не рассуждением.

Готовность хранится как «какая картинка отрисована», а не булевым флагом:
тогда новый отчёт автоматически считается незагруженным и сбрасывающий
эффект не нужен.

Проверено в браузере: при задержке картинки — скелетон есть, панели зума нет;
после загрузки наоборот. Зум со сдвигом после перезапуска возвращается к
исходному преобразованию, дважды подряд.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 17:58:54 +03:00
c0mrade
5db1ffccf6 fix(geocheck): убрать полноэкранный режим в Telegram Mini App
В Mini App окно Telegram и так занимает экран целиком, поэтому режим ничего
не давал: он лишь снимал отступы модалки и лез под шапку и home indicator.
Кнопка полезна на десктопе, где отчёт показывается в центрированном окне.

Модалка определяет платформу через готовый useIsTelegram и передаёт отчёту
canFullscreen; при выключенном флаге кнопка не рендерится, а запрошенный
режим не применяется, даже если состояние осталось от прошлого открытия.

Проверено рендером на обеих платформах в одном дереве: telegram —
canFullscreen=false и 8 кнопок в тулбаре, web — true и 9. Разница ровно в
одной кнопке.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 17:33:56 +03:00
c0mrade
debe26ae35 fix(geocheck): сквозные клики через портал и safe-зоны в полноэкранном режиме
Три поломки, замеченные на dev.

Клики внутри модалки срабатывали и на том, что под ней. Модалка рендерилась
внутри `<div onClick>` карточки ноды: портал уносит её в document.body только
по DOM, а события React прогоняет по дереву компонентов, поэтому каждый клик
всплывал в обработчик аккордеона. Теперь модалка — сосед кликабельного блока,
а не его потомок. Проверено A/B на настоящей модалке: в старой структуре клик
по вкладке внутри модалки поднимал счётчик карточки до 1, в новой остаётся 0.
По существу правка в 6 строк, остальное в дифе — переотступы от обёртки.

В полноэкранном режиме отступы обнулялись целиком, и в Mini App панель
инструментов уезжала под шапку Telegram, а кнопки зума — под home indicator.
Теперь safe-зоны соблюдаются и в полноэкранном режиме, просто без лишнего
сантиметра. Замер при отступах 96/34 на экране 844: диалог занимает 96..810,
низ зум-бара на 784 — оба внутри безопасной зоны, было наоборот.

Высота диалога считалась от `100dvh` мимо safe-зон, из-за чего он мог вылезти
за них даже в обычном режиме. Заменено на `max-h-full`: отступы контейнера
уже урезали доступное место.

Заодно в полноэкранном режиме шапка ужата в одну строку с именем ноды —
вертикальное место ровно то, ради чего его включают.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 17:23:30 +03:00
c0mrade
b4e1de6152 feat(remnawave): GeoCheck ноды в админке — запуск проверки и просмотр отчёта
Кнопка в карточке ноды открывает модалку: выбор маршрута (по умолчанию /
IP-адрес / интерфейс) с подсказками из данных ноды, ожидание, затем отчёт
картинкой либо тем же отчётом в JSON. Есть копирование JSON, скачивание
SVG, повтор проверки и полноэкранный режим.

Кнопка показывается только для узлов 3.3.0+ (versions.node) и только для
подключённых — иначе админ упирался бы в ошибку панели.

Отчёт вставляется как <img src="data:...">, а не сырым SVG в разметку: он
несёт встроенный моноширинный шрифт и <style>, на которых держится
выравнивание колонок, и санитайзер их выбрасывает. В <img> SVG рисуется в
изолированном контексте без скриптов и внешних запросов — и безопаснее, и
вернее по виду.

Зум и панорамирование — react-zoom-pan-pinch с той же конфигурацией, что в
самой панели Remnawave. Своя реализация обязательна: index.html задаёт
user-scalable=no, поэтому браузерного пинча нет ни в мобильном вебе, ни в
Mini App. Колесо намеренно не масштабирует, иначе прокрутка над отчётом
превращается в зум.

В отличие от панели стартовый масштаб считается от читаемой ширины: на
телефоне «вписано по ширине» превращает отчёт в серую рябь. На 390px это
2.42x с панорамированием, на десктопе — 1x. При смене ширины (полный
экран, поворот) масштаб пересчитывается.

Опрос задачи с потолком в три минуты — иначе забытая открытой модалка
опрашивала бы панель бесконечно. Пока проверка идёт, модалка не
закрывается: задача уже поставлена, терять её результат молча хуже.

Заодно в AdminRemnawave.tsx осели автоправки biome (import type,
Math.pow -> **) — файл всё равно правился, они механические.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 16:01:05 +03:00