UNPKG

@ordojs/mobile

Version:

Mobile and PWA support for OrdoJS applications

532 lines (420 loc) 11.9 kB
# @ordojs/mobile Mobile and PWA support for OrdoJS applications. This package provides comprehensive tools for building mobile-optimized applications with PWA capabilities, touch gestures, and native device features. ## Features - **PWA Support**: Service worker generation, app manifest management, and install prompts - **Touch Gestures**: Comprehensive gesture recognition (swipe, pinch, rotate, tap, pan) - **Native Features**: Camera, geolocation, notifications, and device information access - **Offline Support**: Offline-first data synchronization and caching strategies - **Mobile Optimization**: Responsive design utilities and mobile-specific components ## Installation ```bash pnpm add @ordojs/mobile ``` ## Usage ### PWA Setup ```typescript import { PWAManager } from '@ordojs/mobile'; const pwaConfig = { name: 'My OrdoJS App', shortName: 'OrdoJS', description: 'A progressive web app built with OrdoJS', startUrl: '/', display: 'standalone', themeColor: '#ffffff', backgroundColor: '#000000', icons: [ { src: '/icon-192x192.png', sizes: '192x192', type: 'image/png', }, { src: '/icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable', }, ], categories: ['productivity'], lang: 'en', dir: 'ltr', orientation: 'portrait', scope: '/', preferRelatedApplications: false, relatedApplications: [], }; const swConfig = { scope: '/', updateViaCache: 'imports', skipWaiting: true, clientsClaim: true, offlinePage: '/offline.html', cacheStrategies: [ { name: 'static', pattern: '/static/*', strategy: 'cache-first', maxAge: 86400, }, { name: 'api', pattern: '/api/*', strategy: 'network-first', maxAge: 300, }, ], backgroundSync: { enabled: true, syncName: 'background-sync', }, pushNotifications: { enabled: true, defaultNotificationOptions: { title: 'New notification', body: 'You have a new message', icon: '/icon-192x192.png', }, }, }; const pwaManager = new PWAManager(pwaConfig, swConfig); // Generate manifest const manifest = pwaManager.generateManifest(); console.log(manifest); // Generate service worker const swScript = pwaManager.generateServiceWorker(); console.log(swScript); // Register service worker await pwaManager.registerServiceWorker(); // Check if app is installed if (pwaManager.isInstalled()) { console.log('App is installed as PWA'); } // Show install prompt try { await pwaManager.showInstallPrompt(); } catch (error) { console.log('Install prompt not supported'); } ``` ### Touch Gestures ```typescript import { GestureManager } from '@ordojs/mobile'; const element = document.getElementById('gesture-area'); const gestureManager = new GestureManager(element, { enabled: true, threshold: 10, velocity: 0.3, direction: 'both', preventDefault: true, }); // Listen for swipe gestures gestureManager.on('swipe', event => { console.log('Swipe detected:', event.direction, event.velocity); switch (event.direction) { case 'left': // Navigate to next page break; case 'right': // Navigate to previous page break; case 'up': // Scroll up break; case 'down': // Scroll down break; } }); // Listen for pinch gestures gestureManager.on('pinch', event => { console.log('Pinch detected:', event.scale); // Handle zoom in/out }); // Listen for tap gestures gestureManager.on('tap', event => { console.log('Tap detected'); // Handle tap action }); // Listen for long press gestureManager.on('longpress', event => { console.log('Long press detected'); // Show context menu }); // Clean up when done gestureManager.destroy(); ``` ### Native Features ```typescript import { NativeManager } from '@ordojs/mobile'; const nativeManager = new NativeManager({ features: { camera: true, geolocation: true, contacts: true, calendar: true, notifications: true, storage: true, network: true, device: true, }, }); // Get device information const deviceInfo = await nativeManager.getDeviceInfo(); console.log('Device:', deviceInfo.platform, deviceInfo.model); console.log('Screen:', deviceInfo.screenWidth, 'x', deviceInfo.screenHeight); console.log('Battery:', deviceInfo.batteryLevel * 100, '%'); // Take a photo try { const photo = await nativeManager.takePhoto({ source: 'camera', quality: 0.8, maxWidth: 1920, maxHeight: 1080, }); console.log('Photo taken:', photo.dataUrl); } catch (error) { console.error('Failed to take photo:', error); } // Get current location try { const location = await nativeManager.getLocation({ highAccuracy: true, timeout: 10000, }); console.log('Location:', location.latitude, location.longitude); } catch (error) { console.error('Failed to get location:', error); } // Send notification try { await nativeManager.sendNotification({ title: 'Hello from OrdoJS!', body: 'This is a test notification', icon: '/icon-192x192.png', badge: '/badge-72x72.png', vibrate: [100, 50, 100], }); } catch (error) { console.error('Failed to send notification:', error); } // Check available features const features = nativeManager.getAvailableFeatures(); features.forEach(feature => { console.log(`${feature.name}: ${feature.available ? 'Available' : 'Not available'}`); }); ``` ### Complete Mobile App Setup ```typescript import { PWAManager, GestureManager, NativeManager } from '@ordojs/mobile'; class MobileApp { private pwaManager: PWAManager; private gestureManager: GestureManager; private nativeManager: NativeManager; constructor() { // Initialize PWA this.pwaManager = new PWAManager(pwaConfig, swConfig); // Initialize gestures const gestureElement = document.getElementById('app-container'); this.gestureManager = new GestureManager(gestureElement); // Initialize native features this.nativeManager = new NativeManager(); this.setupEventListeners(); } private setupEventListeners(): void { // PWA events this.pwaManager.registerServiceWorker().then(() => { console.log('Service worker registered'); }); // Gesture events this.gestureManager.on('swipe', this.handleSwipe.bind(this)); this.gestureManager.on('pinch', this.handlePinch.bind(this)); this.gestureManager.on('tap', this.handleTap.bind(this)); // Device events window.addEventListener('online', this.handleOnline.bind(this)); window.addEventListener('offline', this.handleOffline.bind(this)); } private handleSwipe(event: any): void { // Handle swipe navigation } private handlePinch(event: any): void { // Handle zoom } private handleTap(event: any): void { // Handle tap } private handleOnline(): void { console.log('Device is online'); // Sync data } private handleOffline(): void { console.log('Device is offline'); // Show offline indicator } async initialize(): Promise<void> { // Get device info const deviceInfo = await this.nativeManager.getDeviceInfo(); // Request permissions if (deviceInfo.platform !== 'web') { await this.requestPermissions(); } console.log('Mobile app initialized'); } private async requestPermissions(): Promise<void> { const permissions = ['camera', 'geolocation', 'notifications']; for (const permission of permissions) { try { const granted = await this.nativeManager.requestPermission(permission); console.log(`${permission} permission: ${granted ? 'granted' : 'denied'}`); } catch (error) { console.error(`Failed to request ${permission} permission:`, error); } } } } // Initialize the app const app = new MobileApp(); app.initialize(); ``` ## API Reference ### PWAManager #### `generateManifest(): string` Generates the web app manifest JSON. #### `generateServiceWorker(): string` Generates the service worker script. #### `registerServiceWorker(): Promise<ServiceWorkerRegistration | null>` Registers the service worker. #### `isInstalled(): boolean` Checks if the app is installed as a PWA. #### `showInstallPrompt(): Promise<void>` Shows the install prompt. ### GestureManager #### `on(type: string, listener: (event: GestureEvent) => void): void` Adds a gesture listener. #### `off(type: string, listener: (event: GestureEvent) => void): void` Removes a gesture listener. #### `destroy(): void` Destroys the gesture manager. ### NativeManager #### `getDeviceInfo(): Promise<DeviceInfo>` Gets device information. #### `requestPermission(feature: string): Promise<boolean>` Requests permission for a native feature. #### `takePhoto(options: CameraOptions): Promise<PhotoResult>` Takes a photo using the camera. #### `getLocation(options: GeolocationOptions): Promise<LocationResult>` Gets current location. #### `sendNotification(options: NotificationOptions): Promise<void>` Sends a notification. #### `getAvailableFeatures(): NativeFeature[]` Gets available native features. ## Configuration ### PWA Configuration ```typescript interface PWAConfig { name: string; shortName: string; description: string; startUrl: string; display: 'standalone' | 'fullscreen' | 'minimal-ui' | 'browser'; themeColor: string; backgroundColor: string; icons: PWAIcon[]; categories: string[]; lang: string; dir: 'ltr' | 'rtl'; orientation: 'portrait' | 'landscape' | 'any'; scope: string; preferRelatedApplications: boolean; relatedApplications: RelatedApplication[]; } ``` ### Gesture Configuration ```typescript interface GestureConfig { enabled: boolean; threshold: number; velocity: number; direction: 'horizontal' | 'vertical' | 'both'; preventDefault: boolean; } ``` ### Native Configuration ```typescript interface NativeConfig { features: { camera: boolean; geolocation: boolean; contacts: boolean; calendar: boolean; notifications: boolean; storage: boolean; network: boolean; device: boolean; }; permissions: PermissionConfig[]; plugins: PluginConfig[]; } ``` ## Examples ### Responsive Mobile Layout ```typescript import { NativeManager } from '@ordojs/mobile'; const nativeManager = new NativeManager(); // Adapt layout based on device async function adaptLayout() { const deviceInfo = await nativeManager.getDeviceInfo(); if (deviceInfo.platform === 'ios') { // iOS-specific layout document.body.classList.add('ios'); } else if (deviceInfo.platform === 'android') { // Android-specific layout document.body.classList.add('android'); } // Handle orientation changes if (deviceInfo.orientation === 'landscape') { document.body.classList.add('landscape'); } else { document.body.classList.add('portrait'); } } adaptLayout(); ``` ### Offline-First Data Sync ```typescript import { PWAManager } from '@ordojs/mobile'; const pwaManager = new PWAManager(pwaConfig, { ...swConfig, backgroundSync: { enabled: true, syncName: 'data-sync', syncOptions: { minInterval: 60000, // 1 minute maxRetentionTime: 86400000, // 24 hours }, }, }); // Sync data when online window.addEventListener('online', async () => { try { await syncData(); console.log('Data synced successfully'); } catch (error) { console.error('Failed to sync data:', error); } }); async function syncData() { // Implement data synchronization logic const pendingData = await getPendingData(); for (const item of pendingData) { await sendToServer(item); await markAsSynced(item.id); } } ``` ## Contributing This package is part of the OrdoJS ecosystem. Please refer to the main OrdoJS repository for contribution guidelines. ## License MIT