1 changed files with 260 additions and 0 deletions
@ -0,0 +1,260 @@ |
|||||
|
--- |
||||
|
description: |
||||
|
globs: |
||||
|
alwaysApply: true |
||||
|
--- |
||||
|
# TimeSafari Cross-Platform Architecture Guide |
||||
|
|
||||
|
## 1. Platform Support Matrix |
||||
|
|
||||
|
| Feature | Web (PWA) | Capacitor (Mobile) | Electron (Desktop) | PyWebView (Desktop) | |
||||
|
|---------|-----------|-------------------|-------------------|-------------------| |
||||
|
| QR Code Scanning | vue-qrcode-reader | @capacitor-mlkit/barcode-scanning | Not Implemented | Not Implemented | |
||||
|
| Deep Linking | URL Parameters | App URL Open Events | Not Implemented | Not Implemented | |
||||
|
| File System | Limited (Browser API) | Capacitor Filesystem | Electron fs | PyWebView Python Bridge | |
||||
|
| Camera Access | MediaDevices API | Capacitor Camera | Not Implemented | Not Implemented | |
||||
|
| Platform Detection | Web APIs | Capacitor.isNativePlatform() | process.env checks | process.env checks | |
||||
|
|
||||
|
## 2. Build Configuration Structure |
||||
|
|
||||
|
### 2.1 Entry Points |
||||
|
``` |
||||
|
src/ |
||||
|
├── main.ts # Base entry |
||||
|
├── main.common.ts # Shared initialization |
||||
|
├── main.capacitor.ts # Mobile entry |
||||
|
├── main.electron.ts # Electron entry |
||||
|
├── main.pywebview.ts # PyWebView entry |
||||
|
└── main.web.ts # Web/PWA entry |
||||
|
``` |
||||
|
|
||||
|
### 2.2 Build Configurations |
||||
|
``` |
||||
|
root/ |
||||
|
├── vite.config.common.mts # Shared config |
||||
|
├── vite.config.capacitor.mts # Mobile build |
||||
|
├── vite.config.electron.mts # Electron build |
||||
|
├── vite.config.pywebview.mts # PyWebView build |
||||
|
└── vite.config.web.mts # Web/PWA build |
||||
|
``` |
||||
|
|
||||
|
## 3. Platform Service Architecture |
||||
|
|
||||
|
### 3.1 Service Factory Pattern |
||||
|
```typescript |
||||
|
// PlatformServiceFactory.ts |
||||
|
export class PlatformServiceFactory { |
||||
|
private static instance: PlatformService | null = null; |
||||
|
|
||||
|
public static getInstance(): PlatformService { |
||||
|
if (!PlatformServiceFactory.instance) { |
||||
|
const platform = process.env.VITE_PLATFORM || "web"; |
||||
|
PlatformServiceFactory.instance = createPlatformService(platform); |
||||
|
} |
||||
|
return PlatformServiceFactory.instance; |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 3.2 Platform-Specific Implementations |
||||
|
``` |
||||
|
services/platforms/ |
||||
|
├── WebPlatformService.ts |
||||
|
├── CapacitorPlatformService.ts |
||||
|
├── ElectronPlatformService.ts |
||||
|
└── PyWebViewPlatformService.ts |
||||
|
``` |
||||
|
|
||||
|
## 4. Feature Implementation Guidelines |
||||
|
|
||||
|
### 4.1 QR Code Scanning |
||||
|
|
||||
|
1. **Factory Pattern** |
||||
|
```typescript |
||||
|
export class QRScannerFactory { |
||||
|
static getInstance(): QRScannerService { |
||||
|
if (__IS_MOBILE__ || Capacitor.isNativePlatform()) { |
||||
|
return new CapacitorQRScanner(); |
||||
|
} else if (__USE_QR_READER__) { |
||||
|
return new WebDialogQRScanner(); |
||||
|
} |
||||
|
throw new Error("No QR scanner implementation available"); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
2. **Platform-Specific Implementation** |
||||
|
```typescript |
||||
|
// Example for Capacitor |
||||
|
export class CapacitorQRScanner implements QRScannerService { |
||||
|
async startScan(options?: QRScannerOptions): Promise<void> { |
||||
|
// Platform-specific implementation |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 4.2 Deep Linking |
||||
|
|
||||
|
1. **URL Structure** |
||||
|
```typescript |
||||
|
// Format: timesafari://<route>[/<param>][?queryParam1=value1] |
||||
|
interface DeepLinkParams { |
||||
|
route: string; |
||||
|
params?: Record<string, string>; |
||||
|
query?: Record<string, string>; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
2. **Platform Handlers** |
||||
|
```typescript |
||||
|
// Capacitor |
||||
|
App.addListener("appUrlOpen", handleDeepLink); |
||||
|
|
||||
|
// Web |
||||
|
router.beforeEach((to, from, next) => { |
||||
|
handleWebDeepLink(to.query); |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
## 5. Build Process |
||||
|
|
||||
|
### 5.1 Environment Configuration |
||||
|
```typescript |
||||
|
// vite.config.common.mts |
||||
|
export function createBuildConfig(mode: string) { |
||||
|
return { |
||||
|
define: { |
||||
|
'process.env.VITE_PLATFORM': JSON.stringify(mode), |
||||
|
'process.env.VITE_PWA_ENABLED': JSON.stringify(!isNative), |
||||
|
__IS_MOBILE__: JSON.stringify(isCapacitor), |
||||
|
__USE_QR_READER__: JSON.stringify(!isCapacitor) |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 5.2 Platform-Specific Builds |
||||
|
|
||||
|
```bash |
||||
|
# Build commands from package.json |
||||
|
"build:web": "vite build --config vite.config.web.mts", |
||||
|
"build:capacitor": "vite build --config vite.config.capacitor.mts", |
||||
|
"build:electron": "vite build --config vite.config.electron.mts", |
||||
|
"build:pywebview": "vite build --config vite.config.pywebview.mts" |
||||
|
``` |
||||
|
|
||||
|
## 6. Testing Strategy |
||||
|
|
||||
|
### 6.1 Test Configuration |
||||
|
```typescript |
||||
|
// playwright.config-local.ts |
||||
|
const config: PlaywrightTestConfig = { |
||||
|
projects: [ |
||||
|
{ |
||||
|
name: 'web', |
||||
|
use: { browserName: 'chromium' } |
||||
|
}, |
||||
|
{ |
||||
|
name: 'mobile', |
||||
|
use: { ...devices['Pixel 5'] } |
||||
|
} |
||||
|
] |
||||
|
}; |
||||
|
``` |
||||
|
|
||||
|
### 6.2 Platform-Specific Tests |
||||
|
```typescript |
||||
|
test('QR scanning works on mobile', async ({ page }) => { |
||||
|
test.skip(!process.env.MOBILE_TEST, 'Mobile-only test'); |
||||
|
// Test implementation |
||||
|
}); |
||||
|
``` |
||||
|
|
||||
|
## 7. Error Handling |
||||
|
|
||||
|
### 7.1 Global Error Handler |
||||
|
```typescript |
||||
|
function setupGlobalErrorHandler(app: VueApp) { |
||||
|
app.config.errorHandler = (err, instance, info) => { |
||||
|
logger.error("[App Error]", { |
||||
|
error: err, |
||||
|
info, |
||||
|
component: instance?.$options.name |
||||
|
}); |
||||
|
}; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 7.2 Platform-Specific Error Handling |
||||
|
```typescript |
||||
|
// API error handling for Capacitor |
||||
|
if (process.env.VITE_PLATFORM === 'capacitor') { |
||||
|
logger.error(`[Capacitor API Error] ${endpoint}:`, { |
||||
|
message: error.message, |
||||
|
status: error.response?.status |
||||
|
}); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 8. Best Practices |
||||
|
|
||||
|
### 8.1 Code Organization |
||||
|
- Use platform-specific directories for unique implementations |
||||
|
- Share common code through service interfaces |
||||
|
- Implement feature detection before using platform capabilities |
||||
|
|
||||
|
### 8.2 Platform Detection |
||||
|
```typescript |
||||
|
const platformService = PlatformServiceFactory.getInstance(); |
||||
|
const capabilities = platformService.getCapabilities(); |
||||
|
|
||||
|
if (capabilities.hasCamera) { |
||||
|
// Implement camera features |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 8.3 Feature Implementation |
||||
|
1. Define platform-agnostic interface |
||||
|
2. Create platform-specific implementations |
||||
|
3. Use factory pattern for instantiation |
||||
|
4. Implement graceful fallbacks |
||||
|
5. Add comprehensive error handling |
||||
|
|
||||
|
## 9. Dependency Management |
||||
|
|
||||
|
### 9.1 Platform-Specific Dependencies |
||||
|
```json |
||||
|
{ |
||||
|
"dependencies": { |
||||
|
"@capacitor/core": "^6.2.0", |
||||
|
"electron": "^33.2.1", |
||||
|
"vue-qrcode-reader": "^5.5.3" |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 9.2 Conditional Loading |
||||
|
```typescript |
||||
|
if (process.env.VITE_PLATFORM === 'capacitor') { |
||||
|
await import('@capacitor/core'); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 10. Security Considerations |
||||
|
|
||||
|
### 10.1 Permission Handling |
||||
|
```typescript |
||||
|
async checkPermissions(): Promise<boolean> { |
||||
|
if (platformService.isCapacitor()) { |
||||
|
return await checkNativePermissions(); |
||||
|
} |
||||
|
return await checkWebPermissions(); |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### 10.2 Data Storage |
||||
|
- Use platform-appropriate storage mechanisms |
||||
|
- Implement encryption for sensitive data |
||||
|
- Handle permissions appropriately |
||||
|
|
||||
|
This document should be updated as new features are added or platform-specific implementations change. Regular reviews ensure it remains current with the codebase. |
Loading…
Reference in new issue