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
text/typescript
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;
}
}