Browse Source
- Add useDefineForClassFields for class field initialization - Remove test-playwright from includes - Add tsconfig.node.json reference - Remove redundant node_modules excludecross-platform-factory
7 changed files with 327 additions and 0 deletions
@ -0,0 +1,20 @@ |
|||
export interface PlatformService { |
|||
// File system operations
|
|||
readFile(path: string): Promise<string>; |
|||
writeFile(path: string, content: string): Promise<void>; |
|||
deleteFile(path: string): Promise<void>; |
|||
listFiles(directory: string): Promise<string[]>; |
|||
|
|||
// Camera operations
|
|||
takePicture(): Promise<string>; |
|||
pickImage(): Promise<string>; |
|||
|
|||
// Platform specific features
|
|||
isCapacitor(): boolean; |
|||
isElectron(): boolean; |
|||
isPyWebView(): boolean; |
|||
isWeb(): boolean; |
|||
|
|||
// Deep linking
|
|||
handleDeepLink(url: string): Promise<void>; |
|||
} |
@ -0,0 +1,36 @@ |
|||
import { Capacitor } from "@capacitor/core"; |
|||
import { PlatformService } from "./PlatformService"; |
|||
import { WebPlatformService } from "./platforms/WebPlatformService"; |
|||
import { CapacitorPlatformService } from "./platforms/CapacitorPlatformService"; |
|||
import { ElectronPlatformService } from "./platforms/ElectronPlatformService"; |
|||
import { PyWebViewPlatformService } from "./platforms/PyWebViewPlatformService"; |
|||
|
|||
export class PlatformServiceFactory { |
|||
private static instance: PlatformService | null = null; |
|||
|
|||
public static getInstance(): PlatformService { |
|||
if (PlatformServiceFactory.instance) { |
|||
return PlatformServiceFactory.instance; |
|||
} |
|||
|
|||
const platform = process.env.VITE_PLATFORM || "web"; |
|||
|
|||
switch (platform) { |
|||
case "capacitor": |
|||
PlatformServiceFactory.instance = new CapacitorPlatformService(); |
|||
break; |
|||
case "electron": |
|||
PlatformServiceFactory.instance = new ElectronPlatformService(); |
|||
break; |
|||
case "pywebview": |
|||
PlatformServiceFactory.instance = new PyWebViewPlatformService(); |
|||
break; |
|||
case "web": |
|||
default: |
|||
PlatformServiceFactory.instance = new WebPlatformService(); |
|||
break; |
|||
} |
|||
|
|||
return PlatformServiceFactory.instance; |
|||
} |
|||
} |
@ -0,0 +1,80 @@ |
|||
import { PlatformService } from "../PlatformService"; |
|||
import { Capacitor } from "@capacitor/core"; |
|||
import { Filesystem, Directory } from "@capacitor/filesystem"; |
|||
import { Camera, CameraResultType, CameraSource } from "@capacitor/camera"; |
|||
import { App } from "@capacitor/app"; |
|||
|
|||
export class CapacitorPlatformService implements PlatformService { |
|||
async readFile(path: string): Promise<string> { |
|||
const file = await Filesystem.readFile({ |
|||
path, |
|||
directory: Directory.Data, |
|||
}); |
|||
return file.data; |
|||
} |
|||
|
|||
async writeFile(path: string, content: string): Promise<void> { |
|||
await Filesystem.writeFile({ |
|||
path, |
|||
data: content, |
|||
directory: Directory.Data, |
|||
}); |
|||
} |
|||
|
|||
async deleteFile(path: string): Promise<void> { |
|||
await Filesystem.deleteFile({ |
|||
path, |
|||
directory: Directory.Data, |
|||
}); |
|||
} |
|||
|
|||
async listFiles(directory: string): Promise<string[]> { |
|||
const result = await Filesystem.readdir({ |
|||
path: directory, |
|||
directory: Directory.Data, |
|||
}); |
|||
return result.files; |
|||
} |
|||
|
|||
async takePicture(): Promise<string> { |
|||
const image = await Camera.getPhoto({ |
|||
quality: 90, |
|||
allowEditing: true, |
|||
resultType: CameraResultType.Uri, |
|||
source: CameraSource.Camera, |
|||
}); |
|||
return image.webPath || ""; |
|||
} |
|||
|
|||
async pickImage(): Promise<string> { |
|||
const image = await Camera.getPhoto({ |
|||
quality: 90, |
|||
allowEditing: true, |
|||
resultType: CameraResultType.Uri, |
|||
source: CameraSource.Photos, |
|||
}); |
|||
return image.webPath || ""; |
|||
} |
|||
|
|||
isCapacitor(): boolean { |
|||
return true; |
|||
} |
|||
|
|||
isElectron(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isPyWebView(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isWeb(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
async handleDeepLink(url: string): Promise<void> { |
|||
// Capacitor handles deep links automatically
|
|||
// This is just a placeholder for the interface
|
|||
return Promise.resolve(); |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
import { PlatformService } from '../PlatformService'; |
|||
|
|||
export class ElectronPlatformService implements PlatformService { |
|||
async readFile(path: string): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async writeFile(path: string, content: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async deleteFile(path: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async listFiles(directory: string): Promise<string[]> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async takePicture(): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async pickImage(): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
isCapacitor(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isElectron(): boolean { |
|||
return true; |
|||
} |
|||
|
|||
isPyWebView(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isWeb(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
async handleDeepLink(url: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
import { PlatformService } from '../PlatformService'; |
|||
|
|||
export class PyWebViewPlatformService implements PlatformService { |
|||
async readFile(path: string): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async writeFile(path: string, content: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async deleteFile(path: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async listFiles(directory: string): Promise<string[]> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async takePicture(): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
async pickImage(): Promise<string> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
|
|||
isCapacitor(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isElectron(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isPyWebView(): boolean { |
|||
return true; |
|||
} |
|||
|
|||
isWeb(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
async handleDeepLink(url: string): Promise<void> { |
|||
throw new Error('Not implemented'); |
|||
} |
|||
} |
@ -0,0 +1,87 @@ |
|||
import { PlatformService } from "../PlatformService"; |
|||
|
|||
export class WebPlatformService implements PlatformService { |
|||
async readFile(path: string): Promise<string> { |
|||
throw new Error("File system access not available in web platform"); |
|||
} |
|||
|
|||
async writeFile(path: string, content: string): Promise<void> { |
|||
throw new Error("File system access not available in web platform"); |
|||
} |
|||
|
|||
async deleteFile(path: string): Promise<void> { |
|||
throw new Error("File system access not available in web platform"); |
|||
} |
|||
|
|||
async listFiles(directory: string): Promise<string[]> { |
|||
throw new Error("File system access not available in web platform"); |
|||
} |
|||
|
|||
async takePicture(): Promise<string> { |
|||
return new Promise((resolve, reject) => { |
|||
const input = document.createElement("input"); |
|||
input.type = "file"; |
|||
input.accept = "image/*"; |
|||
input.capture = "environment"; |
|||
|
|||
input.onchange = (e) => { |
|||
const file = (e.target as HTMLInputElement).files?.[0]; |
|||
if (file) { |
|||
const reader = new FileReader(); |
|||
reader.onload = (event) => { |
|||
resolve(event.target?.result as string); |
|||
}; |
|||
reader.readAsDataURL(file); |
|||
} else { |
|||
reject(new Error("No file selected")); |
|||
} |
|||
}; |
|||
|
|||
input.click(); |
|||
}); |
|||
} |
|||
|
|||
async pickImage(): Promise<string> { |
|||
return new Promise((resolve, reject) => { |
|||
const input = document.createElement("input"); |
|||
input.type = "file"; |
|||
input.accept = "image/*"; |
|||
|
|||
input.onchange = (e) => { |
|||
const file = (e.target as HTMLInputElement).files?.[0]; |
|||
if (file) { |
|||
const reader = new FileReader(); |
|||
reader.onload = (event) => { |
|||
resolve(event.target?.result as string); |
|||
}; |
|||
reader.readAsDataURL(file); |
|||
} else { |
|||
reject(new Error("No file selected")); |
|||
} |
|||
}; |
|||
|
|||
input.click(); |
|||
}); |
|||
} |
|||
|
|||
isCapacitor(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isElectron(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isPyWebView(): boolean { |
|||
return false; |
|||
} |
|||
|
|||
isWeb(): boolean { |
|||
return true; |
|||
} |
|||
|
|||
async handleDeepLink(url: string): Promise<void> { |
|||
// Web platform can handle deep links through URL parameters
|
|||
return Promise.resolve(); |
|||
} |
|||
} |
@ -0,0 +1,10 @@ |
|||
{ |
|||
"compilerOptions": { |
|||
"composite": true, |
|||
"skipLibCheck": true, |
|||
"module": "ESNext", |
|||
"moduleResolution": "bundler", |
|||
"allowSyntheticDefaultImports": true |
|||
}, |
|||
"include": ["vite.config.*"] |
|||
} |
Loading…
Reference in new issue