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>
This commit is contained in:
c0mrade
2026-08-19 17:33:56 +03:00
parent debe26ae35
commit 5db1ffccf6
2 changed files with 34 additions and 15 deletions

View File

@@ -5,6 +5,7 @@ import type { NodeInfo } from '@/api/adminRemnawave';
import { GeoCheckIcon, PlayIcon, WarningIcon, XCloseIcon } from '@/components/icons'; import { GeoCheckIcon, PlayIcon, WarningIcon, XCloseIcon } from '@/components/icons';
import { Spinner } from '@/components/ui/Spinner'; import { Spinner } from '@/components/ui/Spinner';
import { useFocusTrap } from '@/hooks/useFocusTrap'; import { useFocusTrap } from '@/hooks/useFocusTrap';
import { useIsTelegram } from '@/platform/hooks/usePlatform';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { GeoCheckReport } from './GeoCheckReport'; import { GeoCheckReport } from './GeoCheckReport';
import { buildGeoCheckRequest, isRouteReady, type GeoCheckRouteMode } from './geoCheckRoute'; import { buildGeoCheckRequest, isRouteReady, type GeoCheckRouteMode } from './geoCheckRoute';
@@ -27,7 +28,12 @@ export function GeoCheckModal({ node, onClose }: GeoCheckModalProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const [mode, setMode] = useState<GeoCheckRouteMode>('default'); const [mode, setMode] = useState<GeoCheckRouteMode>('default');
const [value, setValue] = useState(''); const [value, setValue] = useState('');
const [fullscreen, setFullscreen] = useState(false); const [fullscreenRequested, setFullscreenRequested] = useState(false);
// В Mini App окно Telegram и так занимает экран целиком: отдельный
// полноэкранный режим там только снимал отступы и залезал под хром.
const canFullscreen = !useIsTelegram();
const fullscreen = canFullscreen && fullscreenRequested;
const job = useGeoCheckJob(node.uuid); const job = useGeoCheckJob(node.uuid);
const isRunning = job.phase === 'running'; const isRunning = job.phase === 'running';
@@ -35,11 +41,11 @@ export function GeoCheckModal({ node, onClose }: GeoCheckModalProps) {
// Пока идёт проверка, закрывать по Escape нельзя: задача уже поставлена // Пока идёт проверка, закрывать по Escape нельзя: задача уже поставлена
// в панель, и молча потерять её результат — хуже, чем подождать. // в панель, и молча потерять её результат — хуже, чем подождать.
const dialogRef = useFocusTrap<HTMLDivElement>(true, { const dialogRef = useFocusTrap<HTMLDivElement>(true, {
onEscape: isRunning ? undefined : fullscreen ? () => setFullscreen(false) : onClose, onEscape: isRunning ? undefined : fullscreen ? () => setFullscreenRequested(false) : onClose,
}); });
useEffect(() => { useEffect(() => {
if (job.phase !== 'done') setFullscreen(false); if (job.phase !== 'done') setFullscreenRequested(false);
}, [job.phase]); }, [job.phase]);
const canStart = isRouteReady(mode, value); const canStart = isRouteReady(mode, value);
@@ -211,7 +217,8 @@ export function GeoCheckModal({ node, onClose }: GeoCheckModalProps) {
result={job.result} result={job.result}
nodeName={node.name} nodeName={node.name}
fullscreen={fullscreen} fullscreen={fullscreen}
onToggleFullscreen={() => setFullscreen((v) => !v)} canFullscreen={canFullscreen}
onToggleFullscreen={() => setFullscreenRequested((v) => !v)}
onRerun={job.retry} onRerun={job.retry}
/> />
)} )}

View File

@@ -25,6 +25,11 @@ interface GeoCheckReportProps {
result: GeoCheckResult; result: GeoCheckResult;
nodeName: string; nodeName: string;
fullscreen: boolean; fullscreen: boolean;
/**
* Показывать ли переключатель полного экрана. В Telegram Mini App окно и так
* во весь экран — режим лишь снимал отступы и лез под хром Telegram.
*/
canFullscreen: boolean;
onToggleFullscreen: () => void; onToggleFullscreen: () => void;
onRerun: () => void; onRerun: () => void;
} }
@@ -42,6 +47,7 @@ export function GeoCheckReport({
result, result,
nodeName, nodeName,
fullscreen, fullscreen,
canFullscreen,
onToggleFullscreen, onToggleFullscreen,
onRerun, onRerun,
}: GeoCheckReportProps) { }: GeoCheckReportProps) {
@@ -133,17 +139,23 @@ export function GeoCheckReport({
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button {canFullscreen && (
type="button" <button
onClick={onToggleFullscreen} type="button"
disabled={!imageSrc} onClick={onToggleFullscreen}
className={TOOLBAR_BUTTON} disabled={!imageSrc}
title={fullscreenLabel} className={TOOLBAR_BUTTON}
aria-label={fullscreenLabel} title={fullscreenLabel}
aria-pressed={fullscreen} aria-label={fullscreenLabel}
> aria-pressed={fullscreen}
{fullscreen ? <CollapseIcon className="h-4 w-4" /> : <ExpandIcon className="h-4 w-4" />} >
</button> {fullscreen ? (
<CollapseIcon className="h-4 w-4" />
) : (
<ExpandIcon className="h-4 w-4" />
)}
</button>
)}
<button <button
type="button" type="button"
onClick={handleCopy} onClick={handleCopy}