mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 10:00:44 +00:00
f7598369ed
## Description: This PR consolidates ad hoc platform/environment/viewport detection into a single shared utility. It is scoped to this refactor only, and serves as groundwork for the mobile-focused feature work planned for the v31 milestone. ### What changed - Introduced a shared `Platform` utility centralising: - OS detection (with `userAgentData` + UA fallback) - Electron environment detection - Viewport breakpoint helpers (`isMobileWidth`, `isTabletWidth`, `isDesktopWidth`) - Replaced duplicated inline checks across client files with the shared API. - Normalised Mac detection to derive from the consolidated OS logic rather than a separate regex. ### Why - Multiple client files each independently ran `navigator.userAgent` regexes or copy-pasted `isElectron` logic — this unifies all of that. - Puts a stable, tested abstraction in place before v31 mobile work lands, so mobile feature branches have a consistent surface to build against. ## Please complete the following: - [x] I have added screenshots for all UI updates (N/A: refactor only, no visible UI changes) - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file (N/A: no new user-facing strings) - [x] I have added relevant tests to the test directory (N/A: refactor only) - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: skigim
113 lines
2.8 KiB
TypeScript
113 lines
2.8 KiB
TypeScript
export const Platform = (() => {
|
|
const isBrowser =
|
|
typeof window !== "undefined" && typeof navigator !== "undefined";
|
|
|
|
const normalizePlatform = (platform: string): string => {
|
|
const normalized = platform.toLowerCase();
|
|
if (normalized.includes("windows")) return "Windows";
|
|
if (
|
|
normalized.includes("iphone") ||
|
|
normalized.includes("ipad") ||
|
|
normalized.includes("ipod") ||
|
|
normalized.includes("ios")
|
|
) {
|
|
return "iOS";
|
|
}
|
|
if (
|
|
normalized.includes("mac") ||
|
|
normalized.includes("macintosh") ||
|
|
normalized.includes("macos")
|
|
) {
|
|
return "macOS";
|
|
}
|
|
if (normalized.includes("android")) return "Android";
|
|
if (normalized.includes("chrome os")) return "Linux";
|
|
if (normalized.includes("linux")) return "Linux";
|
|
return "Unknown";
|
|
};
|
|
|
|
// OS Extraction
|
|
const extractOS = (): string => {
|
|
if (!isBrowser) return "Unknown";
|
|
|
|
const uaData = (navigator as any).userAgentData;
|
|
if (uaData?.platform) {
|
|
return normalizePlatform(uaData.platform);
|
|
}
|
|
|
|
const ua = navigator.userAgent;
|
|
if (/windows nt/i.test(ua)) return "Windows";
|
|
if (/iphone|ipad|ipod/i.test(ua)) return "iOS";
|
|
if (
|
|
/mac os x/i.test(ua) &&
|
|
((navigator.maxTouchPoints ?? 0) > 1 || /ipad/i.test(ua))
|
|
) {
|
|
return "iOS";
|
|
}
|
|
if (/mac os x/i.test(ua)) return "macOS";
|
|
if (/android/i.test(ua)) return "Android";
|
|
if (/linux/i.test(ua)) return "Linux";
|
|
return "Unknown";
|
|
};
|
|
|
|
const currentOS = extractOS();
|
|
|
|
// Environment Extraction
|
|
const performElectronCheck = (): boolean => {
|
|
// Renderer process
|
|
if (
|
|
typeof window !== "undefined" &&
|
|
typeof (window as any).process === "object" &&
|
|
(window as any).process.type === "renderer"
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Main process
|
|
if (
|
|
typeof process !== "undefined" &&
|
|
typeof process.versions === "object" &&
|
|
!!process.versions.electron
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Detect the user agent when the `nodeIntegration` option is set to false
|
|
if (
|
|
isBrowser &&
|
|
typeof navigator.userAgent === "string" &&
|
|
navigator.userAgent.indexOf("Electron") >= 0
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
const isMac = currentOS === "macOS";
|
|
|
|
return {
|
|
os: currentOS,
|
|
isMac,
|
|
isWindows: currentOS === "Windows",
|
|
isIOS: currentOS === "iOS",
|
|
isAndroid: currentOS === "Android",
|
|
isLinux: currentOS === "Linux",
|
|
isElectron: performElectronCheck(),
|
|
|
|
get isMobileWidth(): boolean {
|
|
return isBrowser ? window.innerWidth < 768 : false;
|
|
},
|
|
|
|
get isTabletWidth(): boolean {
|
|
return isBrowser
|
|
? window.innerWidth >= 768 && window.innerWidth < 1024
|
|
: false;
|
|
},
|
|
|
|
get isDesktopWidth(): boolean {
|
|
return isBrowser ? window.innerWidth >= 1024 : false;
|
|
},
|
|
};
|
|
})();
|