mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-08-18 17:53:29 +00:00
refactor: consolidate platform detection across client components (#3325)
## 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
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
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;
|
||||
},
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user