Cross-platform utilities for environment detection, platform-specific code execution, and browser capability checking.
Core platform utilities for detecting the current platform and executing platform-specific code.
/**
* Platform utilities for cross-platform development
* Provides current platform detection and platform-specific value selection
*/
interface Platform {
/**
* Current platform: 'ios', 'android', or 'web'
*/
OS: string;
/**
* Select platform-specific values
* Returns value matching current platform or fallback
* @param specifics - Object mapping platforms to values
* @returns Value for current platform
*/
select: <T>(specifics: { [platform in PlatformSelectOSType]?: T }) => T;
/**
* Whether DOM API is available in current environment
* False in native React runtimes and Node.js
*/
isDOMAvailable: boolean;
/**
* Whether environment can attach event listeners to window
* False in native React runtimes and Node.js
*/
canUseEventListeners: boolean;
/**
* Whether environment can inspect screen properties
* False in native React runtimes and Node.js
*/
canUseViewport: boolean;
/**
* Whether JavaScript runs in remote debugging environment
* When true, synchronous native invocations cannot be executed
*/
isAsyncDebugging: boolean;
}
/**
* Platform types supported by Platform.select
*/
type PlatformSelectOSType = 'ios' | 'android' | 'web' | 'native' | 'electron' | 'default';Usage Examples:
import { Platform } from "expo-modules-core";
// Check current platform
console.log("Running on:", Platform.OS); // 'ios', 'android', or 'web'
// Platform-specific values
const styles = Platform.select({
ios: {
backgroundColor: '#007AFF',
borderRadius: 8,
},
android: {
backgroundColor: '#2196F3',
borderRadius: 4,
},
web: {
backgroundColor: '#0066CC',
borderRadius: 6,
},
default: {
backgroundColor: '#999999',
borderRadius: 0,
}
});
// Platform-specific implementations
const storage = Platform.select({
native: require('@react-native-async-storage/async-storage').default,
web: window.localStorage,
});
// Conditional functionality based on platform
if (Platform.OS === 'web') {
// Web-specific code
document.title = "My App";
} else {
// Native-specific code
import('expo-status-bar').then(({ StatusBar }) => {
// Configure native status bar
});
}
// Platform grouping with 'native' selector
const apiEndpoint = Platform.select({
native: 'https://mobile-api.example.com', // Both iOS and Android
web: 'https://web-api.example.com',
default: 'https://api.example.com'
});Utilities for detecting browser and runtime capabilities.
/**
* Environment capability detection utilities
*/
const Platform: {
/**
* DOM availability - can use document, window objects
*/
isDOMAvailable: boolean;
/**
* Event listener capability - can use addEventListener on window
*/
canUseEventListeners: boolean;
/**
* Viewport access - can inspect screen dimensions
*/
canUseViewport: boolean;
/**
* Remote debugging detection - affects synchronous operations
*/
isAsyncDebugging: boolean;
};Usage Examples:
import { Platform } from "expo-modules-core";
// Safe DOM operations
if (Platform.isDOMAvailable) {
document.title = "My Application";
const element = document.getElementById('root');
element?.classList.add('app-loaded');
}
// Event listener setup
if (Platform.canUseEventListeners) {
window.addEventListener('resize', () => {
console.log('Window resized');
});
// Online/offline detection
window.addEventListener('online', () => {
console.log('Back online');
});
}
// Viewport operations
if (Platform.canUseViewport) {
const screenWidth = window.screen.width;
const screenHeight = window.screen.height;
// Responsive design decisions
const isMobile = screenWidth < 768;
console.log('Mobile device:', isMobile);
}
// Handle debugging environment
if (Platform.isAsyncDebugging) {
console.warn('Running in remote debugger - some features may be limited');
// Avoid synchronous native calls
await performAsyncOperation();
} else {
// Can use synchronous native calls
const result = performSyncOperation();
}
// Comprehensive environment check
function setupEnvironment() {
const capabilities = {
platform: Platform.OS,
dom: Platform.isDOMAvailable,
events: Platform.canUseEventListeners,
viewport: Platform.canUseViewport,
debugging: Platform.isAsyncDebugging,
};
console.log('Environment capabilities:', capabilities);
// Configure based on capabilities
if (capabilities.dom && capabilities.events) {
setupWebFeatures();
}
if (!capabilities.debugging) {
enableSyncFeatures();
}
}Best practices for organizing platform-specific code:
import { Platform } from "expo-modules-core";
// File-based platform selection (recommended for large differences)
const PlatformSpecificComponent = Platform.select({
ios: require('./Component.ios').default,
android: require('./Component.android').default,
web: require('./Component.web').default,
default: require('./Component.default').default,
});
// Inline platform selection (good for small differences)
const buttonStyles = {
padding: 12,
borderRadius: Platform.select({
ios: 8,
android: 4,
web: 6,
default: 0,
}),
backgroundColor: Platform.select({
ios: '#007AFF',
android: '#2196F3',
web: '#0066CC',
native: '#0080FF', // Both iOS and Android
default: '#666666',
}),
};
// Function-based platform selection (for complex logic)
function getNetworkingImplementation() {
return Platform.select({
native: () => import('react-native').then(rn => rn.fetch),
web: () => Promise.resolve(window.fetch),
default: () => Promise.resolve(globalThis.fetch),
})();
}
// Platform-specific constants
const CONSTANTS = Platform.select({
ios: {
HEADER_HEIGHT: 44,
TABBAR_HEIGHT: 49,
STATUS_BAR_HEIGHT: 20,
},
android: {
HEADER_HEIGHT: 56,
TABBAR_HEIGHT: 56,
STATUS_BAR_HEIGHT: 24,
},
web: {
HEADER_HEIGHT: 60,
TABBAR_HEIGHT: 60,
STATUS_BAR_HEIGHT: 0,
},
default: {
HEADER_HEIGHT: 50,
TABBAR_HEIGHT: 50,
STATUS_BAR_HEIGHT: 0,
},
});
// Runtime platform detection
function handlePlatformFeatures() {
switch (Platform.OS) {
case 'ios':
// iOS-specific features
import('expo-haptics').then(haptics => {
haptics.impactAsync('medium');
});
break;
case 'android':
// Android-specific features
import('expo-system-ui').then(systemUI => {
systemUI.setBackgroundColorAsync('#FFFFFF');
});
break;
case 'web':
// Web-specific features
if (Platform.isDOMAvailable) {
document.title = 'My App';
}
break;
default:
console.log('Unknown platform');
}
}/**
* All platform types supported by Platform.select
*/
type PlatformSelectOSType = 'ios' | 'android' | 'web' | 'native' | 'electron' | 'default';
/**
* Generic function type for platform-specific value selection
*/
type PlatformSelect = <T>(specifics: { [platform in PlatformSelectOSType]?: T }) => T;