@ordojs/mobile
v0.1.0
Published
Mobile and PWA support for OrdoJS applications
Maintainers
Readme
@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
pnpm add @ordojs/mobileUsage
PWA Setup
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
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
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
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
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
interface GestureConfig {
enabled: boolean;
threshold: number;
velocity: number;
direction: 'horizontal' | 'vertical' | 'both';
preventDefault: boolean;
}Native Configuration
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
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
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
