From c850c3ba46521a6e5c21e8678e4e55442113e3c3 Mon Sep 17 00:00:00 2001 From: Merul Dhiman Date: Tue, 12 Aug 2025 11:59:04 +0530 Subject: [PATCH 1/2] fix: ios drawer fix --- .../src/routes/(app)/scan-qr/+page.svelte | 39 +++++++++++-------- .../src/components/login/login-main.tsx | 1 + pnpm-lock.yaml | 20 +++++++++- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte b/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte index 89ef3601..571bc293 100644 --- a/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte +++ b/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte @@ -499,23 +499,30 @@ - - - - - - - -

- Point the camera at the code -

+ + + + + + + +

+ Point the camera at the code +

+ = 6'} @@ -23539,7 +23543,7 @@ snapshots: pino-loki@2.6.0: dependencies: pino-abstract-transport: 2.0.0 - pump: 3.0.3 + pump: 3.0.2 pino-std-serializers@7.0.0: {} @@ -23557,6 +23561,20 @@ snapshots: sonic-boom: 4.2.0 thread-stream: 3.1.0 + pino@9.8.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 5.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pirates@4.0.7: {} pkg-dir@4.2.0: From 23241df729763c096e55f5f327e4595ca7b6912a Mon Sep 17 00:00:00 2001 From: Merul Dhiman Date: Tue, 12 Aug 2025 12:00:00 +0530 Subject: [PATCH 2/2] chore: format --- .../src/lib/services/evaultService.ts | 20 +- .../src/routes/api/evaults/+server.ts | 79 +- .../[namespace]/[pod]/details/+server.ts | 14 +- .../evaults/[namespace]/[pod]/logs/+server.ts | 13 +- .../[namespace]/[pod]/metrics/+server.ts | 99 ++- .../monitoring/[namespace]/[service]/+page.ts | 2 +- .../src/routes/(app)/+layout.svelte | 71 +- .../src/routes/(app)/scan-qr/+page.svelte | 811 +++++++++--------- .../src/routes/(app)/sign/+page.svelte | 215 +++-- .../src/routes/(auth)/login/+page.svelte | 268 +++--- .../eid-wallet/src/routes/+layout.svelte | 510 ++++++----- .../src/components/login/login-main.tsx | 2 +- .../blabsy/src/lib/utils/mobile-detection.ts | 15 +- .../fragments/ActionMenu/ActionMenu.svelte | 2 +- .../src/routes/(auth)/auth/+page.svelte | 54 +- 15 files changed, 1105 insertions(+), 1070 deletions(-) diff --git a/infrastructure/control-panel/src/lib/services/evaultService.ts b/infrastructure/control-panel/src/lib/services/evaultService.ts index e9455f1f..8e0b2961 100644 --- a/infrastructure/control-panel/src/lib/services/evaultService.ts +++ b/infrastructure/control-panel/src/lib/services/evaultService.ts @@ -15,9 +15,15 @@ export class EVaultService { } } - static async getEVaultLogs(namespace: string, podName: string, tail: number = 100): Promise { + static async getEVaultLogs( + namespace: string, + podName: string, + tail: number = 100 + ): Promise { try { - const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/logs?tail=${tail}`); + const response = await fetch( + `/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/logs?tail=${tail}` + ); if (!response.ok) { throw new Error('Failed to fetch logs'); } @@ -31,7 +37,9 @@ export class EVaultService { static async getEVaultDetails(namespace: string, podName: string): Promise { try { - const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/details`); + const response = await fetch( + `/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/details` + ); if (!response.ok) { throw new Error('Failed to fetch eVault details'); } @@ -44,7 +52,9 @@ export class EVaultService { static async getEVaultMetrics(namespace: string, podName: string): Promise { try { - const response = await fetch(`/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics`); + const response = await fetch( + `/api/evaults/${encodeURIComponent(namespace)}/${encodeURIComponent(podName)}/metrics` + ); if (!response.ok) { throw new Error('Failed to fetch metrics'); } @@ -54,4 +64,4 @@ export class EVaultService { return null; } } -} \ No newline at end of file +} diff --git a/infrastructure/control-panel/src/routes/api/evaults/+server.ts b/infrastructure/control-panel/src/routes/api/evaults/+server.ts index 5e058744..126983e8 100644 --- a/infrastructure/control-panel/src/routes/api/evaults/+server.ts +++ b/infrastructure/control-panel/src/routes/api/evaults/+server.ts @@ -26,54 +26,60 @@ export const GET: RequestHandler = async () => { // Get minikube IP for NodePort services let minikubeIP = 'localhost'; try { - const { stdout: minikubeIPOutput } = await execAsync('minikube ip 2>/dev/null || echo "localhost"'); + const { stdout: minikubeIPOutput } = await execAsync( + 'minikube ip 2>/dev/null || echo "localhost"' + ); if (minikubeIPOutput.trim()) { minikubeIP = minikubeIPOutput.trim(); } } catch (ipError) { console.log('Could not get minikube IP, using localhost'); } - + console.log('Using IP:', minikubeIP); - + // Get all namespaces const { stdout: namespacesOutput } = await execAsync('kubectl get namespaces -o json'); const namespaces = JSON.parse(namespacesOutput); - + // Filter for eVault namespaces const evaultNamespaces = namespaces.items .filter((ns: any) => ns.metadata.name.startsWith('evault-')) .map((ns: any) => ns.metadata.name); - + console.log('Found eVault namespaces:', evaultNamespaces); - + let allEVaults: EVault[] = []; // Get services and pods from each eVault namespace for (const namespace of evaultNamespaces) { try { // Get services in this namespace as JSON - const { stdout: servicesOutput } = await execAsync(`kubectl get services -n ${namespace} -o json`); + const { stdout: servicesOutput } = await execAsync( + `kubectl get services -n ${namespace} -o json` + ); const services = JSON.parse(servicesOutput); - + // Get pods in this namespace as JSON - const { stdout: podsOutput } = await execAsync(`kubectl get pods -n ${namespace} -o json`); + const { stdout: podsOutput } = await execAsync( + `kubectl get pods -n ${namespace} -o json` + ); const pods = JSON.parse(podsOutput); - + console.log(`=== SERVICES FOR ${namespace} ===`); console.log(JSON.stringify(services, null, 2)); console.log(`=== PODS FOR ${namespace} ===`); console.log(JSON.stringify(pods, null, 2)); console.log(`=== END DATA ===`); - + if (services.items && services.items.length > 0) { for (const service of services.items) { const serviceName = service.metadata.name; const serviceType = service.spec.type; const ports = service.spec.ports; - + console.log(`Service: ${serviceName}, Type: ${serviceType}, Ports:`, ports); - + // Find NodePort for NodePort services let nodePort = null; if (serviceType === 'NodePort' && ports) { @@ -84,9 +90,9 @@ export const GET: RequestHandler = async () => { } } } - + console.log(`NodePort: ${nodePort}`); - + // Get pod data for this service let podData = { status: 'Unknown', @@ -98,28 +104,39 @@ export const GET: RequestHandler = async () => { node: 'N/A', podName: 'N/A' }; - + if (pods.items && pods.items.length > 0) { // Find pod that matches this service (usually same name or has service label) - const matchingPod = pods.items.find((pod: any) => - pod.metadata.name.includes(serviceName.replace('-service', '')) || - pod.metadata.labels?.app === 'evault' + const matchingPod = pods.items.find( + (pod: any) => + pod.metadata.name.includes( + serviceName.replace('-service', '') + ) || pod.metadata.labels?.app === 'evault' ); - + if (matchingPod) { const pod = matchingPod; - const readyCount = pod.status.containerStatuses?.filter((cs: any) => cs.ready).length || 0; + const readyCount = + pod.status.containerStatuses?.filter((cs: any) => cs.ready) + .length || 0; const totalCount = pod.status.containerStatuses?.length || 0; - const restarts = pod.status.containerStatuses?.reduce((sum: number, cs: any) => sum + (cs.restartCount || 0), 0) || 0; - + const restarts = + pod.status.containerStatuses?.reduce( + (sum: number, cs: any) => sum + (cs.restartCount || 0), + 0 + ) || 0; + // Calculate age const creationTime = new Date(pod.metadata.creationTimestamp); const now = new Date(); const ageMs = now.getTime() - creationTime.getTime(); const ageDays = Math.floor(ageMs / (1000 * 60 * 60 * 24)); - const ageHours = Math.floor((ageMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const age = ageDays > 0 ? `${ageDays}d${ageHours}h` : `${ageHours}h`; - + const ageHours = Math.floor( + (ageMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60) + ); + const age = + ageDays > 0 ? `${ageDays}d${ageHours}h` : `${ageHours}h`; + podData = { status: pod.status.phase || 'Unknown', age: age, @@ -132,18 +149,18 @@ export const GET: RequestHandler = async () => { }; } } - + // Extract the eVault ID from the namespace const evaultId = namespace.replace('evault-', ''); - + // Generate service URL let serviceUrl = ''; if (nodePort) { serviceUrl = `http://${minikubeIP}:${nodePort}`; } - + console.log(`Service URL: ${serviceUrl}`); - + allEVaults.push({ id: serviceName, name: serviceName, @@ -172,4 +189,4 @@ export const GET: RequestHandler = async () => { console.error('Error fetching eVaults:', error); return json({ error: 'Failed to fetch eVaults', evaults: [] }, { status: 500 }); } -}; \ No newline at end of file +}; diff --git a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/details/+server.ts b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/details/+server.ts index 27bd353c..ceb226ec 100644 --- a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/details/+server.ts +++ b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/details/+server.ts @@ -11,14 +11,18 @@ export const GET: RequestHandler = async ({ params }) => { try { // Get detailed pod information const { stdout: podInfo } = await execAsync(`kubectl describe pod -n ${namespace} ${pod}`); - + // Get pod YAML - const { stdout: podYaml } = await execAsync(`kubectl get pod -n ${namespace} ${pod} -o yaml`); - + const { stdout: podYaml } = await execAsync( + `kubectl get pod -n ${namespace} ${pod} -o yaml` + ); + // Get pod metrics if available let metrics = null; try { - const { stdout: metricsOutput } = await execAsync(`kubectl top pod -n ${namespace} ${pod}`); + const { stdout: metricsOutput } = await execAsync( + `kubectl top pod -n ${namespace} ${pod}` + ); metrics = metricsOutput.trim(); } catch (metricsError) { // Metrics might not be available @@ -34,4 +38,4 @@ export const GET: RequestHandler = async ({ params }) => { console.error('Error fetching pod details:', error); return json({ error: 'Failed to fetch pod details' }, { status: 500 }); } -}; \ No newline at end of file +}; diff --git a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/logs/+server.ts b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/logs/+server.ts index 73502994..624376aa 100644 --- a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/logs/+server.ts +++ b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/logs/+server.ts @@ -10,12 +10,17 @@ export const GET: RequestHandler = async ({ params, url }) => { const tail = url.searchParams.get('tail') || '100'; try { - const { stdout } = await execAsync(`kubectl logs -n ${namespace} ${pod} -c evault --tail=${tail}`); - const logs = stdout.trim().split('\n').filter(line => line.trim()); - + const { stdout } = await execAsync( + `kubectl logs -n ${namespace} ${pod} -c evault --tail=${tail}` + ); + const logs = stdout + .trim() + .split('\n') + .filter((line) => line.trim()); + return json({ logs }); } catch (error) { console.error('Error fetching logs:', error); return json({ error: 'Failed to fetch logs', logs: [] }, { status: 500 }); } -}; \ No newline at end of file +}; diff --git a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/metrics/+server.ts b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/metrics/+server.ts index 29a605f9..431f3643 100644 --- a/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/metrics/+server.ts +++ b/infrastructure/control-panel/src/routes/api/evaults/[namespace]/[pod]/metrics/+server.ts @@ -7,7 +7,7 @@ const execAsync = promisify(exec); export const GET: RequestHandler = async ({ params }) => { const { namespace, pod } = params; - + console.log('Metrics API called with namespace:', namespace, 'pod:', pod); try { @@ -22,23 +22,34 @@ export const GET: RequestHandler = async ({ params }) => { topOutput = 'No metrics available'; } console.log('kubectl top pod output:', topOutput); - + // Get pod status details console.log('Running kubectl describe pod...'); - const { stdout: describeOutput } = await execAsync(`kubectl describe pod ${pod} -n ${namespace} 2>/dev/null || echo "No pod details available"`); + const { stdout: describeOutput } = await execAsync( + `kubectl describe pod ${pod} -n ${namespace} 2>/dev/null || echo "No pod details available"` + ); console.log('kubectl describe pod output length:', describeOutput?.length || 0); - + // Get container logs count (last 100 lines) console.log('Running kubectl logs...'); - const { stdout: logsOutput } = await execAsync(`kubectl logs -n ${namespace} ${pod} -c evault --tail=100 2>/dev/null || echo ""`); + const { stdout: logsOutput } = await execAsync( + `kubectl logs -n ${namespace} ${pod} -c evault --tail=100 2>/dev/null || echo ""` + ); console.log('kubectl logs output length:', logsOutput?.length || 0); - - const logLines = logsOutput.trim().split('\n').filter(line => line.trim()); - + + const logLines = logsOutput + .trim() + .split('\n') + .filter((line) => line.trim()); + // Parse top output for CPU and Memory let cpu = 'N/A'; let memory = 'N/A'; - if (topOutput && !topOutput.includes('No metrics available') && !topOutput.includes('Metrics API not available')) { + if ( + topOutput && + !topOutput.includes('No metrics available') && + !topOutput.includes('Metrics API not available') + ) { console.log('Parsing top output...'); const lines = topOutput.trim().split('\n'); console.log('Top output lines:', lines); @@ -54,18 +65,18 @@ export const GET: RequestHandler = async ({ params }) => { } } } - + console.log('Final CPU:', cpu, 'Memory:', memory); - + // Parse describe output for events and conditions const events: string[] = []; const conditions: string[] = []; - + if (describeOutput && !describeOutput.includes('No pod details available')) { const lines = describeOutput.split('\n'); let inEvents = false; let inConditions = false; - + for (const line of lines) { if (line.includes('Events:')) { inEvents = true; @@ -82,7 +93,7 @@ export const GET: RequestHandler = async ({ params }) => { inConditions = false; continue; } - + if (inEvents && line.trim() && !line.startsWith(' ')) { // Handle case where Events shows "" if (line.trim() === '') { @@ -96,37 +107,45 @@ export const GET: RequestHandler = async ({ params }) => { } } } - + // Calculate basic stats const totalLogLines = logLines.length; - const errorLogs = logLines.filter(line => - line.toLowerCase().includes('error') || - line.toLowerCase().includes('fail') || - line.toLowerCase().includes('exception') + const errorLogs = logLines.filter( + (line) => + line.toLowerCase().includes('error') || + line.toLowerCase().includes('fail') || + line.toLowerCase().includes('exception') ).length; - const warningLogs = logLines.filter(line => - line.toLowerCase().includes('warn') || - line.toLowerCase().includes('warning') + const warningLogs = logLines.filter( + (line) => line.toLowerCase().includes('warn') || line.toLowerCase().includes('warning') ).length; - + // Get additional pod info for alternative metrics let podAge = 'N/A'; let podStatus = 'Unknown'; try { - const { stdout: getPodOutput } = await execAsync(`kubectl get pod ${pod} -n ${namespace} -o json`); + const { stdout: getPodOutput } = await execAsync( + `kubectl get pod ${pod} -n ${namespace} -o json` + ); const podInfo = JSON.parse(getPodOutput); - podAge = podInfo.metadata?.creationTimestamp ? - Math.floor((Date.now() - new Date(podInfo.metadata.creationTimestamp).getTime()) / (1000 * 60 * 60 * 24)) + 'd' : 'N/A'; + podAge = podInfo.metadata?.creationTimestamp + ? Math.floor( + (Date.now() - new Date(podInfo.metadata.creationTimestamp).getTime()) / + (1000 * 60 * 60 * 24) + ) + 'd' + : 'N/A'; podStatus = podInfo.status?.phase || 'Unknown'; } catch (podError) { console.log('Failed to get pod info:', podError); } - + const metrics = { resources: { cpu, memory, - note: topOutput.includes('Metrics API not available') ? 'Metrics server not enabled' : undefined + note: topOutput.includes('Metrics API not available') + ? 'Metrics server not enabled' + : undefined }, logs: { totalLines: totalLogLines, @@ -141,15 +160,23 @@ export const GET: RequestHandler = async ({ params }) => { podStatus } }; - + return json(metrics); } catch (error) { console.error('Error fetching metrics:', error); - return json({ - error: 'Failed to fetch metrics', - resources: { cpu: 'N/A', memory: 'N/A' }, - logs: { totalLines: 0, errorCount: 0, warningCount: 0, lastUpdate: new Date().toISOString() }, - status: { events: [], conditions: [] } - }, { status: 500 }); + return json( + { + error: 'Failed to fetch metrics', + resources: { cpu: 'N/A', memory: 'N/A' }, + logs: { + totalLines: 0, + errorCount: 0, + warningCount: 0, + lastUpdate: new Date().toISOString() + }, + status: { events: [], conditions: [] } + }, + { status: 500 } + ); } -}; \ No newline at end of file +}; diff --git a/infrastructure/control-panel/src/routes/monitoring/[namespace]/[service]/+page.ts b/infrastructure/control-panel/src/routes/monitoring/[namespace]/[service]/+page.ts index 74c868ca..d4a96c50 100644 --- a/infrastructure/control-panel/src/routes/monitoring/[namespace]/[service]/+page.ts +++ b/infrastructure/control-panel/src/routes/monitoring/[namespace]/[service]/+page.ts @@ -4,4 +4,4 @@ export const load = ({ params }) => { namespace: params.namespace, service: params.service }; -}; \ No newline at end of file +}; diff --git a/infrastructure/eid-wallet/src/routes/(app)/+layout.svelte b/infrastructure/eid-wallet/src/routes/(app)/+layout.svelte index f1261fe2..a0063862 100644 --- a/infrastructure/eid-wallet/src/routes/(app)/+layout.svelte +++ b/infrastructure/eid-wallet/src/routes/(app)/+layout.svelte @@ -1,49 +1,48 @@ diff --git a/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte b/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte index 571bc293..44cbb142 100644 --- a/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte +++ b/infrastructure/eid-wallet/src/routes/(app)/scan-qr/+page.svelte @@ -1,500 +1,483 @@ diff --git a/infrastructure/eid-wallet/src/routes/(app)/sign/+page.svelte b/infrastructure/eid-wallet/src/routes/(app)/sign/+page.svelte index d8f3af44..17bf5f43 100644 --- a/infrastructure/eid-wallet/src/routes/(app)/sign/+page.svelte +++ b/infrastructure/eid-wallet/src/routes/(app)/sign/+page.svelte @@ -1,120 +1,119 @@ diff --git a/infrastructure/eid-wallet/src/routes/(auth)/login/+page.svelte b/infrastructure/eid-wallet/src/routes/(auth)/login/+page.svelte index 07c860b1..3f2477bf 100644 --- a/infrastructure/eid-wallet/src/routes/(auth)/login/+page.svelte +++ b/infrastructure/eid-wallet/src/routes/(auth)/login/+page.svelte @@ -1,152 +1,144 @@
- import SplashScreen from "$lib/fragments/SplashScreen/SplashScreen.svelte"; - import { onMount, setContext, getContext } from "svelte"; - import "../app.css"; - import { onNavigate, goto } from "$app/navigation"; - import { GlobalState } from "$lib/global/state"; - - import { runtime } from "$lib/global/runtime.svelte"; - import { type Status, checkStatus } from "@tauri-apps/plugin-biometric"; - - const { children } = $props(); - - let globalState: GlobalState | undefined = $state(undefined); - - let showSplashScreen = $state(false); - let previousRoute = null; - let navigationStack: string[] = []; - - setContext("globalState", () => globalState); - - // replace with actual data loading logic - async function loadData() { - await new Promise((resolve) => setTimeout(resolve, 1500)); +import SplashScreen from "$lib/fragments/SplashScreen/SplashScreen.svelte"; +import { onMount, setContext, getContext } from "svelte"; +import "../app.css"; +import { onNavigate, goto } from "$app/navigation"; +import { GlobalState } from "$lib/global/state"; + +import { runtime } from "$lib/global/runtime.svelte"; +import { type Status, checkStatus } from "@tauri-apps/plugin-biometric"; + +const { children } = $props(); + +let globalState: GlobalState | undefined = $state(undefined); + +let showSplashScreen = $state(false); +let previousRoute = null; +let navigationStack: string[] = []; + +setContext("globalState", () => globalState); + +// replace with actual data loading logic +async function loadData() { + await new Promise((resolve) => setTimeout(resolve, 1500)); +} + +async function ensureMinimumDelay() { + await new Promise((resolve) => setTimeout(resolve, 500)); +} + +onMount(async () => { + let status: Status | undefined = undefined; + try { + status = await checkStatus(); + } catch (error) { + status = { + biometryType: 0, + isAvailable: false, + }; } - - async function ensureMinimumDelay() { - await new Promise((resolve) => setTimeout(resolve, 500)); + runtime.biometry = status.biometryType; + try { + globalState = await GlobalState.create(); + } catch (error) { + console.error("Failed to initialize global state:", error); + // Consider adding fallback behavior or user notification } - onMount(async () => { - let status: Status | undefined = undefined; - try { - status = await checkStatus(); - } catch (error) { - status = { - biometryType: 0, - isAvailable: false, - }; - } - runtime.biometry = status.biometryType; - try { - globalState = await GlobalState.create(); - } catch (error) { - console.error("Failed to initialize global state:", error); - // Consider adding fallback behavior or user notification + // Handle deep links + try { + const { onOpenUrl, getCurrent } = await import( + "@tauri-apps/plugin-deep-link" + ); + + // Check if app was started via deep link + const initialUrls = await getCurrent(); + if (initialUrls && initialUrls.length > 0) { + handleDeepLink(initialUrls[0]); } - // Handle deep links + // Listen for future deep links + await onOpenUrl((urls) => { + if (urls && urls.length > 0) { + handleDeepLink(urls[0]); + } + }); + } catch (error) { + console.error("Failed to initialize deep link listener:", error); + } + + function handleDeepLink(urlString: string) { + console.log("Deep link received:", urlString); try { - const { onOpenUrl, getCurrent } = await import( - "@tauri-apps/plugin-deep-link" + const url = new URL(urlString); + const path = url.pathname; + const params = url.searchParams; + + console.log("Deep link path:", path); + console.log("Deep link hostname:", url.hostname); + console.log("Deep link protocol:", url.protocol); + console.log("Deep link full URL object:", url); + console.log( + "Deep link params:", + Object.fromEntries(params.entries()), ); - // Check if app was started via deep link - const initialUrls = await getCurrent(); - if (initialUrls && initialUrls.length > 0) { - handleDeepLink(initialUrls[0]); - } + // Check if we're already on the scan-qr page + const currentPath = window.location.pathname; + const isOnScanPage = currentPath === "/scan-qr"; + console.log( + "Current path:", + currentPath, + "Is on scan page:", + isOnScanPage, + ); - // Listen for future deep links - await onOpenUrl((urls) => { - if (urls && urls.length > 0) { - handleDeepLink(urls[0]); - } - }); - } catch (error) { - console.error("Failed to initialize deep link listener:", error); - } + // For w3ds:// URLs, we need to check the hostname instead of pathname + // w3ds://auth becomes hostname: "auth", pathname: "" + const action = url.hostname || path; + console.log("Deep link action (hostname):", action); - function handleDeepLink(urlString: string) { - console.log("Deep link received:", urlString); - try { - const url = new URL(urlString); - const path = url.pathname; - const params = url.searchParams; - - console.log("Deep link path:", path); - console.log("Deep link hostname:", url.hostname); - console.log("Deep link protocol:", url.protocol); - console.log("Deep link full URL object:", url); - console.log( - "Deep link params:", - Object.fromEntries(params.entries()), - ); + // Example: w3ds://auth?session=123&platform=example&redirect=https://example.com + if (action === "auth") { + // Handle authentication deep link + const sessionId = params.get("session"); + const platform = params.get("platform"); + const redirect = params.get("redirect"); - // Check if we're already on the scan-qr page - const currentPath = window.location.pathname; - const isOnScanPage = currentPath === "/scan-qr"; console.log( - "Current path:", - currentPath, - "Is on scan page:", - isOnScanPage, + "Auth deep link - session:", + sessionId, + "platform:", + platform, + "redirect:", + redirect, ); - // For w3ds:// URLs, we need to check the hostname instead of pathname - // w3ds://auth becomes hostname: "auth", pathname: "" - const action = url.hostname || path; - console.log("Deep link action (hostname):", action); - - // Example: w3ds://auth?session=123&platform=example&redirect=https://example.com - if (action === "auth") { - // Handle authentication deep link - const sessionId = params.get("session"); - const platform = params.get("platform"); - const redirect = params.get("redirect"); - - console.log( - "Auth deep link - session:", - sessionId, - "platform:", - platform, - "redirect:", - redirect, - ); - - if (sessionId && platform && redirect) { - // Always store the deep link data first - const deepLinkData = { - type: "auth", - session: sessionId, - platform: platform, - redirect: redirect, - }; - - // Check if user is authenticated by looking for vault data - const checkAuth = async () => { - try { - // Try to access vault data - if this fails, user is not authenticated - const globalState = - getContext<() => GlobalState>( - "globalState", - )(); - if (globalState) { - const vault = - await globalState.vaultController.vault; - if (vault) { - // User is authenticated, go to scan page - console.log( - "User authenticated, navigating to scan-qr", - ); - sessionStorage.setItem( - "deepLinkData", - JSON.stringify(deepLinkData), - ); - goto("/scan-qr"); - return; - } + if (sessionId && platform && redirect) { + // Always store the deep link data first + const deepLinkData = { + type: "auth", + session: sessionId, + platform: platform, + redirect: redirect, + }; + + // Check if user is authenticated by looking for vault data + const checkAuth = async () => { + try { + // Try to access vault data - if this fails, user is not authenticated + const globalState = + getContext<() => GlobalState>("globalState")(); + if (globalState) { + const vault = + await globalState.vaultController.vault; + if (vault) { + // User is authenticated, go to scan page + console.log( + "User authenticated, navigating to scan-qr", + ); + sessionStorage.setItem( + "deepLinkData", + JSON.stringify(deepLinkData), + ); + goto("/scan-qr"); + return; } - } catch (error) { - console.log( - "User not authenticated, redirecting to login", - ); } - - // User not authenticated, store deep link data and redirect to login + } catch (error) { console.log( - "User not authenticated, storing deep link data and redirecting to login", + "User not authenticated, redirecting to login", ); - sessionStorage.setItem( - "pendingDeepLink", - JSON.stringify(deepLinkData), - ); - goto("/login"); - }; - - checkAuth(); - } else { - console.log("Missing required auth parameters"); - } - } else if (action === "sign") { - // Handle signing deep link - const sessionId = params.get("session"); - const data = params.get("data"); - const redirectUri = params.get("redirect_uri"); - - console.log( - "Sign deep link - session:", - sessionId, - "data:", - data, - "redirect_uri:", - redirectUri, - ); - - if (sessionId && data && redirectUri) { - // Always store the deep link data first - const deepLinkData = { - type: "sign", - session: sessionId, - data: data, - redirect_uri: redirectUri, - }; - - // Check if user is authenticated by looking for vault data - const checkAuth = async () => { - try { - // Try to access vault data - if this fails, user is not authenticated - const globalState = - getContext<() => GlobalState>( - "globalState", - )(); - if (globalState) { - const vault = - await globalState.vaultController.vault; - if (vault) { - // User is authenticated, go to scan page - console.log( - "User authenticated, navigating to scan-qr", - ); - sessionStorage.setItem( - "deepLinkData", - JSON.stringify(deepLinkData), - ); - goto("/scan-qr"); - return; - } + } + + // User not authenticated, store deep link data and redirect to login + console.log( + "User not authenticated, storing deep link data and redirecting to login", + ); + sessionStorage.setItem( + "pendingDeepLink", + JSON.stringify(deepLinkData), + ); + goto("/login"); + }; + + checkAuth(); + } else { + console.log("Missing required auth parameters"); + } + } else if (action === "sign") { + // Handle signing deep link + const sessionId = params.get("session"); + const data = params.get("data"); + const redirectUri = params.get("redirect_uri"); + + console.log( + "Sign deep link - session:", + sessionId, + "data:", + data, + "redirect_uri:", + redirectUri, + ); + + if (sessionId && data && redirectUri) { + // Always store the deep link data first + const deepLinkData = { + type: "sign", + session: sessionId, + data: data, + redirect_uri: redirectUri, + }; + + // Check if user is authenticated by looking for vault data + const checkAuth = async () => { + try { + // Try to access vault data - if this fails, user is not authenticated + const globalState = + getContext<() => GlobalState>("globalState")(); + if (globalState) { + const vault = + await globalState.vaultController.vault; + if (vault) { + // User is authenticated, go to scan page + console.log( + "User authenticated, navigating to scan-qr", + ); + sessionStorage.setItem( + "deepLinkData", + JSON.stringify(deepLinkData), + ); + goto("/scan-qr"); + return; } - } catch (error) { - console.log( - "User not authenticated, redirecting to login", - ); } - - // User not authenticated, store deep link data and redirect to login + } catch (error) { console.log( - "User not authenticated, storing deep link data and redirecting to login", + "User not authenticated, redirecting to login", ); - sessionStorage.setItem( - "pendingDeepLink", - JSON.stringify(deepLinkData), - ); - goto("/login"); - }; - - checkAuth(); - } else { - console.log("Missing required signing parameters"); - } + } + + // User not authenticated, store deep link data and redirect to login + console.log( + "User not authenticated, storing deep link data and redirecting to login", + ); + sessionStorage.setItem( + "pendingDeepLink", + JSON.stringify(deepLinkData), + ); + goto("/login"); + }; + + checkAuth(); } else { - console.log("Unknown deep link path:", path); + console.log("Missing required signing parameters"); } - } catch (error) { - console.error("Failed to parse deep link URL:", error); + } else { + console.log("Unknown deep link path:", path); } + } catch (error) { + console.error("Failed to parse deep link URL:", error); } + } - showSplashScreen = true; // Can't set up the original state to true or animation won't start - navigationStack.push(window.location.pathname); + showSplashScreen = true; // Can't set up the original state to true or animation won't start + navigationStack.push(window.location.pathname); - await Promise.all([loadData(), ensureMinimumDelay()]); + await Promise.all([loadData(), ensureMinimumDelay()]); - showSplashScreen = false; - }); + showSplashScreen = false; +}); - const safeAreaTop = $derived.by( - () => - Number.parseFloat( - getComputedStyle(document.documentElement).getPropertyValue( - "--safe-top", - ), - ) || 0, - ); +const safeAreaTop = $derived.by( + () => + Number.parseFloat( + getComputedStyle(document.documentElement).getPropertyValue( + "--safe-top", + ), + ) || 0, +); - $effect(() => console.log("top", safeAreaTop)); +$effect(() => console.log("top", safeAreaTop)); - onNavigate((navigation) => { - if (!document.startViewTransition) return; +onNavigate((navigation) => { + if (!document.startViewTransition) return; - const from = navigation.from?.url.pathname; - const to = navigation.to?.url.pathname; + const from = navigation.from?.url.pathname; + const to = navigation.to?.url.pathname; - if (!from || !to || from === to) return; + if (!from || !to || from === to) return; - let direction: "left" | "right" = "right"; + let direction: "left" | "right" = "right"; - const fromIndex = navigationStack.lastIndexOf(from); - const toIndex = navigationStack.lastIndexOf(to); + const fromIndex = navigationStack.lastIndexOf(from); + const toIndex = navigationStack.lastIndexOf(to); - if (toIndex !== -1 && toIndex < fromIndex) { - // Backward navigation - direction = "left"; - navigationStack = navigationStack.slice(0, toIndex + 1); - } else { - // Forward navigation (or new path) - direction = "right"; - navigationStack.push(to); - } + if (toIndex !== -1 && toIndex < fromIndex) { + // Backward navigation + direction = "left"; + navigationStack = navigationStack.slice(0, toIndex + 1); + } else { + // Forward navigation (or new path) + direction = "right"; + navigationStack.push(to); + } - document.documentElement.setAttribute("data-transition", direction); - previousRoute = to; + document.documentElement.setAttribute("data-transition", direction); + previousRoute = to; - return new Promise((resolve) => { - document.startViewTransition(async () => { - resolve(); - await navigation.complete; - }); + return new Promise((resolve) => { + document.startViewTransition(async () => { + resolve(); + await navigation.complete; }); }); +}); {#if showSplashScreen} diff --git a/platforms/blabsy/src/components/login/login-main.tsx b/platforms/blabsy/src/components/login/login-main.tsx index b037743c..1bd32f38 100644 --- a/platforms/blabsy/src/components/login/login-main.tsx +++ b/platforms/blabsy/src/components/login/login-main.tsx @@ -35,7 +35,7 @@ export function LoginMain(): JSX.Element { process.env.NEXT_PUBLIC_BASE_URL ).toString() ); - console.log("getting offer data") + console.log('getting offer data'); setQr(data.uri); watchEventStream( new URL(data.uri).searchParams.get('session') as string diff --git a/platforms/blabsy/src/lib/utils/mobile-detection.ts b/platforms/blabsy/src/lib/utils/mobile-detection.ts index d381195b..81d924a4 100644 --- a/platforms/blabsy/src/lib/utils/mobile-detection.ts +++ b/platforms/blabsy/src/lib/utils/mobile-detection.ts @@ -1,10 +1,13 @@ export function isMobileDevice(): boolean { - if (typeof window === 'undefined') return false; - - return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || - (window.innerWidth <= 768); + if (typeof window === 'undefined') return false; + + return ( + /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test( + navigator.userAgent + ) || window.innerWidth <= 768 + ); } export function getDeepLinkUrl(qrData: string): string { - return qrData; -} \ No newline at end of file + return qrData; +} diff --git a/platforms/pictique/src/lib/fragments/ActionMenu/ActionMenu.svelte b/platforms/pictique/src/lib/fragments/ActionMenu/ActionMenu.svelte index 63e62b01..6ce4af7b 100644 --- a/platforms/pictique/src/lib/fragments/ActionMenu/ActionMenu.svelte +++ b/platforms/pictique/src/lib/fragments/ActionMenu/ActionMenu.svelte @@ -54,7 +54,7 @@