You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							187 lines
						
					
					
						
							6.0 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							187 lines
						
					
					
						
							6.0 KiB
						
					
					
				
								/**
							 | 
						|
								 * @file Capacitor Main Entry Point
							 | 
						|
								 * @author Matthew Raymer
							 | 
						|
								 *
							 | 
						|
								 * This file initializes the deep linking system for the TimeSafari app.
							 | 
						|
								 * It sets up the connection between Capacitor's URL handling and our deep link processor.
							 | 
						|
								 *
							 | 
						|
								 * Deep Linking Flow:
							 | 
						|
								 * 1. Capacitor receives URL open event
							 | 
						|
								 * 2. Event is passed to DeepLinkHandler
							 | 
						|
								 * 3. URL is validated and processed
							 | 
						|
								 * 4. Router navigates to appropriate view
							 | 
						|
								 *
							 | 
						|
								 * Integration Points:
							 | 
						|
								 * - Capacitor App plugin for URL handling
							 | 
						|
								 * - Vue Router for navigation
							 | 
						|
								 * - Error handling system
							 | 
						|
								 * - Logging system
							 | 
						|
								 *
							 | 
						|
								 * Type Safety:
							 | 
						|
								 * - Uses DeepLinkHandler for type-safe parameter processing
							 | 
						|
								 * - Ensures type safety between Capacitor events and app routing
							 | 
						|
								 * - Maintains type checking through the entire deep link flow
							 | 
						|
								 *
							 | 
						|
								 * @example
							 | 
						|
								 * // URL open event from OS
							 | 
						|
								 * timesafari://claim/123?view=details
							 | 
						|
								 * // Processed and routed to appropriate view with type-safe parameters
							 | 
						|
								 */
							 | 
						|
								
							 | 
						|
								import { initializeApp } from "./main.common";
							 | 
						|
								import { App as CapacitorApp } from "@capacitor/app";
							 | 
						|
								import router from "./router";
							 | 
						|
								import { handleApiError } from "./services/api";
							 | 
						|
								import { AxiosError } from "axios";
							 | 
						|
								import { DeepLinkHandler } from "./services/deepLinks";
							 | 
						|
								import { logger, safeStringify } from "./utils/logger";
							 | 
						|
								import "./utils/safeAreaInset";
							 | 
						|
								
							 | 
						|
								logger.log("[Capacitor] 🚀 Starting initialization");
							 | 
						|
								logger.log("[Capacitor] Platform:", process.env.VITE_PLATFORM);
							 | 
						|
								
							 | 
						|
								const app = initializeApp();
							 | 
						|
								
							 | 
						|
								// Initialize API error handling for unhandled promise rejections
							 | 
						|
								window.addEventListener("unhandledrejection", (event) => {
							 | 
						|
								  if (event.reason?.response) {
							 | 
						|
								    handleApiError(event.reason, event.reason.config?.url || "unknown");
							 | 
						|
								  }
							 | 
						|
								});
							 | 
						|
								
							 | 
						|
								const deepLinkHandler = new DeepLinkHandler(router);
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * Handles deep link routing for the application
							 | 
						|
								 * Processes URLs in the format timesafari://<route>/<param>
							 | 
						|
								 * Maps incoming deep links to corresponding router paths with parameters
							 | 
						|
								 *
							 | 
						|
								 * @param {Object} data - Deep link data object
							 | 
						|
								 * @param {string} data.url - The full deep link URL to process
							 | 
						|
								 * @returns {Promise<void>}
							 | 
						|
								 *
							 | 
						|
								 * @example
							 | 
						|
								 * // Handles URLs like:
							 | 
						|
								 * // timesafari://claim/01JMAAFZRNSRTQ0EBSD70A8E1H
							 | 
						|
								 * // timesafari://project/abc123
							 | 
						|
								 *
							 | 
						|
								 * @throws {Error} If URL format is invalid
							 | 
						|
								 */
							 | 
						|
								const handleDeepLink = async (data: { url: string }) => {
							 | 
						|
								  const { url } = data;
							 | 
						|
								  logger.debug(`[Main] 🌐 Deeplink received from Capacitor: ${url}`);
							 | 
						|
								
							 | 
						|
								  try {
							 | 
						|
								    // Wait for router to be ready
							 | 
						|
								    logger.debug(`[Main] ⏳ Waiting for router to be ready...`);
							 | 
						|
								    await router.isReady();
							 | 
						|
								    logger.debug(`[Main] ✅ Router is ready, processing deeplink`);
							 | 
						|
								
							 | 
						|
								    // Process the deeplink
							 | 
						|
								    logger.debug(`[Main] 🚀 Starting deeplink processing`);
							 | 
						|
								    await deepLinkHandler.handleDeepLink(url);
							 | 
						|
								    logger.debug(`[Main] ✅ Deeplink processed successfully`);
							 | 
						|
								  } catch (error) {
							 | 
						|
								    logger.error(`[Main] ❌ Deeplink processing failed:`, {
							 | 
						|
								      url,
							 | 
						|
								      error: error instanceof Error ? error.message : String(error),
							 | 
						|
								      stack: error instanceof Error ? error.stack : undefined,
							 | 
						|
								      timestamp: new Date().toISOString(),
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    // Log additional context for debugging
							 | 
						|
								    logger.error(`[Main] 🔍 Debug context:`, {
							 | 
						|
								      routerReady: router.isReady(),
							 | 
						|
								      currentRoute: router.currentRoute.value,
							 | 
						|
								      appMounted: app._instance?.isMounted,
							 | 
						|
								      timestamp: new Date().toISOString(),
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    // Fallback to original error handling
							 | 
						|
								    let message: string =
							 | 
						|
								      error instanceof Error ? error.message : safeStringify(error);
							 | 
						|
								    if (url) {
							 | 
						|
								      message += `\nURL: ${url}`;
							 | 
						|
								    }
							 | 
						|
								    handleApiError({ message } as AxiosError, "deep-link");
							 | 
						|
								  }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								// Function to register the deeplink listener
							 | 
						|
								const registerDeepLinkListener = async () => {
							 | 
						|
								  try {
							 | 
						|
								    logger.info(
							 | 
						|
								      `[Main] 🔗 Attempting to register deeplink handler with Capacitor`,
							 | 
						|
								    );
							 | 
						|
								
							 | 
						|
								    // Check if Capacitor App plugin is available
							 | 
						|
								    logger.debug(`[Main] 🔍 Checking Capacitor App plugin availability...`);
							 | 
						|
								    if (!CapacitorApp) {
							 | 
						|
								      throw new Error("Capacitor App plugin not available");
							 | 
						|
								    }
							 | 
						|
								    logger.info(`[Main] ✅ Capacitor App plugin is available`);
							 | 
						|
								
							 | 
						|
								    // Check available methods on CapacitorApp
							 | 
						|
								    logger.debug(
							 | 
						|
								      `[Main] 🔍 Capacitor App plugin methods:`,
							 | 
						|
								      Object.getOwnPropertyNames(CapacitorApp),
							 | 
						|
								    );
							 | 
						|
								    logger.debug(
							 | 
						|
								      `[Main] 🔍 Capacitor App plugin addListener method:`,
							 | 
						|
								      typeof CapacitorApp.addListener,
							 | 
						|
								    );
							 | 
						|
								
							 | 
						|
								    // Wait for router to be ready first
							 | 
						|
								    await router.isReady();
							 | 
						|
								    logger.debug(
							 | 
						|
								      `[Main] ✅ Router is ready, proceeding with listener registration`,
							 | 
						|
								    );
							 | 
						|
								
							 | 
						|
								    // Try to register the listener
							 | 
						|
								    logger.info(`[Main] 🧪 Attempting to register appUrlOpen listener...`);
							 | 
						|
								    const listenerHandle = await CapacitorApp.addListener(
							 | 
						|
								      "appUrlOpen",
							 | 
						|
								      handleDeepLink,
							 | 
						|
								    );
							 | 
						|
								    logger.info(
							 | 
						|
								      `[Main] ✅ appUrlOpen listener registered successfully with handle:`,
							 | 
						|
								      listenerHandle,
							 | 
						|
								    );
							 | 
						|
								
							 | 
						|
								    return listenerHandle;
							 | 
						|
								  } catch (error) {
							 | 
						|
								    logger.error(`[Main] ❌ Failed to register deeplink listener:`, {
							 | 
						|
								      error: error instanceof Error ? error.message : String(error),
							 | 
						|
								      stack: error instanceof Error ? error.stack : undefined,
							 | 
						|
								      timestamp: new Date().toISOString(),
							 | 
						|
								    });
							 | 
						|
								    throw error;
							 | 
						|
								  }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								logger.log("[Capacitor] 🚀 Mounting app");
							 | 
						|
								app.mount("#app");
							 | 
						|
								logger.info(`[Main] ✅ App mounted successfully`);
							 | 
						|
								
							 | 
						|
								// Register deeplink listener after app is mounted
							 | 
						|
								setTimeout(async () => {
							 | 
						|
								  try {
							 | 
						|
								    logger.info(
							 | 
						|
								      `[Main] ⏳ Delaying listener registration to ensure Capacitor is ready...`,
							 | 
						|
								    );
							 | 
						|
								    await registerDeepLinkListener();
							 | 
						|
								    logger.info(`[Main] 🎉 Deep link system fully initialized!`);
							 | 
						|
								  } catch (error) {
							 | 
						|
								    logger.error(`[Main] ❌ Deep link system initialization failed:`, error);
							 | 
						|
								  }
							 | 
						|
								}, 2000); // 2 second delay to ensure Capacitor is fully ready
							 | 
						|
								
							 | 
						|
								// Log app initialization status
							 | 
						|
								setTimeout(() => {
							 | 
						|
								  logger.info(`[Main] 📊 App initialization status:`, {
							 | 
						|
								    routerReady: router.isReady(),
							 | 
						|
								    currentRoute: router.currentRoute.value,
							 | 
						|
								    appMounted: app._instance?.isMounted,
							 | 
						|
								    timestamp: new Date().toISOString(),
							 | 
						|
								  });
							 | 
						|
								}, 1000);
							 | 
						|
								
							 |