Duffer Derek
// Device detection utilities for PWA and notification features
import { isIOSDevice, isIOSPWA, safeLocalStorage } from "./iosPWAUtils";
export interface DeviceInfo {
isMobile: boolean;
isIOS: boolean;
isAndroid: boolean;
isDesktop: boolean;
isPWA: boolean;
isStandalone: boolean;
iosVersion: number | null;
browserName: string;
platform: "Web" | "PWA";
osName: string;
}
// Detect if device is mobile
export const isMobile = (): boolean => {
if (typeof window === "undefined") return false;
const userAgent = navigator.userAgent.toLowerCase();
const mobileKeywords = [
"mobile",
"android",
"iphone",
"ipad",
"ipod",
"blackberry",
"windows phone",
];
return (
mobileKeywords.some((keyword) => userAgent.includes(keyword)) ||
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)
);
};
// Detect if device is iOS
export const isIOS = (): boolean => {
return isIOSDevice();
};
// Detect if device is Android
export const isAndroid = (): boolean => {
if (typeof window === "undefined") return false;
const userAgent = navigator.userAgent.toLowerCase();
return /android/.test(userAgent);
};
// Detect if device is desktop
export const isDesktop = (): boolean => {
return !isMobile();
};
// Detect if app is running as PWA (standalone mode)
export const isPWA = (): boolean => {
if (typeof window === "undefined") return false;
// Use iOS-specific PWA detection if on iOS
if (isIOSDevice()) {
return isIOSPWA();
}
// Primary check: display mode
const isStandaloneMode = window.matchMedia("(display-mode: standalone)").matches;
// Secondary check: iOS Safari standalone
const isIOSStandalone = (window.navigator as any).standalone === true;
// Tertiary check: window dimensions (PWA has no browser chrome)
const hasNoBrowserChrome = window.screen.height - window.innerHeight < 100;
// Additional check: check if we're in a PWA context
const isPWAContext =
window.location.protocol === "https:" || window.location.hostname === "localhost";
// Return true if any of the primary checks pass
return isStandaloneMode || isIOSStandalone || (hasNoBrowserChrome && isPWAContext);
};
// Detect if app is in standalone mode (alternative check)
export const isStandalone = (): boolean => {
if (typeof window === "undefined") return false;
return (
window.matchMedia("(display-mode: standalone)").matches ||
(window.navigator as any).standalone === true
);
};
// Get iOS version
export const getIOSVersion = (): number | null => {
if (typeof window === "undefined" || !isIOS()) return null;
const userAgent = navigator.userAgent;
const match = userAgent.match(/OS (\d+)_(\d+)/);
if (match) {
const major = parseInt(match[1], 10);
const minor = parseInt(match[2], 10);
return major + minor / 10;
}
return null;
};
// Get OS name
export const getOSName = (): string => {
if (typeof window === "undefined") return "Unknown";
const userAgent = navigator.userAgent.toLowerCase();
// Mobile OS detection
if (/iphone|ipad|ipod/.test(userAgent)) {
return "iOS";
}
if (/android/.test(userAgent)) {
return "Android";
}
// Desktop OS detection
if (/windows/.test(userAgent)) {
return "Windows";
}
if (/macintosh|mac os x/.test(userAgent)) {
return "macOS";
}
if (/linux/.test(userAgent)) {
return "Linux";
}
if (/chrome os/.test(userAgent)) {
return "Chrome OS";
}
return "Unknown";
};
// Get browser name
export const getBrowserName = (): string => {
if (typeof window === "undefined") return "Unknown";
const userAgent = navigator.userAgent;
if (userAgent.includes("Chrome")) return "Chrome";
if (userAgent.includes("Firefox")) return "Firefox";
if (userAgent.includes("Safari") && !userAgent.includes("Chrome")) return "Safari";
if (userAgent.includes("Edge")) return "Edge";
if (userAgent.includes("Opera")) return "Opera";
if (userAgent.includes("Samsung")) return "Samsung Internet";
return "Unknown";
};
// Get platform type
export const getPlatform = (): "Web" | "PWA" => {
return isPWA() ? "PWA" : "Web";
};
// Check if iOS version supports notifications (>= 16.4)
export const isIOSNotificationSupported = (): boolean => {
const iosVersion = getIOSVersion();
return iosVersion !== null && iosVersion >= 16.4;
};
// Get comprehensive device information
export const getDeviceInfo = (): DeviceInfo => {
return {
isMobile: isMobile(),
isIOS: isIOS(),
isAndroid: isAndroid(),
isDesktop: isDesktop(),
isPWA: isPWA(),
isStandalone: isStandalone(),
iosVersion: getIOSVersion(),
browserName: getBrowserName(),
platform: getPlatform(),
osName: getOSName(),
};
};
// Check if notifications are supported on current device
export const isNotificationSupported = (): boolean => {
if (typeof window === "undefined") return false;
try {
// Check if notifications are supported
if (!("Notification" in window)) return false;
// For iOS, check version requirement
if (isIOS()) {
return isIOSNotificationSupported();
}
return true;
} catch (error) {
console.warn("Error checking notification support:", error);
return false;
}
};
// Check if PWA installation is supported
export const isPWAInstallSupported = (): boolean => {
if (typeof window === "undefined") return false;
// Check if beforeinstallprompt event is supported
const hasBeforeInstallPrompt = "onbeforeinstallprompt" in window;
// Additional checks for PWA installation support
const hasServiceWorker = "serviceWorker" in navigator;
const isHTTPS = window.location.protocol === "https:" || window.location.hostname === "localhost";
// console.log("PWA Install Support Check:", {
// hasBeforeInstallPrompt,
// hasServiceWorker,
// isHTTPS,
// userAgent: navigator.userAgent,
// });
return hasBeforeInstallPrompt && hasServiceWorker && isHTTPS;
};
// Check if PWA has been installed before (using multiple methods)
export const hasPWABeenInstalled = (): boolean => {
if (typeof window === "undefined") return false;
// Use safe localStorage for iOS
const localStorageFlag = safeLocalStorage.getItem("pwa_installed") === "true";
// Check if we're currently in PWA mode
const currentlyInPWA = isPWA();
// Check if the app was previously installed (by checking if we can detect PWA context)
const hasPWAContext =
window.matchMedia("(display-mode: standalone)").matches ||
(window.navigator as any).standalone === true;
// If we're currently in PWA mode, mark it as installed in localStorage
if (currentlyInPWA && !localStorageFlag) {
safeLocalStorage.setItem("pwa_installed", "true");
}
return localStorageFlag || currentlyInPWA || hasPWAContext;
};
// Check if service worker is supported
export const isServiceWorkerSupported = (): boolean => {
if (typeof window === "undefined") return false;
return "serviceWorker" in navigator;
};
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists