UNPKG

unified-video-framework

Version:

Cross-platform video player framework supporting iOS, Android, Web, Smart TVs (Samsung/LG), Roku, and more

301 lines (260 loc) 8.54 kB
import { PlatformType, PlatformInfo } from '../interfaces'; export class PlatformDetector { private cachedPlatform: PlatformInfo | null = null; detect(): PlatformInfo { if (this.cachedPlatform) { return this.cachedPlatform; } this.cachedPlatform = this.detectPlatform(); return this.cachedPlatform; } private detectPlatform(): PlatformInfo { // Check if we're in React Native environment if (typeof window === 'undefined' || (global as any).nativeCallSyncHook) { return this.detectReactNativePlatform(); } // Web environment detection if (typeof window !== 'undefined' && typeof navigator !== 'undefined') { return this.detectWebPlatform(); } // Default fallback return { type: PlatformType.WEB, os: 'unknown', version: 'unknown', isTV: false, isMobile: false, isDesktop: true }; } private detectReactNativePlatform(): PlatformInfo { try { // This would be available in React Native environment const { Platform } = require('react-native'); if (Platform.isTV) { return { type: Platform.OS === 'ios' ? PlatformType.APPLE_TV : PlatformType.ANDROID_TV, os: Platform.OS, version: Platform.Version?.toString() || 'unknown', isTV: true, isMobile: false, isDesktop: false }; } return { type: Platform.OS === 'ios' ? PlatformType.IOS : PlatformType.ANDROID, os: Platform.OS, version: Platform.Version?.toString() || 'unknown', isTV: false, isMobile: true, isDesktop: false }; } catch (e) { // If React Native is not available, fall back to web detection return this.detectWebPlatform(); } } private detectWebPlatform(): PlatformInfo { const userAgent = navigator.userAgent.toLowerCase(); const platform = navigator.platform?.toLowerCase() || ''; // Tizen (Samsung TV) if (userAgent.includes('tizen') || (window as any).tizen) { return { type: PlatformType.TIZEN, os: 'tizen', version: this.getTizenVersion(), isTV: true, isMobile: false, isDesktop: false, screenSize: this.getScreenSize() }; } // WebOS (LG TV) if (userAgent.includes('webos') || userAgent.includes('web0s') || (window as any).webOS) { return { type: PlatformType.WEBOS, os: 'webos', version: this.getWebOSVersion(), isTV: true, isMobile: false, isDesktop: false, screenSize: this.getScreenSize() }; } // Roku if (userAgent.includes('roku')) { return { type: PlatformType.ROKU, os: 'roku', version: this.getRokuVersion(userAgent), isTV: true, isMobile: false, isDesktop: false }; } // Windows/UWP if (platform.includes('win') || userAgent.includes('windows')) { return { type: PlatformType.WINDOWS, os: 'windows', version: this.getWindowsVersion(userAgent), isTV: false, isMobile: false, isDesktop: true, hasTouch: this.hasTouchSupport(), screenSize: this.getScreenSize() }; } // iOS (Safari on iPhone/iPad) if (/iphone|ipad|ipod/.test(userAgent) || (platform === 'macintel' && navigator.maxTouchPoints > 1)) { return { type: PlatformType.IOS, os: 'ios', version: this.getIOSVersion(userAgent), isTV: false, isMobile: true, isDesktop: false, hasTouch: true, screenSize: this.getScreenSize() }; } // Android if (userAgent.includes('android')) { const isTV = userAgent.includes('tv') || userAgent.includes('aft'); return { type: isTV ? PlatformType.ANDROID_TV : PlatformType.ANDROID, os: 'android', version: this.getAndroidVersion(userAgent), isTV: isTV, isMobile: !isTV, isDesktop: false, hasTouch: !isTV, screenSize: this.getScreenSize() }; } // Apple TV (tvOS browser) if (userAgent.includes('appletv')) { return { type: PlatformType.APPLE_TV, os: 'tvos', version: 'unknown', isTV: true, isMobile: false, isDesktop: false }; } // Default to web return { type: PlatformType.WEB, os: this.getOS(), version: 'unknown', isTV: false, isMobile: this.isMobileWeb(), isDesktop: !this.isMobileWeb(), hasTouch: this.hasTouchSupport(), screenSize: this.getScreenSize() }; } private getTizenVersion(): string { try { if ((window as any).tizen && (window as any).tizen.systeminfo) { return (window as any).tizen.systeminfo.getCapability('http://tizen.org/feature/platform.version'); } } catch (e) { console.error('Failed to get Tizen version:', e); } return 'unknown'; } private getWebOSVersion(): string { try { if ((window as any).webOS && (window as any).webOS.systemInfo) { return (window as any).webOS.systemInfo.version; } } catch (e) { console.error('Failed to get webOS version:', e); } return 'unknown'; } private getRokuVersion(userAgent: string): string { const match = userAgent.match(/roku\/dvp-(\d+\.\d+)/); return match ? match[1] : 'unknown'; } private getWindowsVersion(userAgent: string): string { if (userAgent.includes('windows nt 10.0')) return '10'; if (userAgent.includes('windows nt 6.3')) return '8.1'; if (userAgent.includes('windows nt 6.2')) return '8'; if (userAgent.includes('windows nt 6.1')) return '7'; return 'unknown'; } private getIOSVersion(userAgent: string): string { const match = userAgent.match(/os (\d+)_(\d+)_?(\d+)?/); if (match) { return `${match[1]}.${match[2]}${match[3] ? `.${match[3]}` : ''}`; } return 'unknown'; } private getAndroidVersion(userAgent: string): string { const match = userAgent.match(/android (\d+\.?\d*)/); return match ? match[1] : 'unknown'; } private getOS(): string { const platform = navigator.platform?.toLowerCase() || ''; const userAgent = navigator.userAgent.toLowerCase(); if (platform.includes('mac')) return 'macos'; if (platform.includes('win')) return 'windows'; if (platform.includes('linux')) return 'linux'; if (userAgent.includes('cros')) return 'chromeos'; return 'unknown'; } private isMobileWeb(): boolean { const userAgent = navigator.userAgent.toLowerCase(); const mobileRegex = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i; return mobileRegex.test(userAgent) || this.isSmallScreen(); } private isSmallScreen(): boolean { return window.innerWidth <= 768 && window.innerHeight <= 1024; } private hasTouchSupport(): boolean { return 'ontouchstart' in window || navigator.maxTouchPoints > 0 || (navigator as any).msMaxTouchPoints > 0; } private getScreenSize(): { width: number; height: number } { return { width: window.screen?.width || window.innerWidth, height: window.screen?.height || window.innerHeight }; } // Utility methods for specific platform checks isTV(): boolean { return this.detect().isTV; } isMobile(): boolean { return this.detect().isMobile; } isDesktop(): boolean { return this.detect().isDesktop || false; } isApple(): boolean { const platform = this.detect().type; return [PlatformType.IOS, PlatformType.APPLE_TV].includes(platform); } isAndroid(): boolean { const platform = this.detect().type; return [PlatformType.ANDROID, PlatformType.ANDROID_TV].includes(platform); } isSamsung(): boolean { return this.detect().type === PlatformType.TIZEN; } isLG(): boolean { return this.detect().type === PlatformType.WEBOS; } isRoku(): boolean { return this.detect().type === PlatformType.ROKU; } // Clear cached platform info (useful for testing) clearCache(): void { this.cachedPlatform = null; } }