TdAI / llama.cpp /tools /ui /src /lib /stores /device.svelte.ts
tda45's picture
Upload folder using huggingface_hub (part 8)
15c3607 verified
Raw
History Blame Contribute Delete
2.64 kB
import { browser } from '$app/environment';
import { MEDIA_QUERIES } from '$lib/constants';
/**
* iOS UA token detection.
*
* iPadOS 13+ ships a desktop macOS UA, so 'iPad' is no longer present in it;
* a Macintosh UA combined with touch support is treated as an iPad instead.
* Third-party iOS browsers (Chrome, Firefox, Edge) and in-app WKWebViews all
* run on WKWebView and emit their own tokens (CriOS/FxiOS/EdgiOS/GSA) instead
* of the trailing 'Safari/' the Safari app keeps.
*/
const UA_PATTERNS = {
IOS_PHONE: /iPhone|iPod/,
MACINTOSH: /Macintosh/,
SAFARI: /Safari/,
WEBVIEW_IOS: /CriOS|FxiOS|EdgiOS|GSA/
} as const;
interface DeviceContext {
/** Any iOS/iPadOS device, regardless of which app or browser embeds the page. */
isIOSDevice: boolean;
/** The Safari browser app on iOS, excluding other iOS browsers and WKWebViews. */
isIOSSafari: boolean;
/** Any WKWebView context on iOS: in-app browsers, embedded web views, and the
* third-party iOS browsers (all of which share the WKWebView engine). */
isWKWebView: boolean;
/** PWA standalone mode: the page was launched from the home screen icon. */
isStandalone: boolean;
}
const SERVER_DEFAULT: DeviceContext = {
isIOSDevice: false,
isIOSSafari: false,
isWKWebView: false,
isStandalone: false
};
function detect(): DeviceContext {
if (!browser) return SERVER_DEFAULT;
const ua = navigator.userAgent;
const isTouch = navigator.maxTouchPoints > 0;
const isIOSDevice = UA_PATTERNS.IOS_PHONE.test(ua) || (UA_PATTERNS.MACINTOSH.test(ua) && isTouch);
// Safari keeps 'Safari/' in the UA; non-Safari iOS browsers emit their own
// token instead. WKWebView typically omits 'Safari/' entirely.
const hasSafariToken = UA_PATTERNS.SAFARI.test(ua) && !UA_PATTERNS.WEBVIEW_IOS.test(ua);
const isIOSSafari = isIOSDevice && hasSafariToken;
const isWKWebView = isIOSDevice && !hasSafariToken;
// navigator.standalone is the legacy iOS-only flag (deprecated but still
// present); display-mode: standalone is the modern standard (Safari 16.4+).
const isStandalone =
window.matchMedia(MEDIA_QUERIES.DISPLAY_MODE_STANDALONE).matches ||
(navigator as Navigator & { standalone?: boolean }).standalone === true;
return { isIOSDevice, isIOSSafari, isWKWebView, isStandalone };
}
export const device = $state<DeviceContext>(detect());
if (browser) {
// isStandalone can change at runtime (e.g. user installs the PWA while the
// tab is open); the UA-derived flags are static for the session.
const mql = window.matchMedia(MEDIA_QUERIES.DISPLAY_MODE_STANDALONE);
mql.addEventListener('change', (e) => {
device.isStandalone = e.matches;
});
}