From cf3c0b2eb5179fadc68417997f8d03eb695a7d03 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sat, 8 Mar 2025 10:13:07 -0600 Subject: [PATCH] Prevent settings menu scroll on iOS proxy iframe from shifting entire UI (#17024) --- web/src/pages/Settings.tsx | 6 ++++-- web/src/utils/isIFrame.ts | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 web/src/utils/isIFrame.ts diff --git a/web/src/pages/Settings.tsx b/web/src/pages/Settings.tsx index 30be2afc2..f1a45ebc2 100644 --- a/web/src/pages/Settings.tsx +++ b/web/src/pages/Settings.tsx @@ -20,7 +20,7 @@ import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer"; import { Button } from "@/components/ui/button"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import useOptimisticState from "@/hooks/use-optimistic-state"; -import { isMobile } from "react-device-detect"; +import { isMobile, isMobileSafari } from "react-device-detect"; import { FaVideo } from "react-icons/fa"; import { CameraConfig, FrigateConfig } from "@/types/frigateConfig"; import useSWR from "swr"; @@ -40,6 +40,8 @@ import UiSettingsView from "@/views/settings/UiSettingsView"; import { useSearchEffect } from "@/hooks/use-overlay-state"; import { useSearchParams } from "react-router-dom"; import { useInitialCameraState } from "@/api/ws"; +import { isInIframe } from "@/utils/isIFrame"; +import { isPWA } from "@/utils/isPWA"; import { useIsAdmin } from "@/hooks/use-is-admin"; const allSettingsViews = [ @@ -150,7 +152,7 @@ export default function Settings() { ); if (element instanceof HTMLElement) { scrollIntoView(element, { - behavior: "smooth", + behavior: isMobileSafari && !isPWA && isInIframe ? "auto" : "smooth", inline: "start", }); } diff --git a/web/src/utils/isIFrame.ts b/web/src/utils/isIFrame.ts new file mode 100644 index 000000000..1f78a40aa --- /dev/null +++ b/web/src/utils/isIFrame.ts @@ -0,0 +1,8 @@ +export const isInIframe = (() => { + try { + return window.self !== window.top; + } catch (e) { + // If we get a security error, we're definitely in an iframe + return true; + } +})();