import { PlatformService } from "./PlatformService"; import { WebPlatformService } from "./platforms/WebPlatformService"; import { CapacitorPlatformService } from "./platforms/CapacitorPlatformService"; import { logger } from "../utils/logger"; /** * Factory class for creating platform-specific service implementations. * Implements the Singleton pattern to ensure only one instance of PlatformService exists. * * The factory determines which platform implementation to use based on the VITE_PLATFORM * environment variable. Supported platforms are: * - capacitor: Mobile platform using Capacitor * - electron: Desktop platform using Electron with Capacitor * - web: Default web platform (fallback) * * @example * ```typescript * const platformService = PlatformServiceFactory.getInstance(); * await platformService.takePicture(); * ``` */ export class PlatformServiceFactory { private static instance: PlatformService | null = null; private static callCount = 0; // Debug counter private static creationLogged = false; // Only log creation once /** * Gets or creates the singleton instance of PlatformService. * Creates the appropriate platform-specific implementation based on environment. * * @returns {PlatformService} The singleton instance of PlatformService */ public static getInstance(): PlatformService { PlatformServiceFactory.callCount++; if (PlatformServiceFactory.instance) { // Normal case - return existing instance silently return PlatformServiceFactory.instance; } // Only log when actually creating the instance const platform = process.env.VITE_PLATFORM || "web"; if (!PlatformServiceFactory.creationLogged) { logger.log( `[PlatformServiceFactory] Creating singleton instance for platform: ${platform}`, ); PlatformServiceFactory.creationLogged = true; } switch (platform) { case "capacitor": PlatformServiceFactory.instance = new CapacitorPlatformService(); break; case "electron": // Use a specialized electron service that extends CapacitorPlatformService PlatformServiceFactory.instance = new ElectronPlatformService(); break; case "web": default: PlatformServiceFactory.instance = new WebPlatformService(); break; } return PlatformServiceFactory.instance; } /** * Debug method to check singleton usage stats */ public static getStats(): { callCount: number; instanceExists: boolean } { return { callCount: PlatformServiceFactory.callCount, instanceExists: PlatformServiceFactory.instance !== null, }; } } /** * Electron-specific platform service implementation. * Extends CapacitorPlatformService with electron-specific overrides. * * This service handles the unique requirements of the Electron platform: * - Desktop-specific capabilities * - Electron-specific file system access * - Desktop UI patterns * - Native desktop integration */ class ElectronPlatformService extends CapacitorPlatformService { /** * Gets the capabilities of the Electron platform * Overrides the mobile-focused capabilities from CapacitorPlatformService * @returns Platform capabilities object specific to Electron */ getCapabilities() { return { hasFileSystem: true, hasCamera: false, // Desktop typically doesn't have integrated cameras for our use case isMobile: false, // Electron is desktop, not mobile isIOS: false, hasFileDownload: true, // Desktop supports direct file downloads needsFileHandlingInstructions: false, // Desktop users are familiar with file handling isNativeApp: true, // Electron is a native app }; } /** * Checks if running on Electron platform. * @returns true, as this is the Electron implementation */ isElectron(): boolean { return true; } /** * Checks if running on Capacitor platform. * @returns false, as this is Electron, not pure Capacitor */ isCapacitor(): boolean { return false; } /** * Checks if running on web platform. * @returns false, as this is not web */ isWeb(): boolean { return false; } }