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>
This commit is contained in:
c0mrade
2026-08-19 18:11:58 +03:00
parent 5c3031f5f5
commit a451a129fe
2 changed files with 27 additions and 11 deletions

View File

@@ -32,7 +32,11 @@ export function GeoCheckModal({ node, onClose }: GeoCheckModalProps) {
// В Mini App окно Telegram и так занимает экран целиком: отдельный // В Mini App окно Telegram и так занимает экран целиком: отдельный
// полноэкранный режим там только снимал отступы и залезал под хром. // полноэкранный режим там только снимал отступы и залезал под хром.
const canFullscreen = !useIsTelegram(); // Тот же признак закрывает и скачивание: в webview Telegram оно уводит
// из приложения вместо сохранения файла.
const isTelegram = useIsTelegram();
const canFullscreen = !isTelegram;
const canDownload = !isTelegram;
const fullscreen = canFullscreen && fullscreenRequested; const fullscreen = canFullscreen && fullscreenRequested;
const job = useGeoCheckJob(node.uuid); const job = useGeoCheckJob(node.uuid);
@@ -218,6 +222,7 @@ export function GeoCheckModal({ node, onClose }: GeoCheckModalProps) {
nodeName={node.name} nodeName={node.name}
fullscreen={fullscreen} fullscreen={fullscreen}
canFullscreen={canFullscreen} canFullscreen={canFullscreen}
canDownload={canDownload}
onToggleFullscreen={() => setFullscreenRequested((v) => !v)} onToggleFullscreen={() => setFullscreenRequested((v) => !v)}
onRerun={job.retry} onRerun={job.retry}
/> />

View File

@@ -30,6 +30,14 @@ interface GeoCheckReportProps {
* во весь экран — режим лишь снимал отступы и лез под хром Telegram. * во весь экран — режим лишь снимал отступы и лез под хром Telegram.
*/ */
canFullscreen: boolean; canFullscreen: boolean;
/**
* Показывать ли скачивание. В webview Telegram атрибут `download`
* игнорируется: вместо сохранения файла webview уходит на blob и подменяет
* собой Mini App, вернуться можно только кнопкой «Назад». Штатный
* `downloadFile` из Bot API 8.0 тут не помогает — он требует HTTPS-ссылку
* на файл, а отчёт приходит base64 внутри JSON.
*/
canDownload: boolean;
onToggleFullscreen: () => void; onToggleFullscreen: () => void;
onRerun: () => void; onRerun: () => void;
} }
@@ -48,6 +56,7 @@ export function GeoCheckReport({
nodeName, nodeName,
fullscreen, fullscreen,
canFullscreen, canFullscreen,
canDownload,
onToggleFullscreen, onToggleFullscreen,
onRerun, onRerun,
}: GeoCheckReportProps) { }: GeoCheckReportProps) {
@@ -170,6 +179,7 @@ export function GeoCheckReport({
<CopyIcon className="h-4 w-4" /> <CopyIcon className="h-4 w-4" />
)} )}
</button> </button>
{canDownload && (
<button <button
type="button" type="button"
onClick={handleDownload} onClick={handleDownload}
@@ -180,6 +190,7 @@ export function GeoCheckReport({
> >
<DownloadIcon className="h-4 w-4" /> <DownloadIcon className="h-4 w-4" />
</button> </button>
)}
<button <button
type="button" type="button"
onClick={onRerun} onClick={onRerun}