onairos 4.2.0 โ†’ 4.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"670.js","mappings":"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","sources":["webpack://OnairosLaravel/./src/components/WelcomeScreen.jsx","webpack://OnairosLaravel/./src/theme/colors.js","webpack://OnairosLaravel/./src/components/ui/PrimaryButton.jsx","webpack://OnairosLaravel/./src/components/EmailAuth.js","webpack://OnairosLaravel/./src/utils/capacitorDetection.js","webpack://OnairosLaravel/./src/components/ConnectChatGPTModal.jsx","webpack://OnairosLaravel/./src/components/UniversalOnboarding.jsx","webpack://OnairosLaravel/./src/components/PinSetup.js","webpack://OnairosLaravel/./src/components/DataRequest.js","webpack://OnairosLaravel/./src/components/TrainingComponent.jsx","webpack://OnairosLaravel/./src/components/TrainingScreen.jsx","webpack://OnairosLaravel/./src/components/LoadingScreen.jsx","webpack://OnairosLaravel/./src/components/WrappedLoadingPage.jsx","webpack://OnairosLaravel/./src/utils/responseFormatter.js","webpack://OnairosLaravel/./src/utils/userDataFormatter.js","webpack://OnairosLaravel/./src/components/ui/PageLayout.jsx","webpack://OnairosLaravel/./src/onairosButton.jsx"],"sourcesContent":["import React, { useEffect } from 'react';\r\nimport { COLORS } from '../theme/colors.js';\r\n\r\nexport default function WelcomeScreen({ onContinue, onClose }) {\r\n // Load Sirv script for responsive images\r\n useEffect(() => {\r\n const script = document.createElement('script');\r\n script.src = 'https://scripts.sirv.com/sirvjs/v3/sirv.js';\r\n script.async = true;\r\n document.head.appendChild(script);\r\n \r\n return () => {\r\n const existingScript = document.querySelector('script[src=\"https://scripts.sirv.com/sirvjs/v3/sirv.js\"]');\r\n if (existingScript) {\r\n document.head.removeChild(existingScript);\r\n }\r\n };\r\n }, []);\r\n\r\n return (\r\n <div className=\"w-full flex flex-col\" style={{ height: '100%' }}>\r\n {/* Content - Flexible center area */}\r\n <div className=\"px-6 pt-16 text-center flex-1 flex flex-col\">\r\n {/* Logo */}\r\n <div className=\"mb-8 flex justify-center\">\r\n <div className=\"w-20 h-20 flex items-center justify-center\">\r\n <img \r\n className=\"Sirv w-full h-full object-contain\" \r\n data-src=\"https://anushkasirv.sirv.com/OnairosBlack.png\" \r\n alt=\"Onairos Logo\"\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Welcome Text */}\r\n <p className=\"text-gray-500 text-sm mb-2\">Welcome to</p>\r\n\r\n {/* Main Title */}\r\n <h1 className=\"text-4xl font-bold text-gray-900 mb-6 text-balance\">Onairos</h1>\r\n\r\n {/* Description */}\r\n <p className=\"text-gray-600 text-base leading-relaxed mb-12 text-pretty px-2\">\r\n OnairOS personalizes your digital experience on every app so you can just enjoy being you!\r\n </p>\r\n </div>\r\n\r\n {/* Get Started Button - Fixed at bottom */}\r\n <div className=\"px-6 pb-8 flex-shrink-0\">\r\n <button\r\n className=\"w-full bg-gray-900 hover:bg-gray-800 text-white rounded-full py-4 text-base font-medium flex items-center justify-center gap-2 transition-colors\"\r\n onClick={onContinue}\r\n >\r\n Get Started\r\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","// Theme colors for Onairos SDK - derived from mobile design\r\nexport const COLORS = {\r\n // Button gradient colors\r\n btnGradStart: '#1A1A1A',\r\n btnGradEnd: '#000000',\r\n \r\n // Button text and icon colors\r\n btnLabel: '#FFFFFF',\r\n btnBorder: 'rgba(0, 0, 0, 0.2)',\r\n \r\n // Icon circle gradient colors\r\n iconCircleGradientStart: '#333333',\r\n iconCircleGradientEnd: '#1A1A1A',\r\n \r\n // Background colors\r\n background: '#FFFFFF',\r\n backgroundSecondary: '#F8F9FA',\r\n \r\n // Text colors\r\n textPrimary: '#1A1A1A',\r\n textSecondary: '#6B7280',\r\n textMuted: '#9CA3AF',\r\n \r\n // Border colors\r\n border: '#E5E7EB',\r\n borderLight: '#F3F4F6',\r\n \r\n // Status colors\r\n success: '#10B981',\r\n error: '#EF4444',\r\n warning: '#F59E0B',\r\n info: '#3B82F6',\r\n \r\n // Interactive states\r\n hover: 'rgba(0, 0, 0, 0.05)',\r\n pressed: 'rgba(0, 0, 0, 0.1)',\r\n focus: 'rgba(59, 130, 246, 0.1)',\r\n};\r\n\r\nexport default COLORS; ","import React, { useState } from 'react';\r\nimport { COLORS } from '../../theme/colors.js';\r\n\r\n// Icon Circle component matching the React Native version\r\nconst IconCircle = ({ \r\n size = 40, \r\n children,\r\n className = ''\r\n}) => {\r\n return (\r\n <div \r\n className={`relative flex items-center justify-center border border-black border-opacity-25 ${className}`}\r\n style={{\r\n width: size,\r\n height: size,\r\n borderRadius: size / 2,\r\n background: `linear-gradient(to bottom, ${COLORS.iconCircleGradientStart}, ${COLORS.iconCircleGradientEnd})`\r\n }}\r\n >\r\n {children || (\r\n <span \r\n className=\"font-semibold opacity-95\"\r\n style={{\r\n fontSize: '20px',\r\n color: COLORS.btnLabel,\r\n backgroundColor: 'transparent'\r\n }}\r\n >\r\n โ†’\r\n </span>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// Primary Button component matching the React Native design\r\nconst PrimaryButton = ({\r\n label = \"Get Started\",\r\n onClick,\r\n iconRight,\r\n loading = false,\r\n disabled = false,\r\n testId,\r\n className = '',\r\n style = {},\r\n textStyle = {},\r\n centered = false,\r\n ...props\r\n}) => {\r\n const [pressed, setPressed] = useState(false);\r\n\r\n const handleMouseDown = () => setPressed(true);\r\n const handleMouseUp = () => setPressed(false);\r\n const handleMouseLeave = () => setPressed(false);\r\n\r\n const buttonStyle = {\r\n height: '48px',\r\n borderRadius: '100px',\r\n border: `1px solid ${COLORS.btnBorder}`,\r\n background: `linear-gradient(to bottom, ${COLORS.btnGradStart}, ${COLORS.btnGradEnd})`,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n width: centered ? 'auto' : '100%',\r\n minWidth: centered ? '250px' : 'auto',\r\n maxWidth: centered ? '350px' : 'none',\r\n margin: centered ? '0 auto' : '0',\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n opacity: disabled ? 0.65 : 1,\r\n boxShadow: disabled ? 'none' : '20px 30px 40px rgba(0,0,0,0.10)',\r\n transition: 'all 0.2s ease',\r\n ...style\r\n };\r\n\r\n const pressedOverlayStyle = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n backgroundColor: 'rgba(0,0,0,0.1)',\r\n borderRadius: '100px',\r\n opacity: pressed ? 1 : 0,\r\n transition: 'opacity 0.1s ease'\r\n };\r\n\r\n const textContainerStyle = {\r\n position: 'absolute',\r\n left: 0,\r\n right: 0,\r\n top: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n backgroundColor: 'transparent'\r\n };\r\n\r\n const iconPositionStyle = {\r\n position: 'absolute',\r\n right: '4px',\r\n top: '4px',\r\n bottom: '4px',\r\n width: '40px',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n backgroundColor: 'transparent'\r\n };\r\n\r\n const labelStyle = {\r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n fontWeight: '600',\r\n fontSize: '16px',\r\n color: COLORS.btnLabel,\r\n textAlign: 'center',\r\n backgroundColor: 'transparent',\r\n ...textStyle\r\n };\r\n\r\n return (\r\n <button\r\n className={`relative ${className}`}\r\n style={buttonStyle}\r\n onClick={onClick}\r\n onMouseDown={handleMouseDown}\r\n onMouseUp={handleMouseUp}\r\n onMouseLeave={handleMouseLeave}\r\n disabled={disabled || loading}\r\n data-testid={testId}\r\n aria-label={label}\r\n {...props}\r\n >\r\n {/* Pressed state overlay */}\r\n <div style={pressedOverlayStyle} />\r\n\r\n {/* Centered text container */}\r\n <div style={textContainerStyle}>\r\n {loading ? (\r\n <div \r\n className=\"animate-spin rounded-full border-2 border-white border-t-transparent\"\r\n style={{ width: '20px', height: '20px' }}\r\n />\r\n ) : (\r\n <span style={labelStyle}>{label}</span>\r\n )}\r\n </div>\r\n\r\n {/* Icon in fixed position on right */}\r\n <div style={iconPositionStyle}>\r\n {!loading && (iconRight || <IconCircle />)}\r\n </div>\r\n </button>\r\n );\r\n};\r\n\r\nexport { IconCircle };\r\nexport default PrimaryButton; ","import React, { useState, useEffect } from 'react';\r\nimport { Mail, ArrowRight, Check } from 'lucide-react';\r\nimport { GoogleLogin } from '@react-oauth/google';\r\nimport PrimaryButton from './ui/PrimaryButton.jsx';\r\nimport { COLORS } from '../theme/colors.js';\r\n\r\nexport default function EmailAuth({ onSuccess, testMode = true }) {\r\n const [email, setEmail] = useState('');\r\n // Store verification code as per-digit state to avoid losing position when users click/paste/autofill.\r\n const [codeDigits, setCodeDigits] = useState(() => Array(6).fill(''));\r\n const [step, setStep] = useState('email'); // 'email' | 'code' | 'success'\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState('');\r\n const [emailSent, setEmailSent] = useState(true); // Track if email was actually sent\r\n const [emailServiceMessage, setEmailServiceMessage] = useState(''); // Store service message\r\n const code = codeDigits.join('');\r\n const isCodeComplete = codeDigits.every((d) => typeof d === 'string' && d.length === 1);\r\n const resetCodeDigits = () => setCodeDigits(Array(6).fill(''));\r\n\r\n const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\r\n\r\n const postJson = async (url, apiKey, body) => {\r\n const response = await fetch(url, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': apiKey,\r\n 'Authorization': `Bearer ${apiKey}`,\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n return response;\r\n };\r\n\r\n // Prefer the newer single-endpoint API: POST /email/verification { action: 'request'|'verify' }\r\n // Fall back to legacy /email/verify and /email/verify/confirm if needed.\r\n const requestEmailVerification = async ({ baseUrl, apiKey, email: rawEmail }) => {\r\n const normalizedEmail = (rawEmail || '').trim().toLowerCase();\r\n\r\n // New endpoint\r\n try {\r\n const res = await postJson(`${baseUrl}/email/verification`, apiKey, {\r\n email: normalizedEmail,\r\n action: 'request',\r\n });\r\n if (res.ok) return await res.json();\r\n } catch {\r\n // ignore and fall back\r\n }\r\n\r\n // Legacy endpoint\r\n const legacyRes = await postJson(`${baseUrl}/email/verify`, apiKey, { email: normalizedEmail });\r\n if (!legacyRes.ok) {\r\n let msg = 'Failed to send verification code';\r\n try {\r\n const err = await legacyRes.json();\r\n if (err?.error) msg = err.error;\r\n } catch {}\r\n throw new Error(msg);\r\n }\r\n return await legacyRes.json();\r\n };\r\n\r\n const verifyEmailCode = async ({ baseUrl, apiKey, email: rawEmail, code: rawCode }) => {\r\n const normalizedEmail = (rawEmail || '').trim().toLowerCase();\r\n const normalizedCode = String(rawCode || '').trim();\r\n\r\n // New endpoint\r\n try {\r\n const res = await postJson(`${baseUrl}/email/verification`, apiKey, {\r\n email: normalizedEmail,\r\n action: 'verify',\r\n code: normalizedCode,\r\n });\r\n if (res.ok) return await res.json();\r\n // If it's a hard failure, surface its message\r\n try {\r\n const err = await res.json();\r\n throw new Error(err?.error || err?.message || 'Verification failed');\r\n } catch (e) {\r\n // If parsing fails, fall through to legacy retry below\r\n if (e instanceof Error) throw e;\r\n }\r\n } catch (e) {\r\n // If server doesn't support /email/verification or network hiccup, try legacy below.\r\n // If it's a real \"invalid code\" error, we rethrow and don't spam retries.\r\n const msg = e?.message || '';\r\n if (msg && !msg.toLowerCase().includes('not found') && !msg.toLowerCase().includes('cannot')) {\r\n // Keep going to legacy; it might be the only supported path.\r\n }\r\n }\r\n\r\n // Legacy endpoint with light retry for multi-instance deployments:\r\n // \"No verification code found\" often means request+confirm hit different servers.\r\n const maxAttempts = 5;\r\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\r\n const res = await postJson(`${baseUrl}/email/verify/confirm`, apiKey, {\r\n email: normalizedEmail,\r\n code: normalizedCode,\r\n });\r\n\r\n if (res.ok) return await res.json();\r\n\r\n let errMsg = 'Invalid verification code';\r\n try {\r\n const err = await res.json();\r\n if (err?.error) errMsg = err.error;\r\n if (typeof err?.attemptsRemaining === 'number') {\r\n errMsg = `${errMsg} (attempts remaining: ${err.attemptsRemaining})`;\r\n }\r\n } catch {}\r\n\r\n // Retry only for the \"code missing\" case\r\n if (errMsg.toLowerCase().includes('no verification code found') && attempt < maxAttempts) {\r\n await sleep(150 * attempt);\r\n continue;\r\n }\r\n\r\n throw new Error(errMsg);\r\n }\r\n\r\n throw new Error('Verification failed');\r\n };\r\n\r\n // Helper function to handle OAuth success (Gmail) - defined early for useEffect\r\n const handleOAuthSuccess = async (gmailEmail) => {\r\n try {\r\n setIsLoading(true);\r\n console.log('โœ… Google OAuth completed successfully, email:', gmailEmail);\r\n\r\n const normalizedEmail = (gmailEmail || '').trim().toLowerCase();\r\n setEmail(normalizedEmail);\r\n\r\n // Check if this email already has an account in the backend\r\n const baseUrl = (typeof window !== 'undefined' && window.onairosBaseUrl) || 'https://api2.onairos.uk';\r\n const apiKey = (typeof window !== 'undefined' && window.onairosApiKey) || 'ona_VvoHNg1fdCCUa9eBy4Iz3IfvXdgLfMFI7TNcyHLDKEadPogkbjAeE2iDOs6M7Aey';\r\n\r\n let accountInfo = null;\r\n let accountStatus = null;\r\n let existingUser = false;\r\n\r\n try {\r\n console.log('๐Ÿ” Checking if account exists for:', normalizedEmail);\r\n const accountCheckResponse = await fetch(`${baseUrl}/getAccountInfo/email`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': apiKey,\r\n },\r\n body: JSON.stringify({\r\n Info: {\r\n identifier: normalizedEmail\r\n }\r\n })\r\n });\r\n\r\n if (accountCheckResponse.ok) {\r\n const accountData = await accountCheckResponse.json();\r\n \r\n if (accountData.AccountInfo) {\r\n accountInfo = accountData.AccountInfo;\r\n accountStatus = accountData.accountStatus;\r\n existingUser = accountStatus?.exists || false;\r\n \r\n console.log('โœ… Existing account found:', {\r\n exists: existingUser,\r\n hasTrainedModel: accountStatus?.hasTrainedModel,\r\n hasPersonalityTraits: accountStatus?.hasPersonalityTraits,\r\n connectedPlatforms: accountStatus?.connectedPlatforms,\r\n needsDataConnection: accountStatus?.needsDataConnection,\r\n needsTraining: accountStatus?.needsTraining,\r\n canUseInference: accountStatus?.canUseInference\r\n });\r\n } else {\r\n console.log('โ„น๏ธ No existing account found - new user');\r\n }\r\n } else {\r\n console.log('โ„น๏ธ Account check returned non-OK status - treating as new user');\r\n }\r\n } catch (accountCheckError) {\r\n console.warn('โš ๏ธ Could not check account status, treating as new user:', accountCheckError);\r\n }\r\n\r\n setStep('success');\r\n setIsLoading(false);\r\n\r\n setTimeout(() => {\r\n onSuccess({\r\n email: normalizedEmail,\r\n verified: true,\r\n token: null,\r\n userName: normalizedEmail.split('@')[0],\r\n existingUser: existingUser,\r\n accountInfo: accountInfo,\r\n accountStatus: accountStatus, // NEW: Pass the accountStatus object\r\n isNewUser: !existingUser,\r\n flowType: existingUser ? 'dataRequest' : 'onboarding',\r\n adminMode: false,\r\n userCreated: !existingUser,\r\n accountDetails: existingUser ? accountInfo : {\r\n email: normalizedEmail,\r\n createdAt: new Date().toISOString(),\r\n ssoProvider: 'gmail'\r\n }\r\n });\r\n }, 400);\r\n \r\n } catch (error) {\r\n console.error('โŒ Error handling OAuth success:', error);\r\n setError('Failed to continue with Google authentication. Please try again.');\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n // Check for Gmail OAuth success on mount (after redirect back)\r\n useEffect(() => {\r\n const checkGmailOAuthSuccess = () => {\r\n const gmailSuccess = localStorage.getItem('onairos_gmail_success');\r\n const gmailTimestamp = localStorage.getItem('onairos_gmail_timestamp');\r\n const oauthContext = localStorage.getItem('onairos_oauth_context');\r\n \r\n // Only process if we're coming back from Gmail auth flow\r\n if (gmailSuccess === 'true' && gmailTimestamp && oauthContext === 'gmail-auth') {\r\n const timestampNum = parseInt(gmailTimestamp, 10);\r\n const now = Date.now();\r\n \r\n // Only process if timestamp is recent (within last 30 seconds)\r\n if (now - timestampNum < 30000) {\r\n console.log('โœ… Gmail OAuth completed - processing redirect back');\r\n \r\n // Get email from localStorage\r\n const gmailEmail = localStorage.getItem('onairos_gmail_email') || \r\n localStorage.getItem('onairos_oauth_email');\r\n \r\n // Clean up localStorage\r\n localStorage.removeItem('onairos_gmail_success');\r\n localStorage.removeItem('onairos_gmail_timestamp');\r\n localStorage.removeItem('onairos_oauth_context');\r\n localStorage.removeItem('onairos_return_url');\r\n \r\n if (gmailEmail) {\r\n // Process OAuth success\r\n handleOAuthSuccess(gmailEmail);\r\n }\r\n }\r\n }\r\n };\r\n\r\n checkGmailOAuthSuccess();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []); // Only run once on mount\r\n\r\n // Check for OAuth completion on mount (for same-page redirect flow)\r\n useEffect(() => {\r\n const checkOAuthCompletion = () => {\r\n // Check URL params for OAuth completion\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const oauthSuccess = urlParams.get('onairos_oauth_success');\r\n const oauthPlatform = urlParams.get('onairos_oauth_platform');\r\n const oauthEmail = urlParams.get('onairos_oauth_email');\r\n\r\n if (oauthSuccess === 'true' && oauthPlatform === 'gmail' && oauthEmail) {\r\n console.log('โœ… Gmail OAuth completion detected on page load');\r\n // Clean up URL\r\n const newUrl = window.location.pathname;\r\n window.history.replaceState({}, '', newUrl);\r\n // Handle OAuth success\r\n handleOAuthSuccess(oauthEmail);\r\n } else {\r\n // Check localStorage for OAuth completion (fallback)\r\n const success = localStorage.getItem('onairos_gmail_success');\r\n const timestamp = localStorage.getItem('onairos_gmail_timestamp');\r\n const gmailEmail = localStorage.getItem('onairos_gmail_email');\r\n\r\n if (success === 'true' && timestamp && gmailEmail) {\r\n const timestampNum = parseInt(timestamp, 10);\r\n const now = Date.now();\r\n \r\n // Only process if timestamp is recent (within last 60 seconds)\r\n if (now - timestampNum < 60000) {\r\n console.log('โœ… Gmail OAuth completion detected via localStorage');\r\n // Clean up localStorage\r\n localStorage.removeItem('onairos_gmail_success');\r\n localStorage.removeItem('onairos_gmail_timestamp');\r\n // Handle OAuth success\r\n handleOAuthSuccess(gmailEmail);\r\n }\r\n }\r\n }\r\n };\r\n\r\n checkOAuthCompletion();\r\n }, []); // Run once on mount\r\n\r\n // Auto-focus first PIN input when code step loads\r\n useEffect(() => {\r\n if (step === 'code') {\r\n // Small delay to ensure DOM is ready\r\n setTimeout(() => {\r\n const firstInput = document.querySelector('input.onairos-verification-digit');\r\n if (firstInput) {\r\n firstInput.focus();\r\n }\r\n }, 100);\r\n }\r\n }, [step]);\r\n\r\n const validateEmail = (email) => {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n return emailRegex.test(email);\r\n };\r\n\r\n const handleEmailSubmit = async (e) => {\r\n e.preventDefault();\r\n setError('');\r\n setEmailSent(true); // Reset email status\r\n setEmailServiceMessage(''); // Reset service message\r\n resetCodeDigits();\r\n\r\n if (!validateEmail(email)) {\r\n setError('Please enter a valid email address');\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n\r\n try {\r\n if (testMode) {\r\n // Test mode: Skip API call completely, simulate instant success\r\n console.log('๐Ÿงช Test mode: Simulating email verification request for:', email);\r\n setTimeout(() => {\r\n setStep('code');\r\n setIsLoading(false);\r\n console.log('๐Ÿงช Test mode: Email verification simulated successfully');\r\n }, 800); // Shorter delay for faster testing\r\n } else {\r\n // Production mode: Use proper email verification API from schema\r\n const baseUrl = (typeof window !== 'undefined' && window.onairosBaseUrl) || 'https://api2.onairos.uk';\r\n const apiKey = (typeof window !== 'undefined' && window.onairosApiKey) || 'ona_VvoHNg1fdCCUa9eBy4Iz3IfvXdgLfMFI7TNcyHLDKEadPogkbjAeE2iDOs6M7Aey';\r\n const data = await requestEmailVerification({ baseUrl, apiKey, email });\r\n\r\n console.log('๐Ÿ“ง Email request response:', data);\r\n\r\n // Store email service status\r\n // /email/verify returns emailSent, /email/verification typically does not.\r\n setEmailSent(data.emailSent !== false);\r\n setEmailServiceMessage(data.message || '');\r\n\r\n setStep('code');\r\n setIsLoading(false);\r\n }\r\n } catch (error) {\r\n console.error('Email request error:', error);\r\n setError(error.message);\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n // Handle Google Sign-In success (using official GoogleLogin component)\r\n const handleGoogleSuccess = async (credentialResponse) => {\r\n try {\r\n setIsLoading(true);\r\n setError('');\r\n console.log('โœ… Google Sign-In successful, received credential');\r\n\r\n // Decode the JWT credential to get user info\r\n const credential = credentialResponse.credential;\r\n const base64Url = credential.split('.')[1];\r\n const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');\r\n const jsonPayload = decodeURIComponent(\r\n atob(base64)\r\n .split('')\r\n .map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))\r\n .join('')\r\n );\r\n\r\n const userInfo = JSON.parse(jsonPayload);\r\n const gmailEmail = userInfo.email;\r\n \r\n console.log('โœ… Decoded user email from Google:', gmailEmail);\r\n console.log('โœ… User info:', { \r\n email: userInfo.email, \r\n name: userInfo.name,\r\n picture: userInfo.picture,\r\n email_verified: userInfo.email_verified\r\n });\r\n\r\n // Optional: Send to backend for verification/storage\r\n try {\r\n const sdkConfig = {\r\n baseUrl: 'https://api2.onairos.uk',\r\n apiKey: window.onairosApiKey || 'test-key',\r\n };\r\n\r\n await fetch(`${sdkConfig.baseUrl}/auth/google`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': sdkConfig.apiKey,\r\n },\r\n body: JSON.stringify({\r\n credential: credential,\r\n email: gmailEmail,\r\n userInfo: userInfo,\r\n }),\r\n });\r\n } catch (backendError) {\r\n console.warn('โš ๏ธ Backend verification failed, continuing anyway:', backendError);\r\n }\r\n\r\n // Continue with the OAuth success flow\r\n handleOAuthSuccess(gmailEmail);\r\n\r\n } catch (error) {\r\n console.error('โŒ Google Sign-In processing failed:', error);\r\n setError('Google authentication failed. Please try again.');\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n const handleGoogleError = () => {\r\n console.error('โŒ Google Sign-In failed');\r\n setError('Google authentication failed. Please try again.');\r\n setIsLoading(false);\r\n };\r\n\r\n // handleOAuthSuccess is defined at the top of the component for use in useEffect\r\n\r\n const handleCodeSubmit = async (e) => {\r\n e.preventDefault();\r\n setError('');\r\n setIsLoading(true);\r\n\r\n try {\r\n if (testMode) {\r\n // Test mode: Skip API call completely, simulate verification\r\n console.log('๐Ÿงช Test mode: Simulating code verification for:', email, 'with code:', code);\r\n \r\n if (code === '123456' || isCodeComplete) {\r\n setStep('success');\r\n setTimeout(() => {\r\n // Simulate new user for design testing\r\n const simulatedResponse = { \r\n email, \r\n verified: true, \r\n token: 'test-token-' + Date.now(),\r\n userName: email.split('@')[0],\r\n existingUser: false, // Always simulate new user for full flow testing\r\n accountInfo: null,\r\n isNewUser: true,\r\n flowType: 'onboarding',\r\n adminMode: false,\r\n userCreated: true,\r\n accountDetails: {\r\n email: email,\r\n createdAt: new Date().toISOString(),\r\n testAccount: true\r\n }\r\n };\r\n console.log('๐Ÿงช Test mode: Simulated verification successful, user data:', simulatedResponse);\r\n onSuccess(simulatedResponse);\r\n }, 600); // Faster for design testing\r\n } else {\r\n setError('Invalid code. Use any 6-digit code (e.g., 123456) for testing.');\r\n setIsLoading(false);\r\n }\r\n } else {\r\n // Production mode: Use real email verification API from schema\r\n const baseUrl = (typeof window !== 'undefined' && window.onairosBaseUrl) || 'https://api2.onairos.uk';\r\n const apiKey = (typeof window !== 'undefined' && window.onairosApiKey) || 'ona_VvoHNg1fdCCUa9eBy4Iz3IfvXdgLfMFI7TNcyHLDKEadPogkbjAeE2iDOs6M7Aey';\r\n const codeToSubmit = codeDigits.join('');\r\n\r\n if (!isCodeComplete) {\r\n throw new Error('Please enter the full 6-digit code.');\r\n }\r\n \r\n const data = await verifyEmailCode({ baseUrl, apiKey, email, code: codeToSubmit.trim() });\r\n \r\n if (!data.success) {\r\n throw new Error(data.error || 'Verification failed');\r\n }\r\n\r\n console.log('๐Ÿ“ง Email verification response:', data);\r\n\r\n // NEW: Check account status explicitly, same as Google sign-in flow\r\n // This ensures consistent behavior between Google and email auth\r\n let accountInfo = data.accountInfo || null;\r\n let accountStatus = data.accountStatus || null;\r\n let existingUser = data.existingUser || false;\r\n\r\n try {\r\n console.log('๐Ÿ” Checking account status for:', email);\r\n const accountCheckResponse = await fetch(`${baseUrl}/getAccountInfo/email`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n 'x-api-key': apiKey,\r\n },\r\n body: JSON.stringify({\r\n Info: {\r\n identifier: email.trim().toLowerCase()\r\n }\r\n })\r\n });\r\n\r\n if (accountCheckResponse.ok) {\r\n const accountData = await accountCheckResponse.json();\r\n \r\n if (accountData.AccountInfo) {\r\n accountInfo = accountData.AccountInfo;\r\n accountStatus = accountData.accountStatus;\r\n existingUser = accountStatus?.exists || false;\r\n \r\n console.log('โœ… Account status from explicit check:', {\r\n exists: existingUser,\r\n hasTrainedModel: accountStatus?.hasTrainedModel,\r\n hasPersonalityTraits: accountStatus?.hasPersonalityTraits,\r\n connectedPlatforms: accountStatus?.connectedPlatforms,\r\n needsDataConnection: accountStatus?.needsDataConnection,\r\n needsTraining: accountStatus?.needsTraining,\r\n canUseInference: accountStatus?.canUseInference\r\n });\r\n } else {\r\n console.log('โ„น๏ธ No existing account found - new user');\r\n }\r\n } else {\r\n console.log('โ„น๏ธ Account check returned non-OK status - using verification response data');\r\n }\r\n } catch (accountCheckError) {\r\n console.warn('โš ๏ธ Could not check account status, using verification response data:', accountCheckError);\r\n }\r\n\r\n setStep('success');\r\n setTimeout(() => {\r\n // Pass complete API response with explicit account check data\r\n onSuccess({ \r\n email, \r\n verified: true, \r\n token: data.token || data.jwtToken,\r\n userName: data.userName,\r\n existingUser: existingUser,\r\n accountInfo: accountInfo,\r\n accountStatus: accountStatus, // Now includes explicit account check\r\n isNewUser: !existingUser, // Based on explicit account check\r\n flowType: existingUser ? 'dataRequest' : 'onboarding',\r\n adminMode: data.adminMode,\r\n userCreated: data.userCreated,\r\n accountDetails: accountInfo || data.accountDetails || {\r\n email: email,\r\n createdAt: data.createdAt || new Date().toISOString(),\r\n provider: 'email'\r\n }\r\n });\r\n }, 1000);\r\n }\r\n } catch (error) {\r\n console.error('Email verification error:', error);\r\n setError(error.message || 'Invalid code. Please try again.');\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n const renderEmailStep = () => (\r\n <div className=\"w-full flex flex-col\" style={{ height: '100%' }}>\r\n {/* Content - Flexible center area */}\r\n <div className=\"px-12 pt-16 pb-8 text-center flex-1 flex flex-col\">\r\n <div className=\"mb-8\">\r\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2 text-balance leading-tight\">\r\n Use pre-existing Persona or create a new one in seconds\r\n </h1>\r\n <p className=\"text-gray-600 text-base\">Sign in or create an account</p>\r\n </div>\r\n\r\n <div className=\"mb-6\">\r\n <input\r\n type=\"email\"\r\n value={email}\r\n onChange={(e) => setEmail(e.target.value)}\r\n placeholder=\"Enter your email\"\r\n className=\"w-full max-w-sm mx-auto px-4 py-4 text-base bg-gray-50 border-0 rounded-xl !text-black placeholder:text-gray-400 focus:bg-white focus:ring-2 focus:ring-gray-200 outline-none transition-all duration-200\"\r\n style={{ \r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n WebkitTextFillColor: '#000000'\r\n }}\r\n required\r\n />\r\n </div>\r\n\r\n <div className=\"mb-6 text-center\">\r\n <span className=\"text-gray-500 text-sm\">Or</span>\r\n </div>\r\n\r\n <div className=\"mb-8 flex justify-center\">\r\n <GoogleLogin\r\n onSuccess={handleGoogleSuccess}\r\n onError={handleGoogleError}\r\n text=\"continue_with\"\r\n size=\"large\"\r\n shape=\"rectangular\"\r\n width=\"384\"\r\n logo_alignment=\"left\"\r\n />\r\n </div>\r\n\r\n {/* Error Display */}\r\n {error && (\r\n <div className=\"mb-6\">\r\n <p className=\"text-sm text-center\" style={{ color: COLORS.error }}>{error}</p>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Continue Button - Fixed at bottom */}\r\n <div className=\"px-12 pb-8 flex-shrink-0\">\r\n <button\r\n className=\"w-full max-w-sm mx-auto bg-gray-900 hover:bg-gray-800 text-white rounded-full py-4 text-base font-medium flex items-center justify-center gap-2 transition-colors disabled:opacity-50\"\r\n onClick={handleEmailSubmit}\r\n disabled={isLoading || !email.trim()}\r\n style={{ \r\n fontFamily: 'Inter, system-ui, sans-serif'\r\n }}\r\n >\r\n {isLoading ? 'Loading...' : 'Continue'}\r\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n\r\n const renderCodeStep = () => (\r\n <div className=\"w-full flex flex-col\" style={{ height: '100%' }}>\r\n {/* Ensure verification code inputs always render black text (host apps may inject global input styles) */}\r\n <style>{`\r\n /* High-specificity + !important so consuming apps can't easily override text color */\r\n input.onairos-verification-digit {\r\n color: #000000 !important;\r\n caret-color: #000000 !important;\r\n -webkit-text-fill-color: #000000 !important; /* Safari/iOS */\r\n }\r\n `}</style>\r\n {/* Heading - matching VerificationStep.tsx */}\r\n <div className=\"w-full pt-16 px-12 mb-10 text-center\">\r\n <h1 \r\n className=\"font-bold mb-2\"\r\n style={{ \r\n fontFamily: 'IBM Plex Sans, system-ui, sans-serif',\r\n fontWeight: '700',\r\n fontSize: '24px',\r\n lineHeight: '32px',\r\n color: COLORS.textPrimary\r\n }}\r\n >\r\n Enter verification code\r\n </h1>\r\n <p \r\n className=\"mb-2\"\r\n style={{ \r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n fontWeight: '400',\r\n fontSize: '16px',\r\n lineHeight: '24px',\r\n color: COLORS.textSecondary\r\n }}\r\n >\r\n {emailSent ? `We've sent a 6-digit code to ${email}` : `A verification code has been generated for ${email}`}\r\n </p>\r\n {!emailSent && (\r\n <div \r\n className=\"mb-4 mx-auto max-w-sm px-4 py-3 rounded-lg border\"\r\n style={{ \r\n backgroundColor: '#FEF3C7',\r\n borderColor: '#FCD34D',\r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n fontSize: '14px',\r\n lineHeight: '20px',\r\n color: '#92400E'\r\n }}\r\n >\r\n <p className=\"font-medium mb-1\">โš ๏ธ Email service unavailable</p>\r\n <p className=\"text-sm\">\r\n {emailServiceMessage.includes('testing mode') || emailServiceMessage.includes('server logs') \r\n ? 'Any 6-digit code will be accepted. Check server logs for the actual code.'\r\n : 'The verification code was generated but could not be sent. Please check server logs or contact support.'}\r\n </p>\r\n </div>\r\n )}\r\n </div>\r\n\r\n\r\n {/* Code Input - matching VerificationStep design with individual digit boxes */}\r\n <div className=\"px-12 mb-6\">\r\n <div className=\"flex justify-center space-x-3\">\r\n {Array.from({ length: 6 }, (_, index) => (\r\n <input\r\n key={index}\r\n type=\"text\"\r\n inputMode=\"numeric\"\r\n pattern=\"[0-9]*\"\r\n maxLength=\"1\"\r\n autoComplete={index === 0 ? \"one-time-code\" : \"off\"}\r\n value={codeDigits[index] || ''}\r\n onPaste={(e) => {\r\n const pasted = (e.clipboardData?.getData('text') || '').replace(/\\D/g, '');\r\n if (!pasted) return;\r\n e.preventDefault();\r\n\r\n const nextDigits = [...codeDigits];\r\n for (let i = 0; i < pasted.length && index + i < 6; i++) {\r\n nextDigits[index + i] = pasted[i];\r\n }\r\n setCodeDigits(nextDigits);\r\n\r\n const focusIndex = Math.min(index + pasted.length, 5);\r\n const nextInput = e.currentTarget.parentElement?.children?.[focusIndex];\r\n if (nextInput && typeof nextInput.focus === 'function') nextInput.focus();\r\n }}\r\n onChange={(e) => {\r\n const raw = e.target.value || '';\r\n const digitsOnly = raw.replace(/\\D/g, '');\r\n\r\n // Clear\r\n if (!digitsOnly) {\r\n const nextDigits = [...codeDigits];\r\n nextDigits[index] = '';\r\n setCodeDigits(nextDigits);\r\n return;\r\n }\r\n\r\n // Some browsers/OTP autofill can inject multiple digits at once\r\n const nextDigits = [...codeDigits];\r\n for (let i = 0; i < digitsOnly.length && index + i < 6; i++) {\r\n nextDigits[index + i] = digitsOnly[i];\r\n }\r\n setCodeDigits(nextDigits);\r\n\r\n const focusIndex = Math.min(index + digitsOnly.length, 5);\r\n if (focusIndex !== index) {\r\n const nextInput = e.target.parentElement?.children?.[focusIndex];\r\n if (nextInput && typeof nextInput.focus === 'function') nextInput.focus();\r\n } else if (index < 5) {\r\n const nextInput = e.target.parentElement?.children?.[index + 1];\r\n if (nextInput && typeof nextInput.focus === 'function') nextInput.focus();\r\n }\r\n }}\r\n onKeyDown={(e) => {\r\n // Handle backspace to focus previous input\r\n if (e.key === 'Backspace') {\r\n // If current has a digit, clear it first (common OTP UX)\r\n if (codeDigits[index]) {\r\n const nextDigits = [...codeDigits];\r\n nextDigits[index] = '';\r\n setCodeDigits(nextDigits);\r\n e.preventDefault();\r\n return;\r\n }\r\n // Otherwise move focus left\r\n if (index > 0) {\r\n const prevInput = e.currentTarget.parentElement?.children?.[index - 1];\r\n if (prevInput && typeof prevInput.focus === 'function') prevInput.focus();\r\n }\r\n }\r\n }}\r\n className=\"onairos-verification-digit w-12 h-12 border rounded-lg text-center text-lg font-medium focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none !text-black\"\r\n style={{ \r\n borderColor: COLORS.border,\r\n backgroundColor: COLORS.background,\r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n color: '#000000',\r\n caretColor: '#000000',\r\n WebkitTextFillColor: '#000000',\r\n }}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n\r\n {/* Error Display */}\r\n {error && (\r\n <div className=\"px-12 mb-6\">\r\n <p className=\"text-sm text-center\" style={{ color: COLORS.error }}>{error}</p>\r\n </div>\r\n )}\r\n\r\n {/* Continue Button - positioned right below code inputs */}\r\n <div className=\"px-12 mb-6\">\r\n <div className=\"max-w-sm mx-auto\">\r\n <PrimaryButton\r\n label=\"Continue\"\r\n onClick={handleCodeSubmit}\r\n loading={isLoading}\r\n disabled={isLoading || !isCodeComplete}\r\n testId=\"verify-code-button\"\r\n className=\"!text-white\"\r\n textStyle={{ color: '#FFFFFF' }}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Spacer */}\r\n <div style={{ flex: 1, minHeight: '20px' }} />\r\n\r\n {/* Back to email option */}\r\n <div className=\"px-12 w-full\">\r\n <div className=\"max-w-sm mx-auto\">\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n resetCodeDigits();\r\n setStep('email');\r\n }}\r\n className=\"w-full py-2 px-4 font-medium transition-colors text-sm\"\r\n style={{ color: COLORS.textSecondary }}\r\n >\r\n Use a different email\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n\r\n const renderSuccessStep = () => (\r\n <div className=\"w-full flex flex-col items-center space-y-6 pt-16 px-12\">\r\n <div \r\n className=\"flex items-center justify-center w-16 h-16 rounded-full\"\r\n style={{ backgroundColor: '#D1FAE5' }}\r\n >\r\n <Check className=\"w-8 h-8\" style={{ color: COLORS.success }} />\r\n </div>\r\n \r\n <div className=\"text-center space-y-2\">\r\n <h2 \r\n className=\"text-xl font-semibold\"\r\n style={{ color: COLORS.textPrimary }}\r\n >\r\n Email verified!\r\n </h2>\r\n <p style={{ color: COLORS.textSecondary }}>Setting up your account...</p>\r\n </div>\r\n\r\n <div className=\"w-8 h-8\">\r\n <div className=\"animate-spin h-8 w-8 border-2 border-blue-600 rounded-full border-t-transparent\"></div>\r\n </div>\r\n </div>\r\n );\r\n\r\n return (\r\n <div className=\"w-full\">\r\n {step === 'email' && renderEmailStep()}\r\n {step === 'code' && renderCodeStep()}\r\n {step === 'success' && renderSuccessStep()}\r\n </div>\r\n );\r\n} \r\n","/**\r\n * Capacitor/Mobile Environment Detection Utility\r\n * \r\n * Detects if the app is running in a Capacitor environment\r\n * and provides mobile-specific functionality\r\n */\r\n\r\n/**\r\n * Detect if running in Capacitor environment\r\n * @returns {boolean} True if running in Capacitor\r\n */\r\nexport const isCapacitor = () => {\r\n // Check for Capacitor global object\r\n if (typeof window !== 'undefined' && window.Capacitor) {\r\n return true;\r\n }\r\n \r\n // Check for Capacitor plugins\r\n if (typeof window !== 'undefined' && window.Capacitor?.Plugins) {\r\n return true;\r\n }\r\n \r\n // Check for Capacitor native bridge\r\n if (typeof window !== 'undefined' && window.webkit?.messageHandlers?.bridge) {\r\n return true;\r\n }\r\n \r\n return false;\r\n};\r\n\r\n/**\r\n * Detect if running in React Native environment\r\n * @returns {boolean} True if running in React Native\r\n */\r\nexport const isReactNative = () => {\r\n return typeof navigator !== 'undefined' && navigator.product === 'ReactNative' ||\r\n typeof global !== 'undefined' && global.nativeModuleProxy !== undefined;\r\n};\r\n\r\n/**\r\n * Detect if running in any mobile app environment (Capacitor or React Native)\r\n * @returns {boolean} True if running in a mobile app\r\n */\r\nexport const isMobileApp = () => {\r\n return isCapacitor() || isReactNative();\r\n};\r\n\r\n/**\r\n * Detect if running on iOS\r\n * @returns {boolean} True if running on iOS\r\n */\r\nexport const isIOS = () => {\r\n if (typeof window !== 'undefined' && window.Capacitor) {\r\n return window.Capacitor.getPlatform() === 'ios';\r\n }\r\n \r\n // Fallback to user agent detection\r\n return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;\r\n};\r\n\r\n/**\r\n * Detect if running on Android\r\n * @returns {boolean} True if running on Android\r\n */\r\nexport const isAndroid = () => {\r\n if (typeof window !== 'undefined' && window.Capacitor) {\r\n return window.Capacitor.getPlatform() === 'android';\r\n }\r\n \r\n // Fallback to user agent detection\r\n return /Android/.test(navigator.userAgent);\r\n};\r\n\r\n/**\r\n * Get platform information\r\n * @returns {Object} Platform details\r\n */\r\nexport const getPlatformInfo = () => {\r\n return {\r\n isCapacitor: isCapacitor(),\r\n isReactNative: isReactNative(),\r\n isMobileApp: isMobileApp(),\r\n isIOS: isIOS(),\r\n isAndroid: isAndroid(),\r\n platform: window.Capacitor ? window.Capacitor.getPlatform() : 'web',\r\n userAgent: navigator.userAgent\r\n };\r\n};\r\n\r\n/**\r\n * Detect if mobile browser (not Capacitor, just mobile web browser)\r\n * @returns {boolean} True if mobile browser\r\n */\r\nexport const isMobileBrowser = () => {\r\n if (isMobileApp()) {\r\n return false; // Capacitor/RN apps are not browsers\r\n }\r\n \r\n return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ||\r\n (window.innerWidth <= 768);\r\n};\r\n\r\n/**\r\n * Get environment type\r\n * @returns {string} Environment type: 'capacitor', 'react-native', 'mobile-browser', 'desktop-browser'\r\n */\r\nexport const getEnvironmentType = () => {\r\n if (isCapacitor()) return 'capacitor';\r\n if (isReactNative()) return 'react-native';\r\n if (isMobileBrowser()) return 'mobile-browser';\r\n return 'desktop-browser';\r\n};\r\n\r\n/**\r\n * Check if browser extension support is available\r\n * Browser extensions don't work in Capacitor/React Native\r\n * @returns {boolean} True if browser extensions are supported\r\n */\r\nexport const supportsBrowserExtensions = () => {\r\n return !isMobileApp();\r\n};\r\n\r\n/**\r\n * Log platform information for debugging\r\n */\r\nexport const logPlatformInfo = () => {\r\n const info = getPlatformInfo();\r\n console.log('๐Ÿ” Platform Detection:', info);\r\n console.log('๐Ÿ“ฑ Environment Type:', getEnvironmentType());\r\n console.log('๐Ÿงฉ Browser Extensions Supported:', supportsBrowserExtensions());\r\n return info;\r\n};\r\n\r\n\r\n\r\n","import React from 'react';\r\nimport { createPortal } from 'react-dom';\r\n\r\nconst BOOKMARKLET_HREF =\r\n \"javascript:(async()=>{let loader=null;function showLoader(msg){if(!loader){loader=document.createElement('div');loader.style.cssText='position:fixed;top:20px;right:20px;width:280px;background:rgba(15,23,42,0.95);color:white;padding:14px 20px;border-radius:12px;font-family:-apple-system,BlinkMacSystemFont,\\\"Segoe UI\\\",Roboto,sans-serif;font-size:13px;font-weight:500;z-index:999999;box-shadow:0 8px 24px rgba(0,0,0,0.4),0 2px 8px rgba(0,0,0,0.2);border:1px solid rgba(255,255,255,0.1);backdrop-filter:blur(12px);line-height:1.4;text-align:center';document.body.appendChild(loader)}loader.textContent=msg}function hideLoader(){if(loader){loader.remove();loader=null}}function h(){try{const e=window.location.hostname||'';return e==='chat.openai.com'||e==='chatgpt.com'||e.endsWith('.chatgpt.com')}catch{return false}}function getDeviceId(){try{const c=document.cookie.match(/oai-did=([^;]+)/);return c?c[1]:null}catch{return null}}async function getAccessToken(){const url=`${window.location.origin}/api/auth/session`;const r=await fetch(url,{method:'GET',credentials:'include',headers:{'Accept':'application/json','Referer':window.location.origin}});if(!r.ok)return null;const data=await r.json();return data?.accessToken||null}async function fetchList(token,deviceId){const url=`${window.location.origin}/backend-api/conversations?offset=0&limit=10`;const headers={'Accept':'*/*','oai-language':'en-US'};if(token)headers['Authorization']=`Bearer ${token}`;if(deviceId)headers['oai-device-id']=deviceId;const r=await fetch(url,{method:'GET',credentials:'include',headers});if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()}async function fetchConvo(id,token,deviceId){const url=`${window.location.origin}/backend-api/conversation/${id}`;const headers={'Accept':'*/*','oai-language':'en-US','Referer':window.location.origin};if(token)headers['Authorization']=`Bearer ${token}`;if(deviceId)headers['oai-device-id']=deviceId;const r=await fetch(url,{method:'GET',credentials:'include',headers});if(!r.ok)throw new Error(`HTTP ${r.status}`);return r.json()}async function fetchMemories(token,deviceId){const url=`${window.location.origin}/backend-api/memories?include_memory_entries=true&memory_entries_filter=all`;const headers={'Accept':'application/json','Referer':window.location.origin};if(token)headers['Authorization']=`Bearer ${token}`;if(deviceId)headers['oai-device-id']=deviceId;try{const r=await fetch(url,{method:'GET',credentials:'include',headers});if(!r.ok)return null;return r.json()}catch{return null}}function extractUserMessages(data){const mapping=data?.mapping||{};const msgs=[];for(const node of Object.values(mapping)){const msg=node?.message;if(!msg||!msg.author)continue;if(msg.author.role!=='user')continue;const time=msg.create_time?new Date(msg.create_time*1000).toISOString():null;let text='';const content=msg.content||{};if(Array.isArray(content.parts)){text=content.parts.join('\\\\n').trim()}else if(content.text){text=content.text.trim()}if(text){msgs.push({content:text,timestamp:time})}}return msgs}if(!h()){alert('โš ๏ธ Please open ChatGPT and try again.');return}const popup=window.open('about:blank','OnairosSync','width=500,height=600');if(!popup){alert('โš ๏ธ Please allow popups for ChatGPT to sync with Onairos!\\\\n\\\\nEnable popups and try again.');return}popup.document.write('<html><head><title>Onairos Sync</title><style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:\\\"Sรถhne\\\",-apple-system,BlinkMacSystemFont,\\\"Segoe UI\\\",Helvetica,Arial,sans-serif;background:#0D0D0D;color:#ECECEC;display:flex;align-items:center;justify-content:center;min-height:100vh;padding:20px}.container{max-width:450px;width:100%;background:#212121;border-radius:16px;padding:32px;box-shadow:0 4px 24px rgba(0,0,0,0.4)}h1{font-size:24px;font-weight:600;text-align:center;margin-bottom:8px}.subtitle{font-size:14px;color:#8E8EA0;text-align:center;margin-bottom:32px}.status-text{text-align:center;font-size:16px;margin-bottom:16px}.spinner{width:40px;height:40px;border:3px solid #2F2F2F;border-top-color:#10A37F;border-radius:50%;animation:spin 0.6s linear infinite;margin:0 auto 16px}@keyframes spin{to{transform:rotate(360deg)}}</style></head><body><div class=\\\"container\\\"><h1>โœจ Onairos Sync</h1><p class=\\\"subtitle\\\">Collecting your ChatGPT data</p><div class=\\\"spinner\\\"></div><div class=\\\"status-text\\\" id=\\\"status\\\">Starting...</div></div></body></html>');popup.document.close();function updatePopup(msg){try{if(popup&&!popup.closed){popup.document.getElementById('status').textContent=msg}}catch(e){}}showLoader('๐Ÿš€ Starting export...');console.log('[Onairos] ๐Ÿš€ Starting export...');(async()=>{try{updatePopup('๐Ÿ”‘ Getting access token...');showLoader('๐Ÿ”‘ Getting access token...');const token=await getAccessToken();const deviceId=getDeviceId();if(!token){hideLoader();updatePopup('โŒ Could not get access token. Make sure you\\\\'re logged into ChatGPT.');setTimeout(()=>popup.close(),5000);return}updatePopup('๐Ÿ“‹ Fetching conversations...');showLoader('๐Ÿ“‹ Fetching conversations...');let list;try{list=await fetchList(token,deviceId)}catch(err){hideLoader();updatePopup('โŒ Failed: '+err.message);setTimeout(()=>popup.close(),5000);return}const items=(list?.items||[]).slice(0,10);if(items.length===0){hideLoader();updatePopup('โš ๏ธ No conversations found');setTimeout(()=>popup.close(),3000);return}const convos=[];for(let i=0;i<items.length;i++){const c=items[i];updatePopup(`๐Ÿ“ฅ ${i+1}/${items.length}: ${c.title||'Untitled'}...`);showLoader(`๐Ÿ“ฅ ${i+1}/${items.length}: ${c.title||'Untitled'}...`);try{const data=await fetchConvo(c.id,token,deviceId);const userMsgs=extractUserMessages(data);convos.push({id:c.id,title:c.title||'Untitled',url:`${window.location.origin}/c/${c.id}`,messageCount:userMsgs.length,messages:userMsgs})}catch(err){convos.push({id:c.id,title:c.title||'Untitled',error:err.message})}}updatePopup('๐Ÿง  Fetching memories...');showLoader('๐Ÿง  Fetching memories...');const memories=await fetchMemories(token,deviceId);updatePopup('๐Ÿ’พ Syncing to Onairos...');showLoader('๐Ÿ’พ Syncing to Onairos...');const userData=JSON.parse(localStorage.getItem('onairosUser')||'{}');let jwtToken=userData.token||localStorage.getItem('onairos_user_token');if(!jwtToken){hideLoader();updatePopup('โŒ Please log into Onairos first');setTimeout(()=>popup.close(),5000);return}const syncData={convos,memories,token:jwtToken};updatePopup('๐Ÿ”„ Opening sync page...');const form=popup.document.createElement('form');form.method='POST';form.action='https://api2.onairos.uk/chatgpt-sync';form.style.display='none';const input=popup.document.createElement('input');input.type='hidden';input.name='data';input.value=JSON.stringify(syncData);form.appendChild(input);popup.document.body.appendChild(form);form.submit();hideLoader();console.log('โœ… [Onairos] Submitting sync form')}catch(e){hideLoader();updatePopup('โŒ Error: '+e.message);console.error(e);setTimeout(()=>popup.close(),5000)}})()})();\";\r\n\r\nexport const getOnairosChatGPTBookmarklet = () => BOOKMARKLET_HREF;\r\n\r\nexport default function ConnectChatGPTModal({ open, onClose, onConnected }) {\r\n // Debug log to confirm render attempt\r\n if (open) {\r\n console.log('๐Ÿš€ ConnectChatGPTModal rendering! Open:', open);\r\n }\r\n\r\n if (!open) return null;\r\n\r\n // Get user token from localStorage to embed in bookmarklet\r\n const getUserToken = () => {\r\n try {\r\n // Try onairos_user_token first\r\n const directToken = localStorage.getItem('onairos_user_token');\r\n if (directToken) return directToken;\r\n \r\n // Try onairosUser.token\r\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\r\n if (userData.token) return userData.token;\r\n \r\n return null;\r\n } catch (e) {\r\n console.error('Error getting token:', e);\r\n return null;\r\n }\r\n };\r\n\r\n const userToken = getUserToken();\r\n console.log('๐Ÿ”‘ User token for bookmarklet:', userToken ? userToken.substring(0, 20) + '...' : 'NOT FOUND');\r\n\r\n // Create bookmarklet with embedded token\r\n const createBookmarkletWithToken = (token) => {\r\n if (!token) {\r\n // Fallback to original bookmarklet that checks localStorage\r\n return BOOKMARKLET_HREF;\r\n }\r\n \r\n // Embed the token directly in the bookmarklet\r\n return BOOKMARKLET_HREF.replace(\r\n 'const userData=JSON.parse(localStorage.getItem(\\'onairosUser\\')||\\'{}\\')',\r\n `const userData={token:'${token}'}`\r\n );\r\n };\r\n\r\n const bookmarkletHref = createBookmarkletWithToken(userToken);\r\n\r\n const handleGotIt = () => {\r\n if (typeof onConnected === 'function') {\r\n onConnected();\r\n }\r\n if (typeof onClose === 'function') {\r\n onClose();\r\n }\r\n };\r\n\r\n // Use a portal to break out of any parent transforms/overflows\r\n return createPortal(\r\n <div style={{ position: 'fixed', inset: 0, zIndex: 2147483647, pointerEvents: 'auto' }}>\r\n <style>{`\r\n @keyframes gentlePulse {\r\n 0%, 100% {\r\n box-shadow: 0 0 0 0 rgba(148, 163, 184, 0.35);\r\n }\r\n 50% {\r\n box-shadow: 0 0 0 10px rgba(148, 163, 184, 0);\r\n }\r\n }\r\n .bookmarklet-button {\r\n background: rgba(15, 23, 42, 0.85);\r\n border-radius: 9999px;\r\n border: 1px solid rgba(255,255,255,0.16);\r\n backdrop-filter: blur(18px);\r\n }\r\n .bookmarklet-button:hover {\r\n background: rgba(15, 23, 42, 0.92);\r\n }\r\n @keyframes fadeInScale {\r\n 0% { opacity: 0; transform: translateY(8px) scale(0.96); }\r\n 100% { opacity: 1; transform: translateY(0) scale(1); }\r\n }\r\n .chatgpt-modal-card {\r\n animation: fadeInScale 200ms cubic-bezier(0.16, 1, 0.3, 1);\r\n }\r\n .step-circle {\r\n background: rgba(15, 23, 42, 0.9);\r\n min-width: 28px;\r\n width: 28px;\r\n height: 28px;\r\n }\r\n .chatgpt-got-it-button {\r\n color: #FFFFFF !important;\r\n background-color: rgba(15, 23, 42, 0.8) !important;\r\n }\r\n .chatgpt-got-it-button:hover {\r\n background-color: rgba(15, 23, 42, 0.9) !important;\r\n }\r\n .chatgpt-got-it-button * {\r\n color: #FFFFFF !important;\r\n }\r\n .chatgpt-got-it-button span {\r\n color: #FFFFFF !important;\r\n }\r\n /* Mobile browser specific styling */\r\n @media (max-width: 768px) {\r\n .chatgpt-modal-backdrop {\r\n align-items: flex-end !important;\r\n padding: 0 !important;\r\n }\r\n .chatgpt-modal-card {\r\n max-width: 100% !important;\r\n height: 100% !important;\r\n max-height: 100% !important;\r\n border-radius: 24px 24px 0 0 !important;\r\n animation: slideUpFromBottom 300ms cubic-bezier(0.16, 1, 0.3, 1) !important;\r\n }\r\n }\r\n @keyframes slideUpFromBottom {\r\n 0% { transform: translateY(100%); }\r\n 100% { transform: translateY(0); }\r\n }\r\n `}</style>\r\n\r\n <div \r\n className=\"chatgpt-modal-backdrop fixed inset-0 flex items-center justify-center p-4 bg-black/60\" \r\n style={{ zIndex: 2147483647 }}\r\n >\r\n <div \r\n className=\"chatgpt-modal-card w-full max-w-md rounded-3xl shadow-2xl border border-white/10 overflow-hidden text-white relative\"\r\n style={{\r\n background: 'linear-gradient(135deg, rgba(15, 23, 42, 0.95) 0%, rgba(30, 41, 59, 0.92) 50%, rgba(15, 23, 42, 0.95) 100%)',\r\n boxShadow: 'inset 0 1px 0 0 rgba(255, 255, 255, 0.1), 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 100px rgba(148, 163, 184, 0.15)'\r\n }}\r\n >\r\n <div className=\"relative px-5 py-4 border-b border-white/10 bg-white/5\">\r\n <button\r\n onClick={onClose}\r\n className=\"absolute right-4 top-4 p-2 hover:bg-white/10 rounded-full transition-colors z-50 cursor-pointer\"\r\n aria-label=\"Close\"\r\n >\r\n <svg\r\n className=\"w-5 h-5 text-slate-300\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M6 18L18 6M6 6l12 12\"\r\n />\r\n </svg>\r\n </button>\r\n\r\n <h2 className=\"text-xl font-semibold pr-8 text-white\">\r\n Connect ChatGPT\r\n </h2>\r\n <p className=\"text-sm mt-0.5 text-white\">\r\n Three quick steps to import your conversations\r\n </p>\r\n\r\n <div className=\"mt-3 flex items-start gap-2 bg-white/12 rounded-2xl px-3 py-2\">\r\n <svg\r\n className=\"w-4 h-4 text-emerald-300 mt-0.5 flex-shrink-0\"\r\n fill=\"currentColor\"\r\n viewBox=\"0 0 20 20\"\r\n >\r\n <path\r\n fillRule=\"evenodd\"\r\n d=\"M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\"\r\n clipRule=\"evenodd\"\r\n />\r\n </svg>\r\n <p className=\"text-xs leading-relaxed text-white\">\r\n <strong className=\"font-semibold\">Private &amp; secure.</strong>{' '}\r\n We only access your chat history. No one else sees this data.\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"px-5 py-4 space-y-4\">\r\n <div className=\"flex gap-3\">\r\n <div className=\"flex-shrink-0\">\r\n <div className=\"step-circle rounded-full flex items-center justify-center\">\r\n <span className=\"text-white font-bold text-sm\">1</span>\r\n </div>\r\n </div>\r\n <div className=\"flex-1 pt-0.5\">\r\n <h3 className=\"text-sm font-semibold mb-1 text-white\">\r\n Drag this button to your bookmarks bar\r\n </h3>\r\n <div className=\"relative inline-block mt-2\">\r\n <div\r\n className=\"absolute inset-0 rounded-full\"\r\n style={{ animation: 'gentlePulse 2s ease-in-out infinite' }}\r\n />\r\n <a\r\n href={bookmarkletHref}\r\n title=\"โœจ Onairos ChatGPT Sync\"\r\n draggable=\"true\"\r\n onDragStart={(e) => {\r\n try {\r\n // Set the bookmark URL\r\n e.dataTransfer.setData('text/uri-list', bookmarkletHref);\r\n e.dataTransfer.setData('text/plain', bookmarkletHref);\r\n \r\n // IMPORTANT: Set bookmark title for different browsers\r\n // Firefox uses text/x-moz-url format: URL\\nTitle\r\n e.dataTransfer.setData('text/x-moz-url', `${bookmarkletHref}\\nโœจ Onairos ChatGPT`);\r\n \r\n // Chrome/Safari: Set via DownloadURL\r\n e.dataTransfer.setData('DownloadURL', `application/javascript:โœจ Onairos ChatGPT:${bookmarkletHref}`);\r\n \r\n e.dataTransfer.effectAllowed = 'copy';\r\n console.log('โœ… Bookmarklet drag started with title: โœจ Onairos ChatGPT');\r\n } catch (err) {\r\n console.warn('Drag start error:', err);\r\n }\r\n }}\r\n onClick={(e) => {\r\n e.preventDefault();\r\n alert('โœจ Please drag this button to your bookmarks bar!\\n\\nTip: Press Ctrl+Shift+B (or Cmd+Shift+B on Mac) to show your bookmarks bar.');\r\n }}\r\n className=\"bookmarklet-button relative inline-flex items-center gap-1.5 px-4 py-2 font-medium cursor-move select-none transition-all hover:scale-[1.03]\"\r\n suppressHydrationWarning\r\n >\r\n <span className=\"text-base\">โœจ</span>\r\n <span className=\"text-sm\">Onairos ChatGPT</span>\r\n </a>\r\n </div>\r\n <p className=\"text-xs mt-2 text-slate-200\">\r\n <kbd className=\"px-1.5 py-0.5 bg-white/10 rounded-full text-[10px] font-mono border border-white/10 text-slate-50\">\r\n Ctrl+Shift+B\r\n </kbd>{' '}\r\n (or{' '}\r\n <kbd className=\"px-1.5 py-0.5 bg-white/10 rounded-full text-[10px] font-mono border border-white/10 text-slate-50\">\r\n Cmd+Shift+B\r\n </kbd>{' '}\r\n on Mac) to show bookmarks bar\r\n </p>\r\n </div>\r\n </div>\r\n\r\n <div className=\"border-t border-white/10 ml-10\" />\r\n\r\n <div className=\"flex gap-3\">\r\n <div className=\"flex-shrink-0\">\r\n <div className=\"step-circle rounded-full flex items-center justify-center\">\r\n <span className=\"text-white font-bold text-sm\">2</span>\r\n </div>\r\n </div>\r\n <div className=\"flex-1 pt-0.5\">\r\n <h3 className=\"text-sm font-semibold mb-1 text-white\">\r\n Open ChatGPT and log in\r\n </h3>\r\n <p className=\"text-xs mb-2 text-slate-200\">\r\n Make sure you're logged into your ChatGPT account\r\n </p>\r\n <button\r\n type=\"button\"\r\n onClick={() => {\r\n window.open('https://chat.openai.com', '_blank', 'noopener,noreferrer');\r\n }}\r\n className=\"inline-flex items-center gap-1.5 px-4 py-2 rounded-full text-xs font-medium transition-all hover:scale-[1.02] active:scale-[0.98]\"\r\n style={{\r\n background: 'linear-gradient(135deg, #10a37f 0%, #0d9270 100%)',\r\n color: '#ffffff',\r\n boxShadow: '0 0 25px rgba(16, 163, 127, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.2)'\r\n }}\r\n >\r\n <svg\r\n className=\"w-3.5 h-3.5\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n viewBox=\"0 0 24 24\"\r\n >\r\n <path\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n strokeWidth={2}\r\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"\r\n />\r\n </svg>\r\n Open ChatGPT\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div className=\"border-t border-white/10 ml-10\" />\r\n\r\n <div className=\"flex gap-3\">\r\n <div className=\"flex-shrink-0\">\r\n <div className=\"step-circle rounded-full flex items-center justify-center\">\r\n <span className=\"text-white font-bold text-sm\">3</span>\r\n </div>\r\n </div>\r\n <div className=\"flex-1 pt-0.5\">\r\n <h3 className=\"text-sm font-semibold mb-1 text-white\">\r\n Click the bookmark on ChatGPT\r\n </h3>\r\n <p className=\"text-xs text-slate-200\">\r\n Click the <strong className=\"text-white\">&quot;Onairos ChatGPT&quot;</strong>{' '}\r\n bookmark you added. We&apos;ll securely import your last 10 conversations.\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div className=\"px-5 py-4 bg-white/5 border-t border-white/10\">\r\n <button\r\n type=\"button\"\r\n onClick={handleGotIt}\r\n className=\"w-full px-4 py-2.5 rounded-full font-medium text-sm transition-all hover:scale-[1.01] active:scale-[0.99] shadow-[0_10px_30px_rgba(15,23,42,0.45)] border border-white/40 chatgpt-got-it-button\"\r\n >\r\n <span>Got it! โœ“</span>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>,\r\n document.body\r\n );\r\n}\r\n\r\n\r\n","import React, { useEffect, useId, useState, useRef } from 'react';\nimport { Browser } from '@capacitor/browser';\nimport Lottie from 'lottie-react';\nimport personaAnim from '../../public/persona-anim.json';\nimport { isMobileApp, isMobileBrowser } from '../utils/capacitorDetection';\nimport ConnectChatGPTModal from './ConnectChatGPTModal.jsx';\n\n// Mobile detection\nconst isMobile = () => {\n if (typeof window === 'undefined') return false;\n return isMobileApp() || isMobileBrowser() || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n};\nconst chatgptIcon = 'https://anushkasirv.sirv.com/openai.png';\nconst claudeIcon = 'https://anushkasirv.sirv.com/claude-color.png';\nconst geminiIcon = 'https://anushkasirv.sirv.com/gemini-color.png';\nconst grokIcon = 'https://anushkasirv.sirv.com/grok.png';\n\nconst sdkConfig = {\n apiKey: process.env.REACT_APP_ONAIROS_API_KEY || 'ona_VvoHNg1fdCCUa9eBy4Iz3IfvXdgLfMFI7TNcyHLDKEadPogkbjAeE2iDOs6M7Aey',\n baseUrl: process.env.REACT_APP_ONAIROS_BASE_URL || 'https://api2.onairos.uk',\n sdkType: 'web',\n enableHealthMonitoring: true,\n enableAutoRefresh: true,\n enableConnectionValidation: true,\n};\n\nconst fadeSlideInKeyframes = `\n@keyframes fadeSlideIn {\n from { opacity: 0; transform: translateX(var(--slide-x)); }\n to { opacity: 1; transform: translateX(0); }\n}\n`;\n\nexport default function UniversalOnboarding({ onComplete, onBack, appIcon, appName, username, testMode, priorityPlatform, rawMemoriesOnly, rawMemoriesConfig, isMobile: isMobileProp = false }) {\n const lottieRef = useRef(null);\n const lastFrameRef = useRef(0);\n const rafRef = useRef(null);\n\n const [connectedAccounts, setConnectedAccounts] = useState({});\n const [isConnecting, setIsConnecting] = useState(false);\n const [connectingPlatform, setConnectingPlatform] = useState(null);\n const [selected, setSelected] = useState('Instagram');\n const [currentPage, setCurrentPage] = useState(1);\n const [showChatGPTModal, setShowChatGPTModal] = useState(false);\n\n // swipe state\n const touchStartX = useRef(0);\n const touchDeltaX = useRef(0);\n\n // Mobile detection - use prop if provided (from layout), else detect\n // Only use actual mobile device detection, not window width (to avoid false positives from dev tools)\n const isActualMobileDevice = typeof navigator !== 'undefined' && \n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n const isNativePlatform = typeof window !== 'undefined' && \n window.Capacitor?.isNativePlatform?.() === true;\n const isMobile = isMobileProp || isNativePlatform || isActualMobileDevice;\n\n const [vh, setVh] = useState(() => (typeof window !== 'undefined' ? window.innerHeight : 800));\n useEffect(() => {\n const onResize = () => setVh(window.innerHeight);\n window.addEventListener('resize', onResize);\n return () => window.removeEventListener('resize', onResize);\n }, []);\n\n const FOOTER_H = 88;\n\n // MOBILE ONLY: persona placement / sizing - GIVE MORE SPACE TO PERSONA\n const isSmallMobile = isMobile && vh < 700;\n // Desktop adjustments: Reduce persona size and top position to fit modal without scroll\n // We allow overlap on desktop if needed\n const personaSide = isMobile \n ? (isSmallMobile ? Math.min(vh * 0.46, 420) : Math.min(vh * 0.52, 480))\n : Math.min(vh * 0.45, 420); // Desktop: allow larger size, will position absolutely\n \n const PERSONA_TOP = isMobile \n ? (isSmallMobile ? 28 : 44) \n : 40; // Desktop: Higher up\n\n // MOBILE ONLY: icon layout - PUSH ICONS DOWN significantly\n // Desktop: Adjust spacing to fit\n const SLOT = isMobile \n ? Math.max(50, Math.min(60, Math.floor(vh * 0.07)))\n : 60; // Desktop: fixed reasonable size\n const CIRCLE = isMobile \n ? (isSmallMobile ? 36 : 40)\n : 40; // Desktop: fixed reasonable size\n const GAP_PAGE1 = isMobile ? 10 : 12; // Desktop: original\n const GAP_PAGE2 = isMobile ? 18 : 20; // Desktop: original\n const ACTIVE_SCALE = isMobile \n ? (vh < 760 ? 1.15 : 1.25)\n : 1.2; // Desktop: standard scale\n\n const ICONS_H = isMobile \n ? (isSmallMobile ? 70 : 80)\n : 76; // Desktop: tighter height\n const ICONS_TOP_OFFSET = isMobile \n ? Math.max(200, Math.min(280, Math.round(vh * 0.32)))\n : 200; // Desktop: unused but kept for ref\n\n const igGradId = useId();\n\n // ---- official brand SVGs (compact, consistent viewboxes) ----\n const Brand = {\n ChatGPT: <img src={chatgptIcon} alt=\"ChatGPT\" style={{ width: 20, height: 20, objectFit: 'contain' }} />,\n Claude: <img src={claudeIcon} alt=\"Claude\" style={{ width: 20, height: 20, objectFit: 'contain' }} />,\n Gemini: <img src={geminiIcon} alt=\"Gemini\" style={{ width: 20, height: 20, objectFit: 'contain' }} />,\n Grok: <img src={grokIcon} alt=\"Grok\" style={{ width: 20, height: 20, objectFit: 'contain' }} />,\n Instagram: (\n <svg viewBox=\"0 0 24 24\" aria-hidden width=\"100%\" height=\"100%\">\n <defs>\n <radialGradient id={igGradId} cx=\"0.5\" cy=\"1\" r=\"1\">\n <stop offset=\"0%\" stopColor=\"#FDBB4B\"/>\n <stop offset=\"40%\" stopColor=\"#E95950\"/>\n <stop offset=\"70%\" stopColor=\"#BC2A8D\"/>\n <stop offset=\"100%\" stopColor=\"#4C68D7\"/>\n </radialGradient>\n </defs>\n <path fill={`url(#${igGradId})`} d=\"M7 2h10a5 5 0 0 1 5 5v10a5 5 0 0 1-5 5H7a5 5 0 0 1-5-5V7a5 5 0 0 1 5-5zm5 5.5A4.5 4.5 0 1 0 16.5 12 4.5 4.5 0 0 0 12 7.5zm0 7.4A2.9 2.9 0 1 1 14.9 12 2.9 2.9 0 0 1 12 14.9Zm5.35-8.25a1.15 1.15 0 1 0 1.15 1.15 1.15 1.15 0 0 0-1.15-1.15Z\"/>\n </svg>\n ),\n YouTube: (\n <svg viewBox=\"0 0 24 24\" aria-hidden width=\"100%\" height=\"100%\">\n <path fill=\"#FF0000\" d=\"M22.54 6.42a3 3 0 0 0-2.11-2.12C18.49 3.75 12 3.75 12 3.75s-6.49 0-8.43.55A3 3 0 0 0 1.46 6.42 31.63 31.63 0 0 0 1 12a31.63 31.63 0 0 0 .46 5.58 3 3 0 0 0 2.11 2.12C5.51 20.25 12 20.25 12 20.25s6.49 0 8.43-.55a3 3 0 0 0 2.11-2.12A31.63 31.63 0 0 0 23 12a31.63 31.63 0 0 0-.46-5.58z\"/>\n <path fill=\"#FFF\" d=\"M10 8.75v6.5l6-3.25-6-3.25z\"/>\n </svg>\n ),\n Reddit: (\n <img src=\"https://upload.wikimedia.org/wikipedia/en/b/bd/Reddit_Logo_Icon.svg\" alt=\"Reddit\" width=\"100%\" height=\"100%\" />\n ),\n LinkedIn: (\n <img src=\"https://upload.wikimedia.org/wikipedia/commons/c/ca/LinkedIn_logo_initials.png\" alt=\"LinkedIn\" width=\"100%\" height=\"100%\" />\n ),\n Twitter: (\n <svg viewBox=\"0 0 24 24\" aria-hidden width=\"100%\" height=\"100%\">\n <path fill=\"#1DA1F2\" d=\"M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z\"/>\n </svg>\n ),\n };\n\n const aiLinks = {\n ChatGPT: 'https://chat.openai.com',\n Claude: 'https://claude.ai',\n Gemini: 'https://gemini.google.com',\n Grok: 'https://grok.x.ai',\n };\n\n const descriptions = {\n ChatGPT: <>We analyze your <strong className=\"font-semibold\">prompt style</strong> and <strong className=\"font-semibold\">chat history</strong> to match your writing and thinking patterns.</>,\n Claude: <>We learn your <strong className=\"font-semibold\">document workflow</strong> and <strong className=\"font-semibold\">reasoning preferences</strong> to tune output format and detail.</>,\n Gemini: <>We study your <strong className=\"font-semibold\">search patterns</strong> and <strong className=\"font-semibold\">multimodal usage</strong> to improve response accuracy.</>,\n Grok: <>We adapt to your <strong className=\"font-semibold\">X posting style</strong> and <strong className=\"font-semibold\">meme literacy</strong> to match your tone.</>,\n Twitter: <>We analyze your <strong className=\"font-semibold\">tweets</strong> and <strong className=\"font-semibold\">interests</strong> to understand your preferences.</>,\n YouTube: <>We study your <strong className=\"font-semibold\">watch history</strong> and <strong className=\"font-semibold\">interactions</strong> to learn your interests.</>,\n Reddit: <>We examine your <strong className=\"font-semibold\">search history</strong> and <strong className=\"font-semibold\">discussions</strong> to understand your interests.</>,\n Instagram: <>We analyze your <strong className=\"font-semibold\">photos</strong> and <strong className=\"font-semibold\">interactions</strong> to learn visual preferences.</>,\n LinkedIn: <>We study your <strong className=\"font-semibold\">professional graph</strong> and <strong className=\"font-semibold\">content</strong> to understand career interests.</>,\n };\n\n const allPlatforms = [\n // Page 1\n { name: 'Instagram', connector: 'instagram', icon: Brand.Instagram },\n { name: 'YouTube', connector: 'youtube', icon: Brand.YouTube },\n { name: 'ChatGPT', connector: 'chatgpt', icon: Brand.ChatGPT, directLink: aiLinks.ChatGPT },\n // Page 2\n { name: 'Claude', connector: 'claude', icon: Brand.Claude, directLink: aiLinks.Claude },\n { name: 'Gemini', connector: 'gemini', icon: Brand.Gemini, directLink: aiLinks.Gemini },\n { name: 'Twitter', connector: 'twitter', icon: Brand.Twitter },\n // Page 3\n { name: 'LinkedIn', connector: 'linkedin', icon: Brand.LinkedIn },\n { name: 'Reddit', connector: 'reddit', icon: Brand.Reddit },\n { name: 'Grok', connector: 'grok', icon: Brand.Grok, directLink: aiLinks.Grok },\n ];\n\n const getPlatformsForPage = (page) => {\n if (page === 1) return allPlatforms.slice(0, 3);\n if (page === 2) return allPlatforms.slice(3, 6);\n return allPlatforms.slice(6);\n };\n\n const platforms = getPlatformsForPage(currentPage);\n\n useEffect(() => {\n // Listener for immediate UI update from deep link (when component is already mounted)\n const handleAuthSuccess = (e) => {\n const { platform } = e.detail;\n console.log(`โšก๏ธ Event received: OAuth success for ${platform}`);\n const plat = allPlatforms.find((p) => p.connector === platform);\n if (plat) {\n setConnectedAccounts((s) => {\n // Read existing connections from localStorage, not from stale state\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\n const existingArray = userData.connectedAccounts || [];\n const existingObj = Array.isArray(existingArray) \n ? existingArray.reduce((acc, p) => ({ ...acc, [p]: true }), {})\n : {};\n \n // Merge with new connection\n const updated = { ...existingObj, [plat.name]: true };\n const connectedArray = Object.entries(updated).filter(([, v]) => v).map(([k]) => k);\n userData.connectedAccounts = connectedArray;\n localStorage.setItem('onairosUser', JSON.stringify(userData));\n console.log(`๐Ÿ’พ Saved ${plat.name} to localStorage (event):`, connectedArray);\n return updated;\n });\n }\n };\n if (typeof window !== 'undefined') {\n window.addEventListener('onairos-oauth-success', handleAuthSuccess);\n }\n\n // Check for OAuth success on mount (after redirect back from mobile)\n const checkOAuthSuccess = () => {\n // 1. Check URL-based return signal (from OnairosButton or direct URL params)\n // Note: OnairosButton cleans up URL params, so we might check sessionStorage set by it\n const sessionSuccess = sessionStorage.getItem('onairos_oauth_return_success');\n const sessionPlatform = sessionStorage.getItem('onairos_oauth_return_platform');\n \n if (sessionSuccess === 'true' && sessionPlatform) {\n console.log(`โœ… ${sessionPlatform} OAuth detected via session signal`);\n const plat = allPlatforms.find((p) => p.connector === sessionPlatform);\n if (plat) {\n setConnectedAccounts((s) => {\n // Read existing connections from localStorage, not from stale state\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\n const existingArray = userData.connectedAccounts || [];\n const existingObj = Array.isArray(existingArray) \n ? existingArray.reduce((acc, p) => ({ ...acc, [p]: true }), {})\n : {};\n \n // Merge with new connection\n const updated = { ...existingObj, [plat.name]: true };\n const connectedArray = Object.entries(updated).filter(([, v]) => v).map(([k]) => k);\n userData.connectedAccounts = connectedArray;\n localStorage.setItem('onairosUser', JSON.stringify(userData));\n console.log(`๐Ÿ’พ Saved ${plat.name} to localStorage (session):`, connectedArray);\n return updated;\n });\n }\n // Clean up\n sessionStorage.removeItem('onairos_oauth_return_success');\n sessionStorage.removeItem('onairos_oauth_return_platform');\n return;\n }\n\n // 2. Fallback to existing localStorage logic (same-domain or preserved state)\n const oauthContext = localStorage.getItem('onairos_oauth_context');\n const platformConnector = localStorage.getItem('onairos_oauth_platform');\n \n // Only process if we're coming back from platform connector flow\n if (oauthContext === 'platform-connector' && platformConnector) {\n const localStorageKey = `onairos_${platformConnector}_success`;\n const timestampKey = `onairos_${platformConnector}_timestamp`;\n const success = localStorage.getItem(localStorageKey);\n const timestamp = localStorage.getItem(timestampKey);\n \n if (success === 'true' && timestamp) {\n const timestampNum = parseInt(timestamp, 10);\n const now = Date.now();\n \n // Only process if timestamp is recent (within last 30 seconds)\n if (now - timestampNum < 30000) {\n console.log(`โœ… ${platformConnector} OAuth completed - processing redirect back`);\n \n // Find platform by connector\n const plat = allPlatforms.find((p) => p.connector === platformConnector);\n if (plat) {\n // Mark as connected\n setConnectedAccounts((s) => {\n // Read existing connections from localStorage, not from stale state\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\n const existingArray = userData.connectedAccounts || [];\n const existingObj = Array.isArray(existingArray) \n ? existingArray.reduce((acc, p) => ({ ...acc, [p]: true }), {})\n : {};\n \n // Merge with new connection\n const updated = { ...existingObj, [plat.name]: true };\n const connectedArray = Object.entries(updated).filter(([, v]) => v).map(([k]) => k);\n userData.connectedAccounts = connectedArray;\n localStorage.setItem('onairosUser', JSON.stringify(userData));\n console.log(`๐Ÿ’พ Saved ${plat.name} to localStorage (context):`, connectedArray);\n return updated;\n });\n }\n \n // Clean up localStorage\n localStorage.removeItem(localStorageKey);\n localStorage.removeItem(timestampKey);\n localStorage.removeItem('onairos_oauth_context');\n localStorage.removeItem('onairos_oauth_platform');\n localStorage.removeItem('onairos_return_url');\n }\n }\n }\n };\n\n checkOAuthSuccess();\n \n // Legacy: Load OAuth platform returns (for backward compatibility)\n const p = localStorage.getItem('onairos_oauth_platform');\n if (p && !localStorage.getItem('onairos_oauth_context')) {\n localStorage.removeItem('onairos_oauth_platform');\n localStorage.removeItem('onairos_oauth_return');\n setConnectedAccounts((s) => {\n // Read existing connections from localStorage, not from stale state\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\n const existingArray = userData.connectedAccounts || [];\n const existingObj = Array.isArray(existingArray) \n ? existingArray.reduce((acc, platform) => ({ ...acc, [platform]: true }), {})\n : {};\n \n // Merge with new connection\n const updated = { ...existingObj, [p]: true };\n const connectedArray = Object.entries(updated).filter(([, v]) => v).map(([k]) => k);\n userData.connectedAccounts = connectedArray;\n localStorage.setItem('onairosUser', JSON.stringify(userData));\n console.log(`๐Ÿ’พ Saved ${p} to localStorage (legacy):`, connectedArray);\n return updated;\n });\n }\n \n // Load persisted connected accounts from user data\n try {\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\n console.log('๐Ÿ”„ UniversalOnboarding mount: Loading persisted accounts from localStorage:', userData.connectedAccounts);\n if (userData.connectedAccounts && Array.isArray(userData.connectedAccounts)) {\n // Convert array to object format\n const accountsObj = userData.connectedAccounts.reduce((acc, platform) => {\n acc[platform] = true;\n return acc;\n }, {});\n console.log('โœ… Converted to object format:', accountsObj);\n setConnectedAccounts(accountsObj);\n } else {\n console.log('โš ๏ธ No valid connectedAccounts in localStorage');\n }\n } catch (error) {\n console.error('โŒ Failed to load persisted connected accounts:', error);\n }\n \n return () => {\n if (typeof window !== 'undefined') {\n window.removeEventListener('onairos-oauth-success', handleAuthSuccess);\n }\n };\n }, []);\n\n async function connectToPlatform(name) {\n const plat = allPlatforms.find((p) => p.name === name);\n if (!plat) return false;\n try {\n // For direct-link platforms (no OAuth), mark connected immediately and return\n if (plat.directLink) {\n setConnectedAccounts((s) => ({ ...s, [name]: true }));\n setIsConnecting(false);\n setConnectingPlatform(null);\n return true;\n }\n\n // Immediately reflect selection in UI without spinner while starting OAuth\n console.log(`๐Ÿ”Œ Connecting to ${name} - updating connectedAccounts state`);\n setConnectedAccounts((s) => {\n const updated = { ...s, [name]: true };\n console.log('๐Ÿ“Š Updated connectedAccounts:', updated);\n return updated;\n });\n setIsConnecting(true);\n setConnectingPlatform(name);\n \n // BYPASS: Twitter endpoint is 404, so just keep toggle ON without API call\n if (name === 'Twitter') {\n console.log('๐Ÿฆ Twitter: Bypassing API call (endpoint not available), keeping toggle ON');\n setIsConnecting(false);\n setConnectingPlatform(null);\n return true;\n }\n \n const username = localStorage.getItem('username') || (JSON.parse(localStorage.getItem('onairosUser') || '{}')?.email) || 'user@example.com';\n\n // Determine return URL based on platform\n // For Desktop/Web: Send empty string/null to prevent backend from generating a redirect URL\n // This forces oauth-callback.html to NOT redirect, allowing the popup/iframe to close naturally via postMessage or window.close()\n const isCapacitorNative = typeof window !== 'undefined' && \n window.Capacitor && \n typeof window.Capacitor.isNativePlatform === 'function' && \n window.Capacitor.isNativePlatform();\n \n const isMobileBrowser = typeof navigator !== 'undefined' &&\n /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);\n\n // Effective mobile check for flow control (use prop or detection)\n const effectiveMobile = isMobileProp || isMobileBrowser;\n\n let returnUrl = ''; // Default to empty for Desktop Web\n \n if (isCapacitorNative) {\n returnUrl = `mobiletest://oauth-callback?success=true&platform=${plat.connector}`;\n } else if (effectiveMobile) {\n // Mobile Web needs redirect back to self\n // Sanitize URL to prevent recursive params if user is already on a return URL\n const cleanUrl = window.location.origin + window.location.pathname;\n returnUrl = cleanUrl;\n }\n\n console.log(`๐Ÿ”— Authorizing ${plat.connector} with returnUrl:`, returnUrl || '(none/desktop)');\n\n // Build session payload for backend (SDK-aware)\n const sessionPayload = {\n username,\n };\n\n // For mobile web flows, let backend know this is coming from the web SDK\n // and pass returnUrl inside session for connectors that use parseEnhancedSession (e.g. Reddit)\n if (effectiveMobile) {\n sessionPayload.sdkType = 'web';\n sessionPayload.returnUrl = returnUrl;\n }\n\n const bodyPayload = {\n session: sessionPayload,\n };\n\n // Backward compatibility for YouTube route which currently reads req.body.returnUrl\n // Desktop flows don't need a returnUrl; only send it for mobile web\n if (!isCapacitorNative && effectiveMobile) {\n bodyPayload.returnUrl = returnUrl;\n }\n\n const res = await fetch(`${sdkConfig.baseUrl}/${plat.connector}/authorize`, {\n method: 'POST',\n headers: { 'x-api-key': sdkConfig.apiKey, 'Content-Type': 'application/json' },\n body: JSON.stringify(bodyPayload),\n });\n if (!res.ok) throw new Error('auth failed');\n const data = await res.json();\n\n const candidates = (\n {\n youtube: ['youtubeURL','youtubeUrl','youtube_url'],\n linkedin: ['linkedinURL','linkedinUrl','linkedin_url'],\n reddit: ['redditURL','redditUrl','reddit_url'],\n pinterest: ['pinterestURL','pinterestUrl','pinterest_url'],\n instagram: ['instagramURL','instagramUrl','instagram_url'],\n github: ['githubURL','githubUrl','github_url'],\n facebook: ['facebookURL','facebookUrl','facebook_url'],\n gmail: ['gmailURL','gmailUrl','gmail_url'],\n }[plat.connector]\n ) || [`${plat.connector}URL`, `${plat.connector}Url`, `${plat.connector}_url`, 'platformURL', 'authUrl', 'url'];\n\n let oauthUrl = null;\n console.log(`๐Ÿ”— [DEBUG] ${plat.connector} candidates:`, candidates, 'Response keys:', Object.keys(data));\n \n // Fallback: Check for URL in data object (case-insensitive)\n if (!oauthUrl) {\n const keys = Object.keys(data);\n const candidateLower = candidates.map(c => c.toLowerCase());\n for (const key of keys) {\n if (candidateLower.includes(key.toLowerCase()) && data[key]) {\n console.log(`๐Ÿ”— [DEBUG] Found fuzzy match for ${plat.connector}: ${key}`);\n oauthUrl = data[key];\n break;\n }\n }\n }\n\n for (const k of candidates) {\n if (data[k]) {\n oauthUrl = data[k];\n break;\n }\n }\n \n if (!oauthUrl) {\n console.error(`โŒ No URL found for ${plat.connector} in response:`, data);\n throw new Error('no url');\n }\n\n // PRIORITY 1: Use Capacitor Browser for native apps\n\n if (isCapacitorNative) {\n console.log(`๐Ÿ“ฑ Capacitor Native: opening ${plat.connector} OAuth with Browser plugin`);\n try {\n // Store context for when user returns\n const localStorageKey = `onairos_${plat.connector}_success`;\n localStorage.setItem('onairos_oauth_context', 'platform-connector');\n localStorage.setItem('onairos_oauth_platform', plat.connector);\n \n // Try to set up listener, but don't let it block\n // Note: 'browserFinished' is fired when the browser is closed by the user or programmatically\n try {\n await Browser.addListener('browserFinished', () => {\n console.log(`๐Ÿ”„ Browser closed for ${plat.connector}`);\n // Only reset if we haven't already detected success\n if (!localStorage.getItem(localStorageKey)) {\n setIsConnecting(false);\n setConnectingPlatform(null);\n }\n });\n } catch (listenerError) {\n console.warn('Browser listener setup failed:', listenerError);\n }\n \n // Ensure Browser.open is awaited and errors caught\n await Browser.open({ \n url: oauthUrl,\n windowName: '_blank',\n presentationStyle: 'fullscreen'\n });\n console.log(`โœ… Opened ${plat.connector} OAuth URL in Capacitor Browser`);\n \n return true;\n } catch (err) {\n console.error(`โŒ Capacitor Browser failed for ${plat.connector}:`, err);\n // Fall through to mobile browser redirect if plugin fails\n }\n }\n\n // PRIORITY 2: Mobile browser - use same-page redirect\n if (effectiveMobile) {\n console.log(`๐Ÿ“ฑ Mobile browser/view: redirecting to ${plat.connector} OAuth in same page`);\n \n // Store return URL and context for redirect back\n const returnUrl = window.location.href;\n localStorage.setItem('onairos_return_url', returnUrl);\n localStorage.setItem('onairos_oauth_context', 'platform-connector');\n localStorage.setItem('onairos_oauth_platform', plat.connector);\n console.log(`๐Ÿ“Œ Stored return URL for ${plat.connector}:`, returnUrl);\n \n // Use same-page redirect on mobile\n setIsConnecting(false);\n setConnectingPlatform(null);\n window.location.href = oauthUrl;\n return true;\n }\n\n // Desktop: open popup\n const popup = window.open(\n oauthUrl,\n 'onairos_oauth_popup', \n 'width=500,height=600,scrollbars=yes,resizable=yes'\n );\n\n if (!popup || popup.closed || typeof popup.closed === 'undefined') {\n console.warn(`โš ๏ธ ${plat.connector} popup blocked, falling back to full-page redirect`);\n setIsConnecting(false);\n setConnectingPlatform(null);\n window.location.href = oauthUrl;\n return true;\n }\n\n // Set up postMessage listener for cross-origin communication\n const messageHandler = (event) => {\n // Only accept messages from onairos.uk origin\n if (event.origin !== 'https://api2.onairos.uk' && \n event.origin !== 'https://onairos.uk' &&\n !event.origin.includes('onairos.uk')) {\n return;\n }\n\n if (event.data && event.data.type === 'oauth-success' && event.data.platform === plat.connector) {\n console.log(`โœ… ${plat.connector} OAuth success received via postMessage:`, event.data);\n window.removeEventListener('message', messageHandler);\n clearInterval(pollInterval);\n setIsConnecting(false);\n setConnectingPlatform(null);\n // Toggle is already ON from optimistic update\n \n // Close popup immediately\n try {\n if (popup && !popup.closed) {\n popup.close();\n }\n } catch (e) {\n // Ignore errors closing popup\n }\n }\n };\n\n window.addEventListener('message', messageHandler);\n\n // Poll localStorage for OAuth completion (oauth-callback.html sets this)\n const localStorageKey = `onairos_${plat.connector}_success`;\n const timestampKey = `onairos_${plat.connector}_timestamp`;\n let pollCount = 0;\n const maxPolls = 300; // 5 minutes max\n\n const pollInterval = setInterval(() => {\n pollCount++;\n \n try {\n // Check if popup is closed (works for popups, not tabs)\n if (popup.closed && pollCount > 10) {\n clearInterval(pollInterval);\n window.removeEventListener('message', messageHandler);\n setIsConnecting(false);\n setConnectingPlatform(null);\n console.log(`โš ๏ธ ${plat.connector} popup was closed`);\n return;\n }\n\n // Check localStorage for success signal\n const success = localStorage.getItem(localStorageKey);\n const timestamp = localStorage.getItem(timestampKey);\n \n if (success === 'true' && timestamp) {\n const timestampNum = parseInt(timestamp, 10);\n const now = Date.now();\n \n // Only process if timestamp is recent (within last 30 seconds)\n if (now - timestampNum < 30000) {\n console.log(`โœ… ${plat.connector} OAuth completed successfully`);\n clearInterval(pollInterval);\n window.removeEventListener('message', messageHandler);\n setIsConnecting(false);\n setConnectingPlatform(null);\n // Toggle is already ON from optimistic update\n \n // Close popup immediately\n try {\n if (!popup.closed) {\n popup.close();\n }\n } catch (e) {\n // Ignore errors closing popup\n }\n return;\n }\n }\n\n // Timeout after max polls\n if (pollCount >= maxPolls) {\n clearInterval(pollInterval);\n window.removeEventListener('message', messageHandler);\n setIsConnecting(false);\n setConnectingPlatform(null);\n console.log(`โณ [TIMEOUT] ${plat.connector} OAuth polling timed out after 5 minutes`);\n \n // Try to close popup if still open\n try {\n if (!popup.closed) {\n popup.close();\n }\n } catch (e) {\n // Ignore errors closing popup\n }\n }\n } catch (error) {\n console.error(`Error in ${plat.connector} OAuth polling:`, error);\n }\n }, 1000);\n\n return true;\n } catch (e) {\n console.error(`โŒ Error connecting to ${name}:`, e);\n // On failure, revert the optimistic toggle\n setConnectedAccounts((s) => ({ ...s, [name]: false }));\n setIsConnecting(false); setConnectingPlatform(null); return false;\n }\n }\n\n const handleSwitch = async (name) => {\n // Mobile: AI direct-link platforms are display-only (no-op on tap)\n const aiNoopOnMobile = ['ChatGPT', 'Claude', 'Gemini', 'Grok'];\n if (isMobile && aiNoopOnMobile.includes(name)) {\n console.log(`๐Ÿ“ฑ ${name} disabled on mobile - no action`);\n return;\n }\n if (isConnecting && connectingPlatform !== name) return;\n const on = !!connectedAccounts[name];\n if (on) setConnectedAccounts((s) => ({ ...s, [name]: false }));\n else await connectToPlatform(name);\n };\n\n const connectedCount = Object.values(connectedAccounts).filter(Boolean).length;\n\n useEffect(() => {\n if (!lottieRef.current) return;\n const totalFrames = (personaAnim.op || 0) - (personaAnim.ip || 0);\n const TOTAL_PLATFORMS = 9; // Total number of platforms across all pages\n const progress = connectedCount / TOTAL_PLATFORMS;\n const target = Math.max(0, Math.floor(progress * totalFrames));\n const start = lastFrameRef.current || 0;\n const duration = 420; const startTs = performance.now();\n const step = (now) => {\n const t = Math.min(1, (now - startTs) / duration);\n const eased = t < 0.5 ? 2*t*t : -1 + (4 - 2*t)*t;\n const frame = Math.floor(start + (target - start) * eased);\n lottieRef.current.goToAndStop(frame, true);\n if (t < 1) rafRef.current = requestAnimationFrame(step); else lastFrameRef.current = target;\n };\n if (rafRef.current) cancelAnimationFrame(rafRef.current);\n rafRef.current = requestAnimationFrame(step);\n return () => { if (rafRef.current) cancelAnimationFrame(rafRef.current); };\n }, [connectedCount]);\n\n // swipe handlers for smooth paging\n const onTouchStart = (e) => { touchStartX.current = e.touches[0].clientX; touchDeltaX.current = 0; };\n const onTouchMove = (e) => { touchDeltaX.current = e.touches[0].clientX - touchStartX.current; };\n const onTouchEnd = () => {\n const dx = touchDeltaX.current; const THRESH = 40;\n if (dx < -THRESH && currentPage < 3) setCurrentPage(currentPage + 1);\n else if (dx > THRESH && currentPage > 1) setCurrentPage(currentPage - 1);\n };\n\n return (\n <div className=\"w-full h-full relative\" style={{ \n height: '100%',\n // Hide scrollbars for mobile browser only\n ...(isMobile && {\n scrollbarWidth: 'none', /* Firefox */\n msOverflowStyle: 'none', /* IE/Edge */\n })\n }}>\n <style>\n {fadeSlideInKeyframes}\n {/* Hide scrollbar for webkit browsers on mobile */}\n {isMobile && `\n .w-full::-webkit-scrollbar,\n *::-webkit-scrollbar {\n display: none;\n width: 0;\n height: 0;\n }\n `}\n </style>\n\n {/* persona as background (unchanged) */}\n <div aria-hidden style={{ \n position: 'absolute', \n left: '50%', \n top: PERSONA_TOP, \n transform: 'translateX(-50%)', \n width: personaSide, \n height: personaSide, \n zIndex: 0, \n pointerEvents: 'none', \n opacity: 0.95 \n }}>\n <div className=\"overflow-hidden rounded-[28px] w-full h-full\">\n <Lottie lottieRef={lottieRef} animationData={personaAnim} autoplay={false} loop={false} style={{ width: '100%', height: '100%' }} />\n </div>\n </div>\n\n {/* content above persona */}\n <div className=\"relative z-10 h-full flex flex-col\" style={{\n // Hide scrollbars for mobile browser only\n ...(isMobile && {\n scrollbarWidth: 'none', /* Firefox */\n msOverflowStyle: 'none', /* IE/Edge */\n })\n }}>\n {/* header - MOBILE ONLY: smaller top padding to give persona space */}\n {/* Desktop: Reduced padding to fit everything */}\n <div className=\"px-6 text-center flex-shrink-0\" style={{ paddingTop: isMobile ? (isSmallMobile ? '2.0rem' : '2.25rem') : '1.5rem', paddingBottom: isMobile ? '0.5rem' : '0.25rem' }}>\n {/* Web-only: lift header text slightly so it doesn't overlap the persona head */}\n <div style={{ transform: isMobile ? 'none' : 'translateY(-10px)' }}>\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2 leading-tight\">Connect App Data</h1>\n <p className=\"text-gray-600 text-base\">More Connections, Better Personalization.</p>\n </div>\n </div>\n\n {/* Spacer - MOBILE ONLY: push icons/card WAY down so PERSONA SHINES */}\n {/* Desktop: Increased spacer to push content lower on page */}\n {isMobile && <div className=\"flex-1\" style={{ minHeight: isSmallMobile ? 120 : 150 }} />}\n {!isMobile && <div className=\"flex-1\" style={{ minHeight: 80 }} />}\n\n {/* icons band */}\n <div className=\"px-6 flex-shrink-0\" style={{ height: ICONS_H }}>\n {/* Web-only: nudge icon band down slightly without affecting layout below */}\n <div className=\"h-full flex items-center justify-center\" style={{ transform: isMobile ? 'none' : 'translateY(8px)' }}>\n <div\n className=\"grid w-full box-border relative\"\n onTouchStart={onTouchStart}\n onTouchMove={onTouchMove}\n onTouchEnd={onTouchEnd}\n style={{\n gridAutoFlow: 'column',\n gridTemplateColumns: `repeat(${platforms.length}, minmax(0,1fr))`,\n columnGap: currentPage === 1 ? GAP_PAGE1 : GAP_PAGE2,\n alignItems: 'center',\n justifyItems: 'center',\n paddingInline: 8,\n overflow: 'hidden',\n }}\n >\n {platforms.map((p, idx) => {\n const on = !!connectedAccounts[p.name];\n const busy = false; // keep icon static visually per request\n const isSel = selected === p.name;\n const shift = (currentPage === 1 ? idx : idx - 2) * 14;\n return (\n <div key={p.name} className=\"transition-all duration-300\" style={{ opacity: 0, transform: `translateX(${shift}px)`, animation: 'fadeSlideIn 0.28s forwards', ['--slide-x']: `${shift}px` }}>\n <button\n type=\"button\"\n onClick={() => { \n // Mobile: AI direct-link platforms are display-only (no-op on tap)\n const aiNoopOnMobile = ['chatgpt', 'claude', 'gemini', 'grok'];\n if (isMobile && aiNoopOnMobile.includes(p.connector)) {\n console.log(`๐Ÿ“ฑ ${p.name} disabled on mobile - no action`);\n return;\n }\n\n setSelected(p.name);\n \n // Properly detect native platform (not just Capacitor presence)\n const isNativePlatform = typeof window !== 'undefined' && \n window.Capacitor?.isNativePlatform?.() === true;\n \n // Detect mobile browser (not Capacitor native)\n const isMobileBrowser = typeof window !== 'undefined' && \n window.innerWidth <= 768 && \n !isNativePlatform;\n \n // Debug logging\n console.log('UniversalOnboarding Click:', { \n platform: p.name, \n isMobile, \n isMobileProp, \n isNativePlatform,\n isMobileBrowser,\n hasCapacitor: typeof window !== 'undefined' && !!window.Capacitor,\n userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown'\n });\n\n // MOBILE BROWSER ONLY: Disable Instagram clicks (show visual selection but don't connect)\n if (p.name === 'Instagram' && isMobileBrowser) {\n console.log('๐Ÿ“ฑ Instagram disabled on mobile browser - visual selection only');\n return;\n }\n\n // For ChatGPT, show modal ONLY on DESKTOP (not mobile browser or native app)\n if (p.connector === 'chatgpt' && !isNativePlatform && !isMobileBrowser) {\n console.log('๐Ÿค– Opening ChatGPT Connect Modal (Desktop Only)');\n setShowChatGPTModal(true);\n return;\n }\n \n // On mobile browser, ChatGPT card is visible but clicking does nothing (like Instagram)\n if (p.connector === 'chatgpt' && isMobileBrowser) {\n console.log('๐Ÿ“ฑ ChatGPT disabled on mobile browser - visual selection only');\n return;\n }\n\n if (p.directLink) {\n // For direct-link AI tools, just select (don't open)\n console.log(`Selecting ${p.name} (direct link platform)`);\n setSelected(p.name);\n } else {\n // For all platforms, icon click should ONLY select, not toggle\n console.log(`Selecting ${p.name}`);\n setSelected(p.name);\n }\n }}\n className=\"relative grid place-items-center outline-none\"\n style={{ width: SLOT, height: SLOT }}\n title={p.name}\n >\n <div \n className={`rounded-full transition-all duration-200 ease-out flex items-center justify-center shadow-lg ${on ? 'ring-4 ring-blue-600 border-2 border-white bg-white text-black' : 'border-2 border-gray-300 hover:border-gray-400 bg-white text-black'}`}\n style={{ \n width: CIRCLE, \n height: CIRCLE, \n transform: `scale(${isSel ? ACTIVE_SCALE : 1})`, \n transformOrigin: 'center',\n boxShadow: on ? '0 0 0 4px rgb(37 99 235), 0 4px 6px -1px rgba(0, 0, 0, 0.1)' : undefined\n }}\n >\n <div className=\"flex items-center justify-center\" style={{ width: 20, height: 20 }}>\n {p.icon}\n </div>\n </div>\n </button>\n </div>\n );\n })}\n </div>\n </div>\n </div>\n\n {/* dots navigation (no numbers) - directly under icons, above card */}\n <div className=\"relative flex items-center justify-center gap-3 select-none flex-shrink-0\" style={{ marginTop: isMobile ? 12 : 24, marginBottom: isMobile ? 20 : 20, zIndex: 25 }}>\n {[1,2,3].map(n => (\n <button key={n} onClick={() => setCurrentPage(n)} aria-label={`page ${n}`} className=\"relative\" style={{ width: isMobile ? 6 : 8, height: isMobile ? 6 : 8 }}>\n <span className={`block rounded-full ${currentPage === n ? 'bg-blue-600 scale-125' : 'bg-gray-300'} transition-transform`} style={{ width: isMobile ? 6 : 8, height: isMobile ? 6 : 8 }} />\n </button>\n ))}\n </div>\n\n {/* info sheet โ€” positioned using flex, MOBILE ONLY: LOWER */}\n <div className=\"px-6 flex-shrink-0\" style={{ marginBottom: isMobile ? 24 : 28, zIndex: 20 }}>\n <div className=\"mx-auto rounded-2xl bg-white shadow-sm border border-gray-200 px-4 py-2.5\" style={{ width: 'min(680px,92%)', maxHeight: isMobile ? (vh * 0.18) : (vh * 0.2) }}>\n <div className=\"flex items-center justify-between\">\n <div className=\"text-gray-900 font-medium\">{selected}</div>\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={!!connectedAccounts[selected]}\n aria-label={`toggle ${selected}`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleSwitch(selected);\n }}\n onTouchEnd={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleSwitch(selected);\n }}\n disabled={isConnecting && connectingPlatform !== selected}\n className={`relative inline-flex items-center transition-colors disabled:opacity-50 ${connectedAccounts[selected] ? 'bg-black' : 'bg-gray-200'} rounded-full touch-manipulation`}\n style={{ width: 56, height: 32, WebkitTapHighlightColor: 'transparent', userSelect: 'none', touchAction: 'manipulation' }}\n >\n <span\n className=\"absolute bg-white rounded-full shadow pointer-events-none\"\n style={{\n width: 24,\n height: 24,\n transform: connectedAccounts[selected] ? 'translateX(26px)' : 'translateX(6px)',\n transition: 'transform 160ms ease',\n }}\n />\n </button>\n </div>\n <div className=\"mt-3\">\n <div className=\"rounded-2xl bg-gray-50 text-gray-700 text-sm leading-6 px-4 py-3 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.04)]\">\n {descriptions[selected] || null}\n </div>\n {!isMobileBrowser && !isNativePlatform && selected === 'ChatGPT' && (\n <div className=\"mt-3 flex justify-end\">\n <button\n type=\"button\"\n onClick={() => setShowChatGPTModal(true)}\n className=\"inline-flex items-center gap-2 rounded-full bg-slate-900 px-4 py-2 text-sm font-medium text-white shadow-sm hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-slate-900\"\n >\n <span>Connect ChatGPT</span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M10 6h8m0 0v8m0-8L6 18\"\n />\n </svg>\n </button>\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* footer โ€” anchored at bottom using flex */}\n <div className=\"px-6 flex-shrink-0\" style={{ paddingBottom: isMobile ? 12 : 16, background: isMobile ? 'transparent' : 'linear-gradient(to top, white 60%, rgba(255,255,255,0.9) 85%, rgba(255,255,255,0))', zIndex: 30 }}>\n <div className=\"w-full bg-gray-900 hover:bg-gray-800 rounded-full text-base font-medium flex items-center justify-center gap-2 cursor-pointer transition-colors\"\n style={{ paddingTop: isSmallMobile ? 12 : 16, paddingBottom: isSmallMobile ? 12 : 16, color: '#ffffff' }}\n onClick={() => {\n console.log('๐Ÿ”ฅ UniversalOnboarding: Update clicked');\n console.log('๐Ÿ” Current connectedAccounts state:', connectedAccounts);\n const connected = Object.entries(connectedAccounts).filter(([, v]) => v).map(([k]) => k);\n console.log('โœ… Sending to onComplete:', { connectedAccounts: connected, totalConnections: connected.length });\n onComplete?.({ connectedAccounts: connected, totalConnections: connected.length });\n }}>\n Update\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"#ffffff\" viewBox=\"0 0 24 24\"><path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" /></svg>\n </div>\n <div onClick={() => onComplete?.({ connectedAccounts: [], totalConnections: 0 })} className=\"w-full text-gray-600 text-base font-medium py-2 text-center cursor-pointer hover:text-gray-800 transition-colors\" style={{ paddingTop: isSmallMobile ? 6 : 8, paddingBottom: isSmallMobile ? 6 : 8 }}>Skip</div>\n </div>\n </div>\n {/* Modal - Always render if state is true, regardless of isMobile prop */}\n <ConnectChatGPTModal\n open={showChatGPTModal}\n onClose={() => setShowChatGPTModal(false)}\n onConnected={() => {\n setConnectedAccounts((s) => ({ ...s, ChatGPT: true }));\n }}\n />\n </div>\n );\n}","import React, { useState, useEffect } from 'react';\r\n\r\nexport default function PinSetup({ onComplete, onBack, userEmail }) {\r\n const [pin, setPin] = useState('');\r\n const [pinRequirements, setPinRequirements] = useState({\r\n length: false,\r\n uppercase: false,\r\n number: false,\r\n });\r\n\r\n // Check PIN requirements\r\n useEffect(() => {\r\n setPinRequirements({\r\n length: pin.length >= 6,\r\n uppercase: /[A-Z]/.test(pin),\r\n number: /\\d/.test(pin),\r\n });\r\n }, [pin]);\r\n\r\n const allRequirementsMet = pinRequirements.length && pinRequirements.uppercase && pinRequirements.number;\r\n\r\n const handleSubmit = () => {\r\n if (allRequirementsMet) {\r\n onComplete({\r\n pin: pin, // This should be hashed in production\r\n pinCreated: true,\r\n timestamp: new Date().toISOString()\r\n });\r\n }\r\n };\r\n\r\n return (\r\n <div className=\"w-full h-full flex flex-col\" style={{ height: '100%', minHeight: 0 }}>\r\n {/* Content - Flexible center area */}\r\n <div className=\"px-6 pt-16 flex-1 flex flex-col\" style={{ minHeight: 0, overflow: 'hidden' }}>\r\n <div className=\"mb-6 flex-shrink-0\">\r\n <h1 className=\"text-2xl font-bold text-gray-900 mb-2\">Create a PIN</h1>\r\n <p className=\"text-gray-600 text-base\">A PIN so only you have the access to your data</p>\r\n </div>\r\n\r\n <div className=\"mb-6 flex-shrink-0\">\r\n <input\r\n type=\"password\"\r\n value={pin}\r\n onChange={(e) => setPin(e.target.value)}\r\n className=\"w-full px-4 py-4 border-2 border-gray-300 rounded-xl text-center text-lg font-medium focus:border-gray-900 focus:outline-none bg-white !text-black\"\r\n placeholder=\"Enter your PIN\"\r\n maxLength={20}\r\n style={{\r\n WebkitTextFillColor: '#000000',\r\n backgroundColor: '#FFFFFF',\r\n color: '#000000'\r\n }}\r\n />\r\n </div>\r\n\r\n {/* Scrollable requirements list */}\r\n <div className=\"flex-1 overflow-y-auto\" style={{ minHeight: 0 }}>\r\n <div className=\"space-y-3 pb-4\">\r\n <p className=\"text-gray-900 font-medium mb-4\">Your PIN must:</p>\r\n <div className=\"space-y-3\">\r\n <div className=\"flex items-center gap-3\">\r\n <div\r\n className={`w-5 h-5 rounded-full border-2 ${pinRequirements.length ? \"border-green-500 bg-green-500\" : \"border-gray-300 bg-white\"}`}\r\n >\r\n {pinRequirements.length && (\r\n <svg className=\"w-3 h-3 text-white m-0.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\r\n </svg>\r\n )}\r\n </div>\r\n <span className=\"text-gray-700\">Be at least 6 characters in length.</span>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <div\r\n className={`w-5 h-5 rounded-full border-2 ${pinRequirements.uppercase ? \"border-green-500 bg-green-500\" : \"border-gray-300 bg-white\"}`}\r\n >\r\n {pinRequirements.uppercase && (\r\n <svg className=\"w-3 h-3 text-white m-0.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\r\n </svg>\r\n )}\r\n </div>\r\n <span className=\"text-gray-700\">Contain an uppercase letter.</span>\r\n </div>\r\n <div className=\"flex items-center gap-3\">\r\n <div\r\n className={`w-5 h-5 rounded-full border-2 ${pinRequirements.number ? \"border-green-500 bg-green-500\" : \"border-gray-300 bg-white\"}`}\r\n >\r\n {pinRequirements.number && (\r\n <svg className=\"w-3 h-3 text-white m-0.5\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\r\n </svg>\r\n )}\r\n </div>\r\n <span className=\"text-gray-700\">Contain a number.</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Buttons - Fixed at bottom */}\r\n <div className=\"px-6 pb-6 pt-4 flex-shrink-0 space-y-3\" style={{ minHeight: 'auto' }}>\r\n <div\r\n className={`w-full rounded-full py-4 text-base font-medium flex items-center justify-center gap-2 transition-colors ${\r\n allRequirementsMet \r\n ? \"bg-gray-900 hover:bg-gray-800 cursor-pointer\" \r\n : \"bg-gray-300 text-gray-500 cursor-not-allowed\"\r\n }`}\r\n style={allRequirementsMet ? { color: '#ffffff' } : {}}\r\n onClick={allRequirementsMet ? handleSubmit : undefined}\r\n >\r\n Continue\r\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n} ","import React, { useState } from \"react\";\r\n\r\n/* -------------------------\r\n ICON COMPONENTS\r\n-------------------------- */\r\nconst Icon = ({ type }) => {\r\n const base = \"w-4 h-4 text-gray-700\";\r\n\r\n switch (type) {\r\n case \"User\":\r\n return (\r\n <svg className={base} viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4\r\n 1.79-4 4 1.79 4 4 4zm0 2c-2.67\r\n 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\"/>\r\n </svg>\r\n );\r\n case \"Memory\":\r\n return (\r\n <svg className={base} viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M12 2C6.48 2 2 6.48 2\r\n 12s4.48 10 10 10 10-4.48 10-10S17.52\r\n 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z\"/>\r\n </svg>\r\n );\r\n case \"Grid3X3\":\r\n return (\r\n <svg className={base} viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M3 13h8V3H3v10zm0 8h8v-6H3v6zm10\r\n 0h8V11h-8v10zm0-18v6h8V3h-8z\"/>\r\n </svg>\r\n );\r\n case \"Brain\":\r\n return (\r\n <svg className={base} viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M11.99 2C6.47 2 2 6.48 2\r\n 12s4.47 10 9.99 10C17.52\r\n 22 22 17.52 22 12S17.52\r\n 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8\r\n 8-8 8 3.58 8 8-3.58 8-8\r\n 8zm3.5-9c.83 0 1.5-.67\r\n 1.5-1.5S16.33 8 15.5\r\n 8 14 8.67 14 9.5s.67 1.5\r\n 1.5 1.5zm-7 0c.83 0 1.5-.67\r\n 1.5-1.5S9.33 8 8.5\r\n 8 7 8.67 7 9.5s.67 1.5\r\n 1.5 1.5zm3.5 6.5c2.33\r\n 0 4.31-1.46 5.11-3.5H6.89c.8\r\n 2.04 2.78 3.5 5.11 3.5z\"/>\r\n </svg>\r\n );\r\n default:\r\n return null;\r\n }\r\n};\r\n\r\n/* -------------------------\r\n TOGGLE (soft apple style)\r\n-------------------------- */\r\nconst DataTypeToggle = ({ dataType, enabled, onToggle, isNative }) => {\r\n const handle = () => {\r\n if (dataType.required) return;\r\n onToggle(dataType.id, !enabled);\r\n };\r\n\r\n return (\r\n <button\r\n onClick={handle}\r\n className=\"\r\n w-full flex items-center justify-between\r\n py-2.5 px-2\r\n bg-white/40 backdrop-blur-sm\r\n hover:bg-white/70\r\n transition rounded-xl shadow-sm\r\n \"\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n <div className=\"w-7 h-7 flex items-center justify-center rounded-full bg-gray-100\">\r\n <Icon type={dataType.icon} />\r\n </div>\r\n <span className={`${isNative ? 'text-[15px]' : 'text-[14px]'} text-gray-900 font-medium`}>\r\n {dataType.name}\r\n </span>\r\n </div>\r\n\r\n <div\r\n className={`w-5 h-5 rounded-md border flex items-center justify-center shadow-sm\r\n transition\r\n ${enabled\r\n ? \"bg-gray-900 border-gray-900\"\r\n : \"bg-white border-gray-300\"\r\n }`}\r\n >\r\n {enabled && (\r\n <svg className=\"w-3 h-3 text-white\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path d=\"M16.707 5.293a1 1 0 010\r\n 1.414l-8 8a1 1 0 01-1.414\r\n 0l-4-4a1 1 0 011.414-1.414L8\r\n 12.586l7.293-7.293a1 1 0\r\n 011.414 0z\"/>\r\n </svg>\r\n )}\r\n </div>\r\n </button>\r\n );\r\n};\r\n\r\n/* -------------------------\r\n MAIN COMPONENT\r\n-------------------------- */\r\n\r\nconst options = [\r\n { id: \"basic\", name: \"Basic Profile\", icon: \"User\", required: true },\r\n { id: \"rawMemories\", name: \"Raw Memory Data\", icon: \"Memory\" },\r\n { id: \"preferences\", name: \"User Preferences\", icon: \"Grid3X3\" },\r\n { id: \"personality\", name: \"Personality Traits\", icon: \"Brain\" },\r\n];\r\n\r\nconst DataRequest = ({ appName = \"My App\", onComplete, onConnectMoreApps, connectedPlatforms = [], showTime = false }) => {\r\n const [selected, setSelected] = useState({\r\n basic: true,\r\n rawMemories: false,\r\n preferences: false,\r\n personality: false,\r\n });\r\n\r\n const [freq, setFreq] = useState(\"weekly\");\r\n\r\n const isWrappedApp = typeof appName === 'string' && appName.toLowerCase().includes('wrapped');\r\n\r\n const toggle = (id, val) =>\r\n setSelected((p) => ({ ...p, [id]: val }));\r\n\r\n const selectedCount = Object.values(selected).filter(Boolean).length;\r\n\r\n // Ensure we actually show connected platforms even if prop isn't passed\r\n const getConnected = () => {\r\n console.log('๐Ÿ“Š DataRequest getConnected:', { \r\n connectedPlatforms, \r\n isArray: Array.isArray(connectedPlatforms),\r\n type: typeof connectedPlatforms \r\n });\r\n \r\n // If array provided, use it\r\n if (Array.isArray(connectedPlatforms) && connectedPlatforms.length > 0) {\r\n console.log('โœ… Using connectedPlatforms prop (array):', connectedPlatforms);\r\n return connectedPlatforms;\r\n }\r\n \r\n // If object provided, map truthy keys\r\n if (connectedPlatforms && typeof connectedPlatforms === \"object\" && !Array.isArray(connectedPlatforms)) {\r\n const mapped = Object.entries(connectedPlatforms).filter(([_, v]) => Boolean(v)).map(([k]) => k);\r\n console.log('โœ… Using connectedPlatforms prop (object):', mapped);\r\n return mapped;\r\n }\r\n \r\n // Fallback: try localStorage onairosUser\r\n try {\r\n const u = JSON.parse(localStorage.getItem(\"onairosUser\") || \"{}\");\r\n if (u && u.connectedAccounts) {\r\n // Check if it's an array\r\n if (Array.isArray(u.connectedAccounts) && u.connectedAccounts.length > 0) {\r\n console.log('โœ… Using localStorage connectedAccounts (array):', u.connectedAccounts);\r\n return u.connectedAccounts;\r\n }\r\n // Check if it's an object\r\n if (typeof u.connectedAccounts === \"object\") {\r\n const mapped = Object.entries(u.connectedAccounts).filter(([_, v]) => Boolean(v)).map(([k]) => k);\r\n console.log('โœ… Using localStorage connectedAccounts (object):', mapped);\r\n return mapped;\r\n }\r\n }\r\n } catch (e) {\r\n console.error('โŒ Failed to read localStorage:', e);\r\n }\r\n \r\n console.log('โš ๏ธ No connected platforms found');\r\n return [];\r\n };\r\n const platforms = getConnected();\r\n console.log('๐ŸŽฏ Final platforms to display:', platforms);\r\n\r\n const isCapacitorNative = typeof window !== 'undefined' && \r\n window.Capacitor && \r\n typeof window.Capacitor.isNativePlatform === 'function' && \r\n window.Capacitor.isNativePlatform();\r\n\r\n // Check if user has any LLM connections\r\n const hasLLMConnections = () => {\r\n const llmPlatforms = ['chatgpt', 'claude', 'gemini', 'grok', 'ChatGPT', 'Claude', 'Gemini', 'Grok'];\r\n return platforms.some(p => llmPlatforms.includes(p));\r\n };\r\n\r\n // Filter options based on LLM connections\r\n const availableOptions = options.filter(opt => {\r\n if (opt.id === 'rawMemories') {\r\n return hasLLMConnections();\r\n }\r\n return true;\r\n });\r\n\r\n const freqToPercent = (f) => (f === \"once\" ? 0 : f === \"weekly\" ? 50 : 100);\r\n const handleRailClick = (e) => {\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n const x = Math.max(0, Math.min(rect.width, e.clientX - rect.left));\r\n const ratio = x / rect.width;\r\n if (ratio < 1 / 3) setFreq(\"once\");\r\n else if (ratio < 2 / 3) setFreq(\"weekly\");\r\n else setFreq(\"daily\");\r\n };\r\n\r\n return (\r\n <div className=\"flex flex-col h-full max-h-full md:max-h-[90vh] bg-white/70 backdrop-blur-2xl rounded-3xl overflow-hidden\">\r\n\r\n {/* CONTENT */}\r\n <div className=\"flex-1 overflow-y-auto px-6 pt-6 md:pt-10 pb-4\">\r\n\r\n {/* ICONS */}\r\n <div className=\"flex justify-center items-center gap-4 mb-5 md:mb-6\">\r\n {/* Wrapped: brain -> Onairos. Non-wrapped: Onairos -> app placeholder */}\r\n <div className={`${isCapacitorNative ? 'w-14 h-14' : 'w-12 h-12'} rounded-2xl bg-white shadow flex items-center justify-center`}>\r\n {isWrappedApp ? (\r\n <span className={`${isCapacitorNative ? 'text-3xl' : 'text-2xl'}`} aria-label=\"Brain\">๐Ÿง </span>\r\n ) : (\r\n <img \r\n src=\"https://onairos.sirv.com/Images/OnairosBlack.png\" \r\n alt=\"Onairos\"\r\n className={`${isCapacitorNative ? 'w-10 h-10' : 'w-8 h-8'} object-contain`}\r\n />\r\n )}\r\n </div>\r\n <svg className={`${isCapacitorNative ? 'w-8 h-8' : 'w-6 h-6'} text-gray-400`} fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\r\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M14 5l7 7m0 0l-7 7m7-7H3\" />\r\n </svg>\r\n <div className={`${isCapacitorNative ? 'w-14 h-14' : 'w-12 h-12'} rounded-2xl bg-white shadow flex items-center justify-center`}>\r\n {isWrappedApp ? (\r\n <img \r\n src=\"https://onairos.sirv.com/Images/OnairosBlack.png\" \r\n alt=\"Onairos\"\r\n className={`${isCapacitorNative ? 'w-10 h-10' : 'w-8 h-8'} object-contain`}\r\n />\r\n ) : (\r\n <span className={`${isCapacitorNative ? 'text-2xl' : 'text-xl'} font-serif font-bold`}>J</span>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* TITLE */}\r\n <div className=\"text-center mb-6 md:mb-8\">\r\n <h1 className={`${isCapacitorNative ? 'text-[26px] md:text-[28px]' : 'text-[24px] md:text-[26px]'} font-semibold text-gray-900 leading-tight tracking-tight`}>\r\n {appName} wants to personalize your experience\r\n </h1>\r\n <p className={`${isCapacitorNative ? 'text-[14px]' : 'text-[13px]'} text-gray-500 mt-1`}>choose what to share</p>\r\n </div>\r\n\r\n {/* TOGGLES */}\r\n <div className={`${isCapacitorNative ? 'flex flex-col gap-3' : 'flex flex-col sm:grid sm:grid-cols-2 gap-3 sm:gap-4'} mb-6 md:mb-10`}>\r\n {availableOptions.map((opt) => (\r\n <DataTypeToggle\r\n key={opt.id}\r\n dataType={opt}\r\n enabled={selected[opt.id]}\r\n onToggle={toggle}\r\n isNative={isCapacitorNative}\r\n />\r\n ))}\r\n </div>\r\n\r\n {/* FREQUENCY PANEL - Only shown if showTime is true */}\r\n {showTime && (\r\n <div className=\"p-5 rounded-3xl bg-white/50 backdrop-blur-md border border-black/5 shadow-sm\">\r\n <div className=\"flex justify-between items-center mb-3\">\r\n <span className=\"text-sm font-medium text-gray-900\">\r\n How often can {appName} receive updates?\r\n </span>\r\n <span className=\"text-[11px] text-gray-500\">\r\n {freq === \"once\"\r\n ? \"one-time only\"\r\n : freq === \"weekly\"\r\n ? \"once per week\"\r\n : \"once per day\"}\r\n </span>\r\n </div>\r\n\r\n {/* SLIDER: subtle rail, monochrome progress, click-to-set */}\r\n <div\r\n className=\"relative h-2.5 rounded-full bg-gray-200/90 overflow-hidden mb-4 border border-black/5 shadow-inner cursor-pointer\"\r\n onClick={handleRailClick}\r\n >\r\n <div\r\n className=\"absolute h-full transition-all rounded-full\"\r\n style={{\r\n width: `${freqToPercent(freq)}%`,\r\n background: \"linear-gradient(90deg, rgba(31,41,55,0.95) 0%, rgba(107,114,128,0.9) 60%, rgba(209,213,219,0.85) 100%)\",\r\n }}\r\n />\r\n {/* Tick marks for 3 stops */}\r\n <span className=\"absolute left-0 top-1/2 -translate-y-1/2 w-[2px] h-3 bg-black/10\" />\r\n <span className=\"absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[2px] h-3 bg-black/10\" />\r\n <span className=\"absolute right-0 top-1/2 -translate-y-1/2 w-[2px] h-3 bg-black/10\" />\r\n {/* Thumb indicator (sleek) */}\r\n <span\r\n className=\"absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-4.5 h-4.5 rounded-full bg-white border border-black/20 shadow-md\"\r\n style={{\r\n left: `${freqToPercent(freq)}%`,\r\n }}\r\n />\r\n </div>\r\n\r\n <div className=\"grid grid-cols-3 text-center text-[12px] font-medium\">\r\n <button onClick={() => setFreq(\"once\")} className=\"text-gray-700\">1ร— only</button>\r\n <button onClick={() => setFreq(\"weekly\")} className=\"text-gray-900 font-semibold\">1ร— weekly</button>\r\n <button onClick={() => setFreq(\"daily\")} className=\"text-gray-700\">1ร— daily</button>\r\n </div>\r\n\r\n <p className=\"text-[11px] text-gray-500 mt-3 leading-snug\">\r\n This only controls update frequency; It does not grant more access.\r\n </p>\r\n </div>\r\n )}\r\n\r\n </div>\r\n\r\n {/* FOOTER */}\r\n <div className=\"px-6 py-4 md:py-5 bg-white/80 backdrop-blur border-t border-black/5\">\r\n {/* Connected platforms pinned above CTAs so it never gets cropped on mobile */}\r\n {platforms && platforms.length > 0 && (\r\n <div className=\"mb-3 rounded-2xl bg-white/60 backdrop-blur border border-black/5 px-3 py-2\">\r\n <div className=\"text-center text-[11px] text-gray-500 mb-1\">Connected Platforms</div>\r\n <div className=\"flex items-center justify-center gap-2 overflow-x-auto whitespace-nowrap pb-1\" style={{ WebkitOverflowScrolling: 'touch' }}>\r\n {platforms.map((platform, index) => {\r\n const logoMap = {\r\n Instagram: 'https://upload.wikimedia.org/wikipedia/commons/a/a5/Instagram_icon.png',\r\n YouTube: 'https://upload.wikimedia.org/wikipedia/commons/0/09/YouTube_full-color_icon_%282017%29.svg',\r\n LinkedIn: 'https://upload.wikimedia.org/wikipedia/commons/c/ca/LinkedIn_logo_initials.png',\r\n Reddit: 'https://upload.wikimedia.org/wikipedia/en/b/bd/Reddit_Logo_Icon.svg',\r\n Pinterest: 'https://upload.wikimedia.org/wikipedia/commons/0/08/Pinterest-logo.png',\r\n GitHub: 'https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png',\r\n Facebook: 'https://upload.wikimedia.org/wikipedia/commons/5/51/Facebook_f_logo_%282019%29.svg',\r\n Gmail: 'https://upload.wikimedia.org/wikipedia/commons/7/7e/Gmail_icon_%282020%29.svg',\r\n Twitter: 'https://upload.wikimedia.org/wikipedia/commons/6/6f/Logo_of_Twitter.svg',\r\n ChatGPT: 'https://anushkasirv.sirv.com/openai.png',\r\n Claude: 'https://anushkasirv.sirv.com/claude-color.png',\r\n Gemini: 'https://anushkasirv.sirv.com/gemini-color.png',\r\n Grok: 'https://anushkasirv.sirv.com/grok.png'\r\n };\r\n const src = logoMap[platform] || '';\r\n return (\r\n <img\r\n key={`${platform}-${index}`}\r\n src={src}\r\n alt={platform}\r\n title={platform}\r\n className=\"w-6 h-6 rounded-md shadow-sm flex-shrink-0\"\r\n onError={(e) => { e.currentTarget.style.display = 'none'; }}\r\n />\r\n );\r\n })}\r\n </div>\r\n {typeof onConnectMoreApps === 'function' && (\r\n <div className=\"mt-1 flex justify-center\">\r\n <button\r\n type=\"button\"\r\n onClick={onConnectMoreApps}\r\n className=\"text-[11px] font-medium underline underline-offset-2 text-gray-700 hover:text-gray-900\"\r\n style={{ WebkitTextFillColor: '#111827' }}\r\n >\r\n Connect more apps?\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n <button\r\n className=\"w-full rounded-full py-3 bg-gray-900 text-sm font-medium shadow-sm flex items-center justify-center mb-3\"\r\n style={{ color: '#ffffff' }}\r\n disabled={selectedCount === 0}\r\n onClick={() => {\r\n if (selectedCount === 0) return;\r\n onComplete?.({\r\n approved: Object.keys(selected).filter(id => selected[id]),\r\n freq,\r\n });\r\n }}\r\n >\r\n Accept & Continue\r\n </button>\r\n\r\n <style>{`\r\n .decline-button {\r\n color: #000000 !important;\r\n }\r\n .decline-button * {\r\n color: #000000 !important;\r\n }\r\n .decline-button span {\r\n color: #000000 !important;\r\n }\r\n button.decline-button {\r\n color: #000000 !important;\r\n }\r\n .decline-button-text {\r\n color: #000000 !important;\r\n -webkit-text-fill-color: #000000 !important;\r\n }\r\n `}</style>\r\n <button\r\n className=\"w-full rounded-full py-3 bg-gray-100 text-sm font-medium shadow-sm decline-button\"\r\n style={{ color: '#000000' }}\r\n onClick={() => {\r\n onComplete?.({\r\n approved: [],\r\n freq,\r\n declined: true,\r\n });\r\n }}\r\n >\r\n <span className=\"decline-button-text\" style={{ color: '#000000' }}>Decline</span>\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DataRequest;\r\n","import React, { useState, useEffect } from 'react';\r\nimport { COLORS } from '../theme/colors.js';\r\n\r\nexport default function TrainingComponent({ onComplete, userEmail, appName = 'App', testMode = false }) {\r\n const [currentStep, setCurrentStep] = useState(0);\r\n const [progress, setProgress] = useState(0);\r\n const [isComplete, setIsComplete] = useState(false);\r\n\r\n const steps = [\r\n {\r\n title: 'Setting up your personal AI',\r\n description: 'Initializing your secure data model',\r\n icon: '๐Ÿค–',\r\n duration: testMode ? 800 : 2000 // Much faster in test mode\r\n },\r\n {\r\n title: 'Processing your connections',\r\n description: 'Analyzing your social media patterns',\r\n icon: '๐Ÿ”—',\r\n duration: testMode ? 600 : 2500\r\n },\r\n {\r\n title: 'Training your model',\r\n description: 'Building your personalized insights',\r\n icon: '๐Ÿง ',\r\n duration: testMode ? 700 : 3000\r\n },\r\n {\r\n title: 'Finalizing setup',\r\n description: 'Preparing your Onairos experience',\r\n icon: 'โœจ',\r\n duration: testMode ? 500 : 2000\r\n }\r\n ];\r\n\r\n useEffect(() => {\r\n let interval;\r\n let stepTimeout;\r\n\r\n if (currentStep < steps.length) {\r\n const stepDuration = steps[currentStep].duration;\r\n const stepProgress = 100 / steps.length;\r\n\r\n // Update progress gradually\r\n interval = setInterval(() => {\r\n setProgress(prev => {\r\n const newProgress = prev + (stepProgress / (stepDuration / 100));\r\n return Math.min(newProgress, (currentStep + 1) * stepProgress);\r\n });\r\n }, 100);\r\n\r\n // Move to next step after duration\r\n stepTimeout = setTimeout(() => {\r\n if (currentStep < steps.length - 1) {\r\n setCurrentStep(prev => prev + 1);\r\n } else {\r\n setIsComplete(true);\r\n const completionDelay = testMode ? 400 : 1000; // Faster completion in test mode\r\n \r\n if (testMode) {\r\n console.log('๐Ÿงช Test mode: Training simulation completed');\r\n }\r\n \r\n setTimeout(() => {\r\n onComplete({\r\n trainingComplete: true,\r\n timestamp: new Date().toISOString(),\r\n userEmail: userEmail,\r\n appName: appName,\r\n testMode: testMode,\r\n simulatedTraining: testMode\r\n });\r\n }, completionDelay);\r\n }\r\n }, stepDuration);\r\n }\r\n\r\n return () => {\r\n if (interval) clearInterval(interval);\r\n if (stepTimeout) clearTimeout(stepTimeout);\r\n };\r\n }, [currentStep, onComplete, userEmail, appName]);\r\n\r\n return (\r\n <div className=\"w-full flex flex-col items-center space-y-8\">\r\n <div className=\"text-center\">\r\n <div \r\n className=\"w-20 h-20 rounded-full flex items-center justify-center mx-auto mb-4\"\r\n style={{\r\n background: `linear-gradient(135deg, ${COLORS.info}, #8B5CF6)`\r\n }}\r\n >\r\n <div className=\"text-3xl\">\r\n {isComplete ? '๐ŸŽ‰' : steps[currentStep]?.icon}\r\n </div>\r\n </div>\r\n <h2 \r\n className=\"text-2xl font-bold mb-2\"\r\n style={{ color: COLORS.textPrimary }}\r\n >\r\n {isComplete ? 'All set!' : steps[currentStep]?.title}\r\n </h2>\r\n <p style={{ color: COLORS.textSecondary }}>\r\n {isComplete \r\n ? 'Your personal AI is ready to use' \r\n : steps[currentStep]?.description\r\n }\r\n </p>\r\n </div>\r\n\r\n {/* Progress Bar */}\r\n <div className=\"w-full\">\r\n <div \r\n className=\"flex justify-between text-sm mb-2\"\r\n style={{ color: COLORS.textSecondary }}\r\n >\r\n <span>Progress</span>\r\n <span>{Math.round(progress)}%</span>\r\n </div>\r\n <div \r\n className=\"w-full rounded-full h-2\"\r\n style={{ backgroundColor: COLORS.borderLight }}\r\n >\r\n <div \r\n className=\"h-2 rounded-full transition-all duration-300 ease-out\"\r\n style={{ \r\n width: `${progress}%`,\r\n background: `linear-gradient(90deg, ${COLORS.info}, #8B5CF6)`\r\n }}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Steps Indicator */}\r\n <div className=\"flex justify-center space-x-2\">\r\n {steps.map((_, index) => (\r\n <div\r\n key={index}\r\n className=\"w-3 h-3 rounded-full transition-all duration-300\"\r\n style={{\r\n backgroundColor: index <= currentStep ? COLORS.info : COLORS.border\r\n }}\r\n />\r\n ))}\r\n </div>\r\n\r\n {/* Current Step Details */}\r\n <div \r\n className=\"p-4 rounded-lg w-full\"\r\n style={{ backgroundColor: COLORS.backgroundSecondary }}\r\n >\r\n <div className=\"flex items-center space-x-3\">\r\n <div \r\n className=\"w-8 h-8 rounded-full flex items-center justify-center\"\r\n style={{ backgroundColor: '#DBEAFE' }}\r\n >\r\n <div className=\"text-sm\">\r\n {isComplete ? 'โœ…' : steps[currentStep]?.icon}\r\n </div>\r\n </div>\r\n <div>\r\n <h3 \r\n className=\"font-medium\"\r\n style={{ color: COLORS.textPrimary }}\r\n >\r\n {isComplete ? 'Training Complete' : `Step ${currentStep + 1} of ${steps.length}`}\r\n </h3>\r\n <p \r\n className=\"text-sm\"\r\n style={{ color: COLORS.textSecondary }}\r\n >\r\n {isComplete \r\n ? 'Your Onairos experience is ready' \r\n : steps[currentStep]?.description\r\n }\r\n </p>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* App Info */}\r\n <div className=\"text-center\">\r\n <p \r\n className=\"text-sm\"\r\n style={{ color: COLORS.textSecondary }}\r\n >\r\n Setting up for <span className=\"font-medium\">{appName}</span>\r\n </p>\r\n {userEmail && (\r\n <p \r\n className=\"text-xs mt-1\"\r\n style={{ color: COLORS.textMuted }}\r\n >\r\n {userEmail}\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n} ","import React, { useEffect, useState, useRef } from 'react';\r\nimport Lottie from 'lottie-react';\r\nimport rainAnim from '../../public/rain-anim.json';\r\nimport io from 'socket.io-client';\r\n\r\nconst trainingPhrases = [\r\n \"Analyzing your data patterns...\",\r\n \"Building your personality model...\",\r\n \"Training neural networks...\",\r\n \"Running inference algorithms...\",\r\n \"Generating personalized insights...\",\r\n \"Finalizing your profile...\",\r\n \"Almost done...\"\r\n];\r\n\r\nexport default function TrainingScreen({ onComplete, onTrainingStart, userEmail, connectedAccounts = [], userToken }) {\r\n const [progress, setProgress] = useState(0);\r\n const [currentPhrase, setCurrentPhrase] = useState(trainingPhrases[0]);\r\n const [currentStage, setCurrentStage] = useState('training'); // 'training' | 'inference' | 'complete'\r\n const lottieRef = useRef(null);\r\n\r\n useEffect(() => {\r\n let socket = null;\r\n let progressTimer = null;\r\n let didSignalStart = false;\r\n\r\n const signalTrainingStarted = () => {\r\n if (didSignalStart) return;\r\n didSignalStart = true;\r\n try {\r\n onTrainingStart?.();\r\n } catch (e) {\r\n // never block training due to callback issues\r\n }\r\n };\r\n \r\n // ACTUALLY run training + inference using Socket.IO\r\n const runTrainingAndInference = async () => {\r\n console.log('๐ŸŽ“ Starting REAL training for:', userEmail);\r\n console.log('๐Ÿ“Š Connected accounts:', connectedAccounts);\r\n console.log('๐Ÿ”‘ userToken prop received:', userToken ? `${userToken.substring(0, 20)}...` : 'UNDEFINED');\r\n\r\n try {\r\n // Use token passed from parent component, fallback to localStorage\r\n let token = userToken;\r\n \r\n if (!token) {\r\n console.warn('โš ๏ธ Token not passed as prop, checking localStorage...');\r\n try {\r\n const storedToken = localStorage.getItem('onairos_user_token');\r\n if (storedToken) {\r\n token = storedToken;\r\n console.log('โœ… Found token in localStorage');\r\n } else {\r\n const userData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\r\n token = userData.token;\r\n if (token) {\r\n console.log('โœ… Found token in onairosUser localStorage');\r\n }\r\n }\r\n } catch (e) {\r\n console.error('โŒ Error reading from localStorage:', e);\r\n }\r\n }\r\n\r\n if (!token) {\r\n console.error('โŒ No token found anywhere - cannot run training');\r\n console.error('๐Ÿ’ก Token should be passed from parent component OR stored in localStorage');\r\n throw new Error('No authentication token');\r\n }\r\n \r\n console.log('โœ… Token found, starting Socket.IO training...', token.substring(0, 20) + '...');\r\n\r\n // Phase 1: Connect to Socket.IO\r\n setCurrentStage('training');\r\n setCurrentPhrase('Connecting to server...');\r\n console.log('๐Ÿ”Œ Connecting to Socket.IO server...');\r\n\r\n socket = io('https://api2.onairos.uk', {\r\n auth: { token },\r\n transports: ['websocket', 'polling'],\r\n reconnection: false, // Don't reconnect automatically for this one-time operation\r\n timeout: 60000 // 60 second timeout\r\n });\r\n\r\n // Handle connection\r\n socket.on('connect', () => {\r\n console.log('โœ… Socket connected:', socket.id);\r\n // At this point, training can actually start (server reachable).\r\n signalTrainingStarted();\r\n setCurrentPhrase('Starting training...');\r\n \r\n // Start progress animation\r\n progressTimer = setInterval(() => {\r\n setProgress(prev => {\r\n if (prev < 95) return prev + 0.5; // Slow smooth progress\r\n return prev;\r\n });\r\n }, 200);\r\n\r\n // Trigger training\r\n console.log('๐Ÿš€ Emitting start-training event with:', {\r\n socketId: socket.id,\r\n email: userEmail,\r\n platforms: connectedAccounts\r\n });\r\n\r\n socket.emit('start-training', {\r\n socketId: socket.id,\r\n email: userEmail,\r\n username: userEmail,\r\n platforms: connectedAccounts,\r\n connectedAccounts: connectedAccounts\r\n });\r\n });\r\n\r\n // Handle training progress updates\r\n socket.on('training-progress', (data) => {\r\n console.log('๐Ÿ“Š Training progress:', data);\r\n // Progress events mean training has definitely started.\r\n signalTrainingStarted();\r\n if (data.percentage) {\r\n setProgress(Math.min(data.percentage, 95)); // Cap at 95% until complete\r\n }\r\n if (data.message) {\r\n setCurrentPhrase(data.message);\r\n }\r\n if (data.stage) {\r\n setCurrentStage(data.stage);\r\n }\r\n });\r\n\r\n // Handle training completion\r\n socket.on('training-complete', (result) => {\r\n console.log('โœ… Training complete via Socket.IO:', result);\r\n \r\n if (progressTimer) clearInterval(progressTimer);\r\n setProgress(100);\r\n setCurrentStage('complete');\r\n setCurrentPhrase('Training complete!');\r\n\r\n // Log complete results to console\r\n console.log('\\n๐ŸŽ‰ ===== TRAINING + INFERENCE COMPLETE =====\\n');\r\n console.log('๐Ÿ“Š Training Results:', {\r\n status: 'completed',\r\n userEmail,\r\n connectedPlatforms: connectedAccounts,\r\n traits: result.traits || result.trainingResults?.traits || {},\r\n timestamp: new Date().toISOString()\r\n });\r\n \r\n console.log('\\n๐Ÿง  Traits Retrieved:', {\r\n traits: result.traits || result.trainingResults?.traits || {},\r\n userTraits: result.userTraits || result.trainingResults?.userTraits || {},\r\n hasLlmData: !!result.llmData,\r\n inferenceResults: result.inferenceResults || null\r\n });\r\n \r\n console.log('\\nโœ… Model ready for predictions!\\n');\r\n\r\n // Disconnect socket\r\n socket.disconnect();\r\n\r\n // Complete after short delay\r\n setTimeout(() => {\r\n onComplete?.(result);\r\n }, 500);\r\n });\r\n\r\n // Handle errors\r\n socket.on('training-error', (error) => {\r\n console.error('โŒ Training error from Socket.IO:', error);\r\n \r\n if (progressTimer) clearInterval(progressTimer);\r\n \r\n setProgress(100);\r\n setCurrentPhrase('Error occurred, continuing...');\r\n \r\n socket.disconnect();\r\n \r\n setTimeout(() => {\r\n onComplete?.({ \r\n error: error.message || 'Training failed',\r\n fallback: true \r\n });\r\n }, 500);\r\n });\r\n\r\n // Handle connection errors\r\n socket.on('connect_error', (error) => {\r\n console.error('โŒ Socket.IO connection error:', error);\r\n \r\n if (progressTimer) clearInterval(progressTimer);\r\n \r\n setProgress(100);\r\n setCurrentPhrase('Connection error, continuing...');\r\n \r\n socket.disconnect();\r\n \r\n setTimeout(() => {\r\n onComplete?.({ \r\n error: 'Failed to connect to training server',\r\n fallback: true \r\n });\r\n }, 500);\r\n });\r\n\r\n // Handle disconnect\r\n socket.on('disconnect', (reason) => {\r\n console.log('๐Ÿ”Œ Socket disconnected:', reason);\r\n });\r\n\r\n } catch (error) {\r\n console.error('โŒ Training/Inference Error:', error);\r\n \r\n if (progressTimer) clearInterval(progressTimer);\r\n if (socket) socket.disconnect();\r\n \r\n // Fallback: still complete but show error\r\n console.warn('โš ๏ธ Falling back to cached data or skipping training');\r\n setProgress(100);\r\n setTimeout(() => {\r\n onComplete?.({ \r\n error: error.message,\r\n fallback: true \r\n });\r\n }, 500);\r\n }\r\n };\r\n\r\n runTrainingAndInference();\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (progressTimer) clearInterval(progressTimer);\r\n if (socket) {\r\n console.log('๐Ÿงน Cleaning up socket connection');\r\n socket.disconnect();\r\n }\r\n };\r\n }, [userEmail, connectedAccounts, userToken, onComplete]);\r\n\r\n return (\r\n <div className=\"w-full h-full flex flex-col items-center justify-center p-8 bg-gradient-to-br from-slate-900 via-blue-900 to-slate-900\">\r\n <style>{`\r\n @keyframes float {\r\n 0%, 100% { transform: translateY(0px); }\r\n 50% { transform: translateY(-20px); }\r\n }\r\n .float-animation {\r\n animation: float 6s ease-in-out infinite;\r\n }\r\n .glow-bar {\r\n box-shadow: 0 0 20px rgba(59, 130, 246, 0.5),\r\n 0 0 40px rgba(139, 92, 246, 0.3),\r\n inset 0 0 20px rgba(255, 255, 255, 0.1);\r\n }\r\n `}</style>\r\n\r\n {/* Rain Animation - Sleek and centered */}\r\n <div className=\"w-full max-w-sm mb-6 float-animation\">\r\n <Lottie \r\n lottieRef={lottieRef}\r\n animationData={rainAnim}\r\n loop={true}\r\n autoplay={true}\r\n style={{ width: '100%', height: '240px', filter: 'brightness(1.1)' }}\r\n />\r\n </div>\r\n\r\n {/* Training Status - Sleeker design */}\r\n <div className=\"w-full max-w-lg\">\r\n {/* Title with stage indicator */}\r\n <div className=\"text-center mb-6\">\r\n <div className=\"inline-flex items-center gap-2 mb-3 px-4 py-1.5 rounded-full bg-white/10 backdrop-blur-sm border border-white/20\">\r\n <div className=\"w-2 h-2 rounded-full bg-blue-400 animate-pulse\"></div>\r\n <span className=\"text-xs font-medium text-blue-100 uppercase tracking-wider\">\r\n {currentStage === 'training' ? 'Training Model' : \r\n currentStage === 'inference' ? 'Running Inference' : 'Complete'}\r\n </span>\r\n </div>\r\n \r\n <h2 className=\"text-3xl font-bold text-white mb-2 tracking-tight\">\r\n {currentStage === 'complete' ? 'Ready!' : 'Building Your Profile'}\r\n </h2>\r\n \r\n <p className=\"text-blue-200 text-sm font-medium\">\r\n {currentPhrase}\r\n </p>\r\n </div>\r\n\r\n {/* Progress Bar - Sleek glassmorphism design */}\r\n <div className=\"relative mb-4\">\r\n <div className=\"w-full bg-white/5 backdrop-blur-sm rounded-full h-3 overflow-hidden border border-white/10\">\r\n <div \r\n className=\"h-full rounded-full transition-all duration-300 ease-out glow-bar\"\r\n style={{ \r\n width: `${progress}%`,\r\n background: 'linear-gradient(90deg, #3b82f6 0%, #8b5cf6 50%, #ec4899 100%)'\r\n }}\r\n />\r\n </div>\r\n \r\n {/* Progress percentage overlay */}\r\n <div className=\"absolute inset-0 flex items-center justify-center\">\r\n <span className=\"text-xs font-bold text-white drop-shadow-lg\">\r\n {progress}%\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Stage indicators */}\r\n <div className=\"flex justify-between items-center px-2 mb-6\">\r\n <div className={`text-xs font-medium transition-colors ${progress >= 0 ? 'text-blue-400' : 'text-gray-500'}`}>\r\n Training\r\n </div>\r\n <div className={`text-xs font-medium transition-colors ${progress >= 50 ? 'text-purple-400' : 'text-gray-500'}`}>\r\n Inference\r\n </div>\r\n <div className={`text-xs font-medium transition-colors ${progress >= 100 ? 'text-pink-400' : 'text-gray-500'}`}>\r\n Complete\r\n </div>\r\n </div>\r\n\r\n {/* Info box - Sleek and minimal */}\r\n <div className=\"mt-6 p-4 rounded-2xl bg-white/5 backdrop-blur-md border border-white/10\">\r\n <div className=\"flex items-center justify-center gap-2 text-blue-100\">\r\n <svg className=\"w-4 h-4\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\r\n <path fillRule=\"evenodd\" d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z\" clipRule=\"evenodd\" />\r\n </svg>\r\n <p className=\"text-xs\">\r\n Processing your data securely โ€ข {connectedAccounts.length} {connectedAccounts.length === 1 ? 'platform' : 'platforms'} connected\r\n </p>\r\n </div>\r\n </div> \r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React, { useState, useEffect } from \"react\";\r\nimport Lottie from 'lottie-react';\r\nimport rainAnim from '../../public/rain-anim.json';\r\n\r\nexport default function LoadingScreen({ onComplete }) {\r\n const [currentStep, setCurrentStep] = useState(0);\r\n const [dotCount, setDotCount] = useState(0);\r\n\r\n const loadingStates = [\r\n { message: \"Validating PIN and continuing training\", progress: 20 },\r\n { message: \"Uploading model to secure storage\", progress: 40 },\r\n { message: \"Running test inference\", progress: 60 },\r\n { message: \"Storing results in databases\", progress: 80 },\r\n { message: \"Complete!\", progress: 100 },\r\n ];\r\n\r\n useEffect(() => {\r\n const stateInterval = setInterval(() => {\r\n setCurrentStep((prev) => {\r\n const nextStep = prev + 1;\r\n if (nextStep >= loadingStates.length) {\r\n // Loading complete, call onComplete after a short delay\r\n setTimeout(() => {\r\n onComplete();\r\n }, 1000);\r\n return prev; // Keep at last step\r\n }\r\n return nextStep;\r\n });\r\n }, 3000); // Change state every 3 seconds\r\n\r\n return () => clearInterval(stateInterval);\r\n }, [loadingStates.length, onComplete]);\r\n\r\n useEffect(() => {\r\n const dotInterval = setInterval(() => {\r\n setDotCount((prev) => (prev + 1) % 4); // 0, 1, 2, 3 dots\r\n }, 500); // Change dots every 500ms\r\n\r\n return () => clearInterval(dotInterval);\r\n }, []);\r\n\r\n const currentState = loadingStates[currentStep];\r\n\r\n return (\r\n <div className=\"fixed inset-0 bg-gray-500 bg-opacity-50 flex items-center justify-center p-6\" style={{ zIndex: 2147483647, pointerEvents: 'auto' }}>\r\n {/* Modal - Full height from bottom */}\r\n <div className=\"bg-white rounded-3xl w-full max-w-lg mx-auto shadow-2xl overflow-hidden flex flex-col\" style={{ maxWidth: '500px', height: '100%', maxHeight: '90vh' }}>\r\n {/* Header */}\r\n <div className=\"px-6 pt-6 pb-4 flex-shrink-0\">\r\n </div>\r\n\r\n {/* Content - Rain animation and loading state */}\r\n <div className=\"flex-1 flex flex-col px-6\">\r\n {/* Rain Animation */}\r\n <div className=\"flex-1 flex items-center justify-center\">\r\n <div style={{ width: '100%', maxWidth: '400px', aspectRatio: '1' }}>\r\n <Lottie\r\n animationData={rainAnim}\r\n loop={true}\r\n autoplay={true}\r\n style={{ width: '100%', height: '100%' }}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Loading State - Positioned at bottom */}\r\n <div className=\"flex-shrink-0 pb-12\">\r\n <div className=\"text-center\">\r\n <h1 className=\"font-bold text-gray-900 leading-tight mb-6\" style={{ fontSize: 'clamp(16px, 4vw, 20px)' }}>\r\n {currentState.message}\r\n {currentState.message !== \"Complete!\" && (\r\n <span className=\"inline-block w-8 text-left\">{\".\".repeat(dotCount)}</span>\r\n )}\r\n </h1>\r\n\r\n <div className=\"mx-auto\" style={{ width: 'clamp(200px, 50vw, 300px)' }}>\r\n <div className=\"w-full h-2 bg-gray-200 rounded-full\">\r\n <div\r\n className=\"h-2 bg-gray-900 rounded-full transition-all duration-1000 ease-out\"\r\n style={{ width: `${currentState.progress}%` }}\r\n ></div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Bottom spacing */}\r\n <div className=\"h-20 flex-shrink-0\"></div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import React, { useEffect, useState } from 'react';\r\nimport Lottie from 'lottie-react';\r\n\r\nexport default function WrappedLoadingPage({ appName }) {\r\n const [animationData, setAnimationData] = useState(null);\r\n const [progress, setProgress] = useState(0);\r\n const [messageIndex, setMessageIndex] = useState(0);\r\n \r\n // Only show \"Updating your digital brain for 2025...\" if app name contains \"wrapped\"\r\n const isWrappedApp = appName && appName.toLowerCase().includes('wrapped');\r\n\r\n // Whimsical rotating messages\r\n const messages = [\r\n \"Reading your mind...\",\r\n \"Connecting the dots...\",\r\n \"Brewing insights...\",\r\n \"Decoding your vibe...\",\r\n \"Piecing together your story...\",\r\n \"Finding patterns in the chaos...\",\r\n \"Translating data to wisdom...\",\r\n \"Your digital fingerprint is unique...\",\r\n \"Almost done thinking...\",\r\n \"Polishing the final details...\"\r\n ];\r\n\r\n useEffect(() => {\r\n // Fetch the animation JSON from public folder\r\n fetch('/rain-anim.json')\r\n .then(res => res.json())\r\n .then(data => setAnimationData(data))\r\n .catch(err => {\r\n console.error('Failed to load rain animation:', err);\r\n // Fallback: try from the npm package public folder\r\n fetch('https://onairos.sirv.com/rain-anim.json')\r\n .then(res => res.json())\r\n .then(data => setAnimationData(data))\r\n .catch(err2 => console.error('Failed to load rain animation from fallback:', err2));\r\n });\r\n }, []);\r\n\r\n // Animate progress bar over ~2 minutes (API can take 1-3 minutes)\r\n useEffect(() => {\r\n const duration = 120000; // 2 minutes in ms\r\n const interval = 100; // Update every 100ms\r\n const increment = (interval / duration) * 100;\r\n \r\n const timer = setInterval(() => {\r\n setProgress(prev => {\r\n const next = prev + increment;\r\n // Cap at 95% to avoid reaching 100% before API completes\r\n return next >= 95 ? 95 : next;\r\n });\r\n }, interval);\r\n\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n // Rotate messages every 4 seconds\r\n useEffect(() => {\r\n const messageTimer = setInterval(() => {\r\n setMessageIndex(prev => (prev + 1) % messages.length);\r\n }, 4000);\r\n\r\n return () => clearInterval(messageTimer);\r\n }, []);\r\n\r\n return (\r\n <div className=\"flex flex-col items-center justify-center h-full px-6 py-4\">\r\n {/* Content is centered vertically inside the modal card */}\r\n <div className=\"flex flex-col items-center justify-center w-full max-w-2xl space-y-6\">\r\n {/* Title */}\r\n <div className=\"text-center\">\r\n <h2 className=\"text-xl md:text-2xl font-semibold text-gray-900 mb-1\">\r\n {isWrappedApp ? 'Updating your digital brain for 2025...' : 'Processing your data...'}\r\n </h2>\r\n <p className=\"text-xs md:text-sm text-gray-600\">\r\n {isWrappedApp ? 'Crafting your personalized insights from your digital footprint' : 'This will just take a moment'}\r\n </p>\r\n </div>\r\n\r\n {/* Lottie Animation */}\r\n {animationData ? (\r\n <div className=\"w-full max-w-sm mx-auto\">\r\n {/* Fixed aspect ratio so the figure sits nicely in the center and never clips */}\r\n <div className=\"relative w-full\" style={{ paddingBottom: '100%' }}>\r\n <Lottie \r\n animationData={animationData}\r\n loop={true}\r\n autoplay={true}\r\n className=\"absolute inset-0 w-full h-full\"\r\n />\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"w-full max-w-sm h-64 flex items-center justify-center\">\r\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-gray-900\"></div>\r\n </div>\r\n )}\r\n\r\n {/* Black and White Loading Bar - Below Lottie */}\r\n <div className=\"w-full max-w-md\">\r\n <div className=\"relative w-full h-1.5 bg-gray-200 rounded-full overflow-hidden\">\r\n <div \r\n className=\"absolute top-0 left-0 h-full bg-gray-900 rounded-full transition-all duration-300 ease-out\"\r\n style={{ \r\n width: `${progress}%`\r\n }}\r\n />\r\n </div>\r\n \r\n {/* Rotating message with fade transition */}\r\n <p \r\n key={messageIndex}\r\n className=\"text-center text-xs text-gray-600 mt-3 animate-fadeIn\"\r\n style={{ \r\n animation: 'fadeIn 0.5s ease-in-out'\r\n }}\r\n >\r\n {messages[messageIndex]}\r\n </p>\r\n </div>\r\n\r\n <style>{`\r\n @keyframes fadeIn {\r\n 0% { opacity: 0; transform: translateY(-4px); }\r\n 100% { opacity: 1; transform: translateY(0); }\r\n }\r\n `}</style>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\n","/**\r\n * Response formatter utility for Onairos SDK\r\n * Converts array-based responses to dictionary format for better developer experience\r\n */\r\n\r\n// Standard 16 personality types in order that the API returns them\r\nexport const PERSONALITY_TYPES = [\r\n 'Analyst',\r\n 'Diplomat', \r\n 'Sentinel',\r\n 'Explorer',\r\n 'Architect',\r\n 'Logician',\r\n 'Commander',\r\n 'Debater',\r\n 'Advocate',\r\n 'Mediator',\r\n 'Protagonist',\r\n 'Campaigner',\r\n 'Logistician',\r\n 'Defender',\r\n 'Executive',\r\n 'Consul'\r\n];\r\n\r\n// Standard trait categories that might be returned\r\nexport const TRAIT_CATEGORIES = [\r\n 'Openness',\r\n 'Conscientiousness',\r\n 'Extraversion',\r\n 'Agreeableness',\r\n 'Neuroticism'\r\n];\r\n\r\n/**\r\n * Formats API response to include both array and dictionary formats\r\n * @param {Object} apiResponse - Raw API response from Onairos\r\n * @param {Object} options - Formatting options\r\n * @param {boolean} options.includeDictionary - Whether to include dictionary format (default: true)\r\n * @param {boolean} options.includeArray - Whether to include original array format (default: true)\r\n * @returns {Object} Formatted response with both formats\r\n */\r\nexport function formatOnairosResponse(apiResponse, options = {}) {\r\n const { includeDictionary = true, includeArray = true } = options;\r\n \r\n if (!apiResponse) {\r\n return apiResponse;\r\n }\r\n\r\n const formatted = { ...apiResponse };\r\n\r\n // Handle personality scores if present\r\n if (apiResponse.InferenceResult?.traits || apiResponse.traits || apiResponse.scores) {\r\n const scores = apiResponse.InferenceResult?.traits || apiResponse.traits || apiResponse.scores;\r\n \r\n if (Array.isArray(scores) && scores.length >= 16) {\r\n if (includeDictionary) {\r\n // Create personality dictionary\r\n const personalityDict = {};\r\n PERSONALITY_TYPES.forEach((type, index) => {\r\n personalityDict[type] = scores[index];\r\n });\r\n \r\n // Add to formatted response\r\n if (formatted.InferenceResult) {\r\n formatted.InferenceResult.personalityDict = personalityDict;\r\n } else {\r\n formatted.personalityDict = personalityDict;\r\n }\r\n }\r\n \r\n if (!includeArray) {\r\n // Remove array format if not requested\r\n if (formatted.InferenceResult?.traits) {\r\n delete formatted.InferenceResult.traits;\r\n }\r\n if (formatted.traits) {\r\n delete formatted.traits;\r\n }\r\n if (formatted.scores) {\r\n delete formatted.scores;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Handle trait data if present (for preferences/traits)\r\n if (apiResponse.traitResult || apiResponse.traits) {\r\n const traits = apiResponse.traitResult || apiResponse.traits;\r\n \r\n if (Array.isArray(traits) && includeDictionary) {\r\n const traitDict = {};\r\n TRAIT_CATEGORIES.forEach((category, index) => {\r\n if (traits[index] !== undefined) {\r\n traitDict[category] = traits[index];\r\n }\r\n });\r\n \r\n formatted.traitDict = traitDict;\r\n }\r\n }\r\n\r\n return formatted;\r\n}\r\n\r\n/**\r\n * Legacy formatter for backward compatibility\r\n * Converts scores array to personality dictionary only\r\n * @param {Array} scores - Array of personality scores\r\n * @returns {Object} Dictionary with personality type names as keys\r\n */\r\nexport function formatPersonalityScores(scores) {\r\n if (!Array.isArray(scores) || scores.length < 16) {\r\n console.warn('Invalid scores array provided to formatPersonalityScores');\r\n return {};\r\n }\r\n\r\n const personalityDict = {};\r\n PERSONALITY_TYPES.forEach((type, index) => {\r\n personalityDict[type] = scores[index];\r\n });\r\n \r\n return personalityDict;\r\n}\r\n\r\n/**\r\n * Get personality type names in order\r\n * @returns {Array} Array of personality type names\r\n */\r\nexport function getPersonalityTypes() {\r\n return [...PERSONALITY_TYPES];\r\n}\r\n\r\n/**\r\n * Get trait category names in order \r\n * @returns {Array} Array of trait category names\r\n */\r\nexport function getTraitCategories() {\r\n return [...TRAIT_CATEGORIES];\r\n} ","/**\r\n * Enhanced User Data Formatter for onComplete Callback\r\n * Provides structured, readable formatting of Onairos user data\r\n */\r\n\r\n/**\r\n * Formats user data for better readability in onComplete callback\r\n * @param {Object} result - The complete result object from data request\r\n * @returns {Object} Enhanced result with formatted user data display\r\n */\r\nexport function formatUserDataForDisplay(result) {\r\n if (!result) return result;\r\n\r\n const formatted = { ...result };\r\n \r\n // Create a structured summary of the user data\r\n const userDataSummary = {\r\n // Basic request information\r\n requestInfo: {\r\n timestamp: result.timestamp || new Date().toISOString(),\r\n appName: result.appName || 'Unknown App',\r\n userHash: result.userHash || 'Unknown User',\r\n testMode: result.testMode || false,\r\n dataTypesRequested: Array.isArray(result.approvedData) ? result.approvedData : (result.approved || [])\r\n },\r\n \r\n // User authentication and profile data\r\n userProfile: {\r\n email: result.userData?.email || 'Not provided',\r\n userType: result.userData?.userType || 'Unknown',\r\n onboardingComplete: result.userData?.onboardingComplete || false,\r\n pinCreated: result.userData?.pinCreated || false,\r\n trainingComplete: result.userData?.trainingComplete || false,\r\n modelReady: result.userData?.modelReady || false\r\n },\r\n \r\n // Connected platforms/accounts\r\n connectedAccounts: formatConnectedAccounts(result.userData?.connectedAccounts || []),\r\n \r\n // API response data (personality, preferences, etc.)\r\n aiData: formatAIResponseData(result.apiResponse),\r\n \r\n // Success status and any errors\r\n status: {\r\n success: result.success || false,\r\n hasApiResponse: !!result.apiResponse,\r\n hasErrors: !!result.error || !!result.apiError\r\n }\r\n };\r\n\r\n // Add the formatted summary to the result\r\n formatted.userDataSummary = userDataSummary;\r\n \r\n // Create a pretty-printed version for console logging\r\n formatted.prettyPrint = createPrettyPrintVersion(userDataSummary);\r\n \r\n return formatted;\r\n}\r\n\r\n/**\r\n * Formats connected accounts data\r\n * @param {Array} accounts - Array of connected account objects\r\n * @returns {Object} Formatted accounts summary\r\n */\r\nfunction formatConnectedAccounts(accounts) {\r\n if (!Array.isArray(accounts) || accounts.length === 0) {\r\n return {\r\n count: 0,\r\n platforms: [],\r\n summary: 'No connected accounts'\r\n };\r\n }\r\n\r\n return {\r\n count: accounts.length,\r\n platforms: accounts.map(account => ({\r\n name: account.platform || account.name || 'Unknown Platform',\r\n status: account.status || 'Unknown',\r\n connectedAt: account.connectedAt || 'Unknown date',\r\n hasData: account.hasData || false\r\n })),\r\n summary: `${accounts.length} platform(s) connected: ${accounts.map(a => a.platform || a.name).join(', ')}`\r\n };\r\n}\r\n\r\n/**\r\n * Formats AI response data (personality scores, traits, etc.)\r\n * @param {Object} apiResponse - The API response containing AI data\r\n * @returns {Object} Formatted AI data summary\r\n */\r\nfunction formatAIResponseData(apiResponse) {\r\n if (!apiResponse) {\r\n return {\r\n available: false,\r\n summary: 'No AI data available'\r\n };\r\n }\r\n\r\n const aiData = {\r\n available: true,\r\n dataTypes: []\r\n };\r\n\r\n // Check for Onairos Wrapped Dashboard\r\n if (apiResponse.data?.dashboard || apiResponse.dashboard || apiResponse.slides) {\r\n aiData.dataTypes.push({\r\n type: 'wrapped_dashboard',\r\n available: true,\r\n data: apiResponse.data?.dashboard || apiResponse.dashboard || apiResponse,\r\n summary: 'Onairos Wrapped / Neural Recall Dashboard'\r\n });\r\n \r\n // Add apps if available\r\n if (apiResponse.data?.apps || apiResponse.apps) {\r\n aiData.dataTypes.push({\r\n type: 'connected_apps',\r\n available: true,\r\n data: apiResponse.data?.apps || apiResponse.apps,\r\n summary: `Connected apps list (${(apiResponse.data?.apps || apiResponse.apps).length})`\r\n });\r\n }\r\n }\r\n\r\n // Check for personality data\r\n if (apiResponse.InferenceResult?.traits || apiResponse.personalityDict || apiResponse.traits) {\r\n const personalityData = {\r\n type: 'personality',\r\n available: true\r\n };\r\n\r\n // If we have dictionary format, use it for better readability\r\n if (apiResponse.personalityDict) {\r\n personalityData.data = apiResponse.personalityDict;\r\n personalityData.summary = `Personality analysis with ${Object.keys(apiResponse.personalityDict).length} traits`;\r\n } else if (apiResponse.InferenceResult?.traits) {\r\n personalityData.data = apiResponse.InferenceResult.traits;\r\n personalityData.summary = `Personality scores array with ${apiResponse.InferenceResult.traits.length} values`;\r\n } else if (apiResponse.traits) {\r\n personalityData.data = apiResponse.traits;\r\n personalityData.summary = `Personality traits with ${Array.isArray(apiResponse.traits) ? apiResponse.traits.length : Object.keys(apiResponse.traits).length} items`;\r\n }\r\n\r\n aiData.dataTypes.push(personalityData);\r\n }\r\n\r\n // Check for preferences/traits data\r\n if (apiResponse.traitResult || apiResponse.traitDict) {\r\n const preferencesData = {\r\n type: 'preferences',\r\n available: true\r\n };\r\n\r\n if (apiResponse.traitDict) {\r\n preferencesData.data = apiResponse.traitDict;\r\n preferencesData.summary = `Preferences analysis with ${Object.keys(apiResponse.traitDict).length} categories`;\r\n } else if (apiResponse.traitResult) {\r\n preferencesData.data = apiResponse.traitResult;\r\n preferencesData.summary = `Trait results with ${Array.isArray(apiResponse.traitResult) ? apiResponse.traitResult.length : Object.keys(apiResponse.traitResult).length} items`;\r\n }\r\n\r\n aiData.dataTypes.push(preferencesData);\r\n }\r\n\r\n // Check for basic info/output\r\n if (apiResponse.InferenceResult?.output || apiResponse.output) {\r\n aiData.dataTypes.push({\r\n type: 'basic_info',\r\n available: true,\r\n data: apiResponse.InferenceResult?.output || apiResponse.output,\r\n summary: 'Basic user information and insights'\r\n });\r\n }\r\n\r\n // Create overall summary\r\n aiData.summary = aiData.dataTypes.length > 0 \r\n ? `AI analysis complete with ${aiData.dataTypes.length} data type(s): ${aiData.dataTypes.map(d => d.type).join(', ')}`\r\n : 'AI data structure present but no recognized data types found';\r\n\r\n return aiData;\r\n}\r\n\r\n/**\r\n * Creates a pretty-printed version for console logging\r\n * @param {Object} userDataSummary - The formatted user data summary\r\n * @returns {string} Pretty-printed string for console output\r\n */\r\nfunction createPrettyPrintVersion(userDataSummary) {\r\n const lines = [];\r\n \r\n lines.push('๐ŸŽ‰ ONAIROS USER DATA SUMMARY');\r\n lines.push('=' .repeat(50));\r\n \r\n // Request Info\r\n lines.push('\\n๐Ÿ“‹ REQUEST INFORMATION:');\r\n lines.push(` App: ${userDataSummary.requestInfo.appName}`);\r\n lines.push(` User: ${userDataSummary.requestInfo.userHash}`);\r\n lines.push(` Mode: ${userDataSummary.requestInfo.testMode ? 'Test' : 'Production'}`);\r\n lines.push(` Data Types: ${Array.isArray(userDataSummary.requestInfo.dataTypesRequested) && userDataSummary.requestInfo.dataTypesRequested.length > 0 ? userDataSummary.requestInfo.dataTypesRequested.join(', ') : 'None'}`);\r\n lines.push(` Timestamp: ${new Date(userDataSummary.requestInfo.timestamp).toLocaleString()}`);\r\n \r\n // User Profile\r\n lines.push('\\n๐Ÿ‘ค USER PROFILE:');\r\n lines.push(` Email: ${userDataSummary.userProfile.email}`);\r\n lines.push(` Type: ${userDataSummary.userProfile.userType}`);\r\n lines.push(` Onboarding: ${userDataSummary.userProfile.onboardingComplete ? 'โœ…' : 'โŒ'}`);\r\n lines.push(` PIN Setup: ${userDataSummary.userProfile.pinCreated ? 'โœ…' : 'โŒ'}`);\r\n lines.push(` Training: ${userDataSummary.userProfile.trainingComplete ? 'โœ…' : 'โŒ'}`);\r\n lines.push(` Model Ready: ${userDataSummary.userProfile.modelReady ? 'โœ…' : 'โŒ'}`);\r\n \r\n // Connected Accounts\r\n lines.push('\\n๐Ÿ”— CONNECTED ACCOUNTS:');\r\n lines.push(` ${userDataSummary.connectedAccounts.summary}`);\r\n if (userDataSummary.connectedAccounts.platforms.length > 0) {\r\n userDataSummary.connectedAccounts.platforms.forEach(platform => {\r\n lines.push(` โ€ข ${platform.name}: ${platform.status} ${platform.hasData ? '(has data)' : '(no data)'}`);\r\n });\r\n }\r\n \r\n // AI Data\r\n lines.push('\\n๐Ÿค– AI ANALYSIS DATA:');\r\n lines.push(` ${userDataSummary.aiData.summary}`);\r\n if (userDataSummary.aiData.dataTypes.length > 0) {\r\n userDataSummary.aiData.dataTypes.forEach(dataType => {\r\n lines.push(` โ€ข ${dataType.type.toUpperCase()}: ${dataType.summary}`);\r\n });\r\n }\r\n \r\n // Status\r\n lines.push('\\nโœ… STATUS:');\r\n lines.push(` Success: ${userDataSummary.status.success ? 'โœ…' : 'โŒ'}`);\r\n lines.push(` API Response: ${userDataSummary.status.hasApiResponse ? 'โœ…' : 'โŒ'}`);\r\n lines.push(` Errors: ${userDataSummary.status.hasErrors ? 'โŒ Yes' : 'โœ… None'}`);\r\n \r\n lines.push('\\n' + '=' .repeat(50));\r\n \r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Console logging helper that prints formatted user data\r\n * @param {Object} result - The result object from onComplete\r\n */\r\nexport function logFormattedUserData(result) {\r\n const formatted = formatUserDataForDisplay(result);\r\n \r\n console.log('\\n' + formatted.prettyPrint + '\\n');\r\n \r\n // Also log the structured data for programmatic access\r\n console.log('๐Ÿ“Š Structured User Data Summary:', formatted.userDataSummary);\r\n \r\n return formatted;\r\n}\r\n\r\nexport default {\r\n formatUserDataForDisplay,\r\n logFormattedUserData\r\n};\r\n","import React, { useEffect, useMemo, useState } from 'react';\r\nimport { COLORS } from '../../theme/colors.js';\r\n\r\n// Standardized page layout component with white background\r\nconst PageLayout = ({\r\n children,\r\n title,\r\n subtitle,\r\n icon,\r\n showHeader = true,\r\n showCloseButton = false,\r\n onClose,\r\n onBack,\r\n showBackButton = false,\r\n className = '',\r\n contentClassName = '',\r\n centerContent = true,\r\n style = {},\r\n ...props\r\n}) => {\r\n const isSmallScreen = typeof window !== 'undefined' && window.innerWidth <= 768;\r\n\r\n const layoutStyle = {\r\n backgroundColor: COLORS.background,\r\n minHeight: '100%',\r\n width: '100%',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n ...style\r\n };\r\n\r\n const headerStyle = {\r\n position: 'sticky',\r\n top: 0,\r\n backgroundColor: COLORS.background,\r\n zIndex: 10,\r\n padding: isSmallScreen\r\n ? '10px 16px 8px'\r\n : 'clamp(8px, 2vw, 16px) clamp(16px, 4vw, 32px) clamp(6px, 1.5vw, 12px)'\r\n };\r\n\r\n const contentStyle = {\r\n flex: 1,\r\n padding: isSmallScreen ? '16px 16px 18px' : 'clamp(16px, 4vw, 32px)',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n overflow: 'auto',\r\n minHeight: 0, // Allow flex item to shrink below content size\r\n ...(centerContent && {\r\n alignItems: 'center',\r\n justifyContent: 'flex-start'\r\n })\r\n };\r\n\r\n const titleStyle = {\r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n fontSize: 'clamp(20px, 5vw, 28px)',\r\n fontWeight: '700',\r\n color: COLORS.textPrimary,\r\n margin: '0 0 clamp(6px, 1.5vw, 12px) 0',\r\n textAlign: centerContent ? 'center' : 'left',\r\n lineHeight: '1.2'\r\n };\r\n\r\n const subtitleStyle = {\r\n fontFamily: 'Inter, system-ui, sans-serif',\r\n fontSize: 'clamp(14px, 3.5vw, 18px)',\r\n fontWeight: '400',\r\n color: COLORS.textSecondary,\r\n margin: isSmallScreen ? '0 0 18px 0' : '0 0 clamp(20px, 5vw, 40px) 0',\r\n textAlign: centerContent ? 'center' : 'left',\r\n lineHeight: '1.5'\r\n };\r\n\r\n const iconStyle = {\r\n width: 'clamp(40px, 8vw, 56px)',\r\n height: 'clamp(40px, 8vw, 56px)',\r\n margin: '0 auto clamp(16px, 4vw, 32px)',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n fontSize: 'clamp(20px, 5vw, 28px)'\r\n };\r\n\r\n return (\r\n <div \r\n className={`onairos-page-layout ${className}`}\r\n style={layoutStyle}\r\n {...props}\r\n >\r\n {/* Header with navigation */}\r\n {showHeader && (\r\n <div style={headerStyle}>\r\n <div className=\"flex items-center justify-between\">\r\n {/* Back button */}\r\n {showBackButton && onBack && (\r\n <button\r\n onClick={onBack}\r\n className=\"flex items-center justify-center w-8 h-8 rounded-full hover:bg-gray-100 transition-colors\"\r\n aria-label=\"Go back\"\r\n >\r\n <span style={{ fontSize: '16px', color: COLORS.textPrimary }}>โ†</span>\r\n </button>\r\n )}\r\n\r\n\r\n {/* Close button */}\r\n {showCloseButton && onClose && (\r\n <button\r\n onClick={onClose}\r\n className=\"flex items-center justify-center w-8 h-8 rounded-full hover:bg-gray-100 transition-colors\"\r\n aria-label=\"Close\"\r\n >\r\n <span style={{ fontSize: '16px', color: COLORS.textPrimary }}>ร—</span>\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Main content area */}\r\n <div \r\n className={`onairos-page-content ${contentClassName}`}\r\n style={contentStyle}\r\n >\r\n {/* Icon */}\r\n {icon && (\r\n <div style={iconStyle}>\r\n {typeof icon === 'string' ? <span>{icon}</span> : icon}\r\n </div>\r\n )}\r\n\r\n {/* Title */}\r\n {title && (\r\n <h1 style={titleStyle}>\r\n {title}\r\n </h1>\r\n )}\r\n\r\n {/* Subtitle */}\r\n {subtitle && (\r\n <p style={subtitleStyle}>\r\n {subtitle}\r\n </p>\r\n )}\r\n\r\n {/* Page content */}\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// Modal wrapper component for overlay-style pages\r\nconst ModalPageLayout = ({\r\n children,\r\n visible = true,\r\n onClose,\r\n onBackdropClick,\r\n backdropStyle = {},\r\n modalStyle = {},\r\n modalClassName = '',\r\n ...pageLayoutProps\r\n}) => {\r\n if (!visible) return null;\r\n\r\n // Detect Capacitor native platform\r\n // Must be defined BEFORE usage to avoid Temporal Dead Zone (TDZ) error\r\n const isCapacitorNative = typeof window !== 'undefined' && \r\n window.Capacitor && \r\n typeof window.Capacitor.isNativePlatform === 'function' && \r\n window.Capacitor.isNativePlatform();\r\n \r\n // Detect mobile browser (not Capacitor native)\r\n const isMobileBrowser = typeof window !== 'undefined' && \r\n window.innerWidth <= 768 && \r\n !isCapacitorNative;\r\n\r\n // Use visualViewport to avoid iOS \"vh\" causing phantom scroll and clipped content.\r\n const [mobileModalHeightPx, setMobileModalHeightPx] = useState(() => {\r\n if (typeof window === 'undefined') return null;\r\n if (!isMobileBrowser) return null;\r\n const h = window.visualViewport?.height || window.innerHeight;\r\n return Math.round(h * 0.8);\r\n });\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n if (!isMobileBrowser) return;\r\n const compute = () => {\r\n const h = window.visualViewport?.height || window.innerHeight;\r\n setMobileModalHeightPx(Math.round(h * 0.8));\r\n };\r\n compute();\r\n window.addEventListener('resize', compute);\r\n window.visualViewport?.addEventListener?.('resize', compute);\r\n window.visualViewport?.addEventListener?.('scroll', compute);\r\n return () => {\r\n window.removeEventListener('resize', compute);\r\n window.visualViewport?.removeEventListener?.('resize', compute);\r\n window.visualViewport?.removeEventListener?.('scroll', compute);\r\n };\r\n }, [isMobileBrowser]);\r\n \r\n // ENHANCED DEBUG LOGGING for mobile browser height issues\r\n if (typeof window !== 'undefined') {\r\n console.log('[Onairos SDK][ModalPageLayout] Mobile Detection', {\r\n width: window.innerWidth,\r\n height: window.innerHeight,\r\n isCapacitorNative,\r\n isMobileBrowser,\r\n modalHeight: isMobileBrowser ? '80vh' : (isCapacitorNative ? '100vh' : 'auto'),\r\n modalMaxHeight: isMobileBrowser ? '80vh' : (isCapacitorNative ? '100vh' : '90vh'),\r\n modalMaxWidth: isMobileBrowser ? '100%' : '500px',\r\n backdropAlign: (isCapacitorNative || isMobileBrowser) ? 'flex-end' : 'center',\r\n backdropPadding: isMobileBrowser ? '0' : '16px'\r\n });\r\n }\r\n\r\n const backdropStyles = {\r\n position: 'fixed',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\r\n zIndex: 2147483647,\r\n display: 'flex',\r\n alignItems: (isCapacitorNative || isMobileBrowser) ? 'flex-end' : 'center',\r\n justifyContent: 'center',\r\n padding: isMobileBrowser ? '0' : '16px',\r\n transition: 'opacity 200ms ease',\r\n willChange: 'opacity',\r\n ...backdropStyle\r\n };\r\n \r\n console.log('[Onairos SDK][ModalPageLayout] ๐ŸŽฏ Backdrop Styles COMPUTED:', {\r\n alignItems: backdropStyles.alignItems,\r\n padding: backdropStyles.padding,\r\n display: backdropStyles.display,\r\n hasBackdropStyleOverride: Object.keys(backdropStyle).length > 0,\r\n backdropStyleOverride: backdropStyle\r\n });\r\n \r\n const modalStyles = {\r\n backgroundColor: COLORS.background,\r\n borderTopLeftRadius: '24px',\r\n borderTopRightRadius: '24px',\r\n borderBottomLeftRadius: (isCapacitorNative || isMobileBrowser) ? '0px' : '24px',\r\n borderBottomRightRadius: (isCapacitorNative || isMobileBrowser) ? '0px' : '24px',\r\n // Force height on mobile browser with !important via inline style\r\n height: isMobileBrowser ? (mobileModalHeightPx ? `${mobileModalHeightPx}px` : '80vh') : (isCapacitorNative ? '100vh' : 'auto'),\r\n maxHeight: isMobileBrowser ? (mobileModalHeightPx ? `${mobileModalHeightPx}px` : '80vh') : (isCapacitorNative ? '100vh' : '90vh'),\r\n minHeight: (isCapacitorNative || isMobileBrowser) ? 'auto' : '600px',\r\n width: '100%',\r\n maxWidth: isMobileBrowser ? '100%' : '500px',\r\n boxShadow: '0 -10px 40px rgba(0, 0, 0, 0.3)',\r\n overflow: 'hidden',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n // iOS safe-area: extend the white modal background into the home-indicator inset\r\n ...(isMobileBrowser ? { paddingBottom: 'env(safe-area-inset-bottom)' } : {}),\r\n transform: 'translateY(0)',\r\n transition: 'transform 220ms ease, opacity 220ms ease',\r\n willChange: 'transform, opacity',\r\n marginLeft: (isCapacitorNative || isMobileBrowser) ? '0' : 'auto',\r\n marginRight: (isCapacitorNative || isMobileBrowser) ? '0' : 'auto',\r\n marginBottom: isMobileBrowser ? '0' : 'auto',\r\n marginTop: isMobileBrowser ? 'auto' : 'auto',\r\n // Ensure full height on Capacitor native\r\n ...(isCapacitorNative && {\r\n position: 'absolute',\r\n bottom: 0,\r\n left: 0,\r\n right: 0,\r\n top: 0,\r\n borderRadius: 0\r\n }),\r\n // Position mobile browser modal at bottom\r\n ...(isMobileBrowser && {\r\n flexShrink: 0\r\n }),\r\n // CRITICAL: Do NOT spread modalStyle on mobile browser - it breaks height\r\n ...(isMobileBrowser ? {} : modalStyle)\r\n };\r\n \r\n console.log('[Onairos SDK][ModalPageLayout] ๐ŸŽจ Modal Styles COMPUTED:', {\r\n height: modalStyles.height,\r\n maxHeight: modalStyles.maxHeight,\r\n minHeight: modalStyles.minHeight,\r\n width: modalStyles.width,\r\n maxWidth: modalStyles.maxWidth,\r\n borderRadius: `${modalStyles.borderTopLeftRadius} / ${modalStyles.borderBottomLeftRadius}`,\r\n hasModalStyleOverride: Object.keys(modalStyle).length > 0,\r\n modalStyleWasApplied: isMobileBrowser ? 'NO (blocked for mobile)' : 'YES',\r\n modalStyleOverride: modalStyle\r\n });\r\n \r\n // Warn if modalStyle is trying to override on mobile browser\r\n if (isMobileBrowser && modalStyle && Object.keys(modalStyle).length > 0) {\r\n console.warn('[Onairos SDK][ModalPageLayout] โš ๏ธ BLOCKED modalStyle override on mobile browser. Ignoring:', modalStyle);\r\n }\r\n\r\n // ๐Ÿ” Layout debug logging (desktop vs native)\r\n try {\r\n if (typeof window !== 'undefined') {\r\n const width = window.innerWidth;\r\n const isDesktop = width >= 1024 && !isCapacitorNative;\r\n // Only spam logs in desktop where sizing issues occur\r\n if (isDesktop) {\r\n // Keep this fairly compact but detailed\r\n console.log('[Onairos SDK][Layout][ModalPageLayout]', {\r\n width,\r\n isCapacitorNative,\r\n modalClassName,\r\n modalStyleKeys: Object.keys(modalStyle || {}),\r\n backdropStyleKeys: Object.keys(backdropStyle || {}),\r\n modalMaxWidth: modalStyles.maxWidth,\r\n modalMinHeight: modalStyles.minHeight,\r\n modalHeight: modalStyles.height,\r\n });\r\n }\r\n }\r\n } catch (e) {\r\n // Never let logging break rendering\r\n }\r\n\r\n const handleBackdropClick = (e) => {\r\n if (e.target === e.currentTarget) {\r\n console.log('๐Ÿ”˜ Backdrop clicked outside modal');\r\n if (onBackdropClick) {\r\n console.log('๐Ÿ“ž Calling onBackdropClick handler');\r\n onBackdropClick();\r\n } else if (onClose) {\r\n console.log('โŒ Calling onClose handler');\r\n onClose();\r\n }\r\n }\r\n };\r\n\r\n return (\r\n <div \r\n style={backdropStyles} \r\n onClick={handleBackdropClick}\r\n data-onairos-backdrop=\"true\"\r\n data-mobile-browser={isMobileBrowser ? 'true' : 'false'}\r\n data-capacitor-native={isCapacitorNative ? 'true' : 'false'}\r\n >\r\n <div \r\n style={modalStyles} \r\n className={modalClassName}\r\n onClick={(e) => e.stopPropagation()}\r\n data-onairos-modal=\"true\"\r\n data-mobile-browser={isMobileBrowser ? 'true' : 'false'}\r\n data-modal-height={modalStyles.height}\r\n >\r\n <PageLayout\r\n showHeader={true}\r\n showCloseButton={true}\r\n onClose={onClose}\r\n {...pageLayoutProps}\r\n >\r\n {children}\r\n </PageLayout>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport { ModalPageLayout };\r\nexport default PageLayout; ","import React, { useEffect, useState } from 'react';\r\nimport { App } from '@capacitor/app';\r\nimport { Browser } from '@capacitor/browser';\r\nimport WelcomeScreen from './components/WelcomeScreen.jsx';\r\nimport EmailAuth from './components/EmailAuth.js';\r\nimport UniversalOnboarding from './components/UniversalOnboarding.jsx';\r\nimport PinSetup from './components/PinSetup.js';\r\nimport DataRequest from './components/DataRequest.js';\r\nimport TrainingComponent from './components/TrainingComponent.jsx';\r\nimport TrainingScreen from './components/TrainingScreen.jsx';\r\nimport LoadingScreen from './components/LoadingScreen.jsx';\r\nimport WrappedLoadingPage from './components/WrappedLoadingPage.jsx';\r\nimport { formatOnairosResponse } from './utils/responseFormatter.js';\r\nimport { logFormattedUserData } from './utils/userDataFormatter.js';\r\nimport { ModalPageLayout } from './components/ui/PageLayout.jsx';\r\nimport { isMobileApp, isMobileBrowser } from './utils/capacitorDetection.js';\r\n\r\nexport function OnairosButton({\r\n requestData, \r\n webpageName, \r\n inferenceData = null, \r\n onComplete = null, \r\n autoFetch = true, // Auto-enabled for seamless testing experience\r\n testMode = false, // Production mode by default - set to true for testing\r\n proofMode = false, \r\n textLayout = 'below', \r\n textColor = 'white',\r\n login = false,\r\n buttonType = 'pill',\r\n loginReturn = null,\r\n loginType = 'signIn',\r\n visualType = 'full',\r\n appIcon = null,\r\n enableTraining = true,\r\n formatResponse = true,\r\n responseFormat = { includeDictionary: true, includeArray: true },\r\n priorityPlatform = null, // Platform to prioritize (e.g., 'gmail', 'pinterest', 'linkedin')\r\n rawMemoriesOnly = false, // Show only LLM connections when true\r\n rawMemoriesConfig = null, // Configuration for RAW memories collection\r\n time = false // Show time frequency slider (default: false)\r\n}) {\r\n\r\n const [showOverlay, setShowOverlay] = useState(false);\r\n const [currentFlow, setCurrentFlow] = useState('welcome'); // 'welcome' | 'email' | 'onboarding' | 'pin' | 'trainingScreen' | 'dataRequest' | 'wrappedLoading'\r\n const [trainingHasStarted, setTrainingHasStarted] = useState(false);\r\n const [userData, setUserData] = useState(null);\r\n const [error, setError] = useState(null);\r\n const [oauthReturnDetected, setOauthReturnDetected] = useState(false);\r\n const [returnToDataRequestAfterOnboarding, setReturnToDataRequestAfterOnboarding] = useState(false);\r\n \r\n // Detect mobile for conditional styling (MOBILE ONLY changes)\r\n // Use a safer check that doesn't rely on window/navigator being immediately available\r\n const [isMobileDevice, setIsMobileDevice] = useState(false);\r\n \r\n useEffect(() => {\r\n // Determine mobile vs desktop based on viewport width + native runtime,\r\n // and keep it updated on resize.\r\n const computeMobile = () => {\r\n try {\r\n const hasWindow = typeof window !== 'undefined';\r\n if (!hasWindow) {\r\n setIsMobileDevice(false);\r\n return;\r\n }\r\n\r\n // Base width from current window\r\n let width = window.innerWidth || document.documentElement?.clientWidth || document.body?.clientWidth || 0;\r\n\r\n // If running inside an iframe, try to use the parent window width as well\r\n // so desktop pages embedding the SDK don't get misclassified as mobile.\r\n try {\r\n if (window.parent && window.parent !== window && window.parent.innerWidth) {\r\n width = Math.max(width, window.parent.innerWidth);\r\n }\r\n } catch (_) {\r\n // Cross-origin access can fail; ignore and fall back to local width.\r\n }\r\n\r\n const isCapNative = !!window.Capacitor?.isNativePlatform?.();\r\n\r\n // โœ… Final, explicit rule:\r\n // - Capacitor native: ALWAYS mobile\r\n // - Otherwise: viewport < 1024px (taking parent if available) โ†’ mobile; >= 1024px โ†’ desktop\r\n const detectedMobile = isCapNative || width < 1024;\r\n\r\n console.log('[Onairos SDK][Layout][MobileDetection simple]', {\r\n width,\r\n isCapNative,\r\n detectedMobile,\r\n });\r\n\r\n setIsMobileDevice(detectedMobile);\r\n } catch (e) {\r\n setIsMobileDevice(false);\r\n }\r\n };\r\n\r\n computeMobile();\r\n\r\n // Desktop resize listener to keep classification accurate when user resizes window.\r\n // This runs in all environments, but the rule above ensures iPhone/Capacitor\r\n // keep their correct classification.\r\n if (typeof window !== 'undefined') {\r\n window.addEventListener('resize', computeMobile);\r\n return () => window.removeEventListener('resize', computeMobile);\r\n }\r\n }, []);\r\n\r\n // Lock background scroll on DESKTOP while modal is open (do not touch mobile/Capacitor)\r\n useEffect(() => {\r\n if (typeof document === 'undefined') return;\r\n\r\n const body = document.body;\r\n if (!body) return;\r\n\r\n if (showOverlay && !isMobileDevice) {\r\n // Remember previous overflow so we can restore it precisely\r\n if (!body.dataset.onairosPrevOverflow) {\r\n body.dataset.onairosPrevOverflow = body.style.overflow || '';\r\n }\r\n body.style.overflow = 'hidden';\r\n } else {\r\n // Restore previous overflow when modal closes or when switching back to mobile\r\n if (body.dataset.onairosPrevOverflow !== undefined) {\r\n body.style.overflow = body.dataset.onairosPrevOverflow;\r\n delete body.dataset.onairosPrevOverflow;\r\n }\r\n }\r\n }, [showOverlay, isMobileDevice]);\r\n\r\n // ๐Ÿ” High-level layout debug for desktop vs mobile\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n const width = window.innerWidth;\r\n const isDesktop = width >= 1024 && !isMobileDevice;\r\n console.log('[Onairos SDK][Layout][OnairosButton state]', {\r\n width,\r\n isDesktop,\r\n isMobileDevice,\r\n currentFlow,\r\n showOverlay,\r\n });\r\n }, [isMobileDevice, currentFlow, showOverlay]);\r\n\r\n // ๐Ÿ” DOM-level layout debug (only on desktop web)\r\n useEffect(() => {\r\n if (typeof window === 'undefined') return;\r\n const width = window.innerWidth;\r\n const isDesktopWeb = width >= 1024 && !isMobileDevice && !window.Capacitor?.isNativePlatform?.();\r\n if (!isDesktopWeb || !showOverlay) return;\r\n\r\n // Defer to allow React layout to flush\r\n const id = window.setTimeout(() => {\r\n try {\r\n const modal = document.querySelector('.onairos-modal');\r\n const pageContent = document.querySelector('.onairos-page-content');\r\n const shell = document.querySelector('.onairos-modal-shell');\r\n\r\n const getMetrics = (el) => {\r\n if (!el) return null;\r\n const rect = el.getBoundingClientRect();\r\n const styles = window.getComputedStyle(el);\r\n return {\r\n width: rect.width,\r\n height: rect.height,\r\n maxWidth: styles.maxWidth,\r\n paddingInline: styles.paddingLeft + ' / ' + styles.paddingRight,\r\n classList: Array.from(el.classList || []),\r\n };\r\n };\r\n\r\n console.log('[Onairos SDK][Layout][DOM snapshot]', {\r\n currentFlow,\r\n viewportWidth: width,\r\n modal: getMetrics(modal),\r\n pageContent: getMetrics(pageContent),\r\n shell: getMetrics(shell),\r\n });\r\n } catch (e) {\r\n console.log('[Onairos SDK][Layout][DOM snapshot] failed', e?.message);\r\n }\r\n }, 0);\r\n\r\n return () => window.clearTimeout(id);\r\n }, [currentFlow, showOverlay, isMobileDevice]);\r\n \r\n // Logic to process return URLs (Login & Connectors)\r\n const handleDeepLink = (url) => {\r\n try {\r\n console.log('๐Ÿ” Checking URL for OAuth return:', url);\r\n \r\n // Normalize URL to check for params\r\n // For native apps, url might be 'mobiletest://oauth-callback?success=true...'\r\n // Also check specifically for Reddit's return format or other providers\r\n const hasSuccess = url.includes('success=true') || \r\n url.includes('onairos_oauth_success=true') ||\r\n (url.includes('state=') && url.includes('code='));\r\n \r\n const hasError = url.includes('error=') || url.includes('onairos_oauth_error=');\r\n const isPopup = url.includes('is_popup=true'); // Check for our custom flag\r\n \r\n // Safety Check: If we are running inside a popup or iframe (desktop), we should close ourselves\r\n // and notify the parent. This happens if the callback redirected instead of closing.\r\n // We check for window.opener, parent!=window, OR our explicit is_popup flag\r\n if ((hasSuccess || hasError) && typeof window !== 'undefined' && \r\n (window.opener || window.parent !== window || isPopup)) {\r\n console.log('๐Ÿšจ App loaded inside OAuth popup/iframe (detected via opener/parent/flag) - closing');\r\n \r\n // Extract params for storage/message\r\n let params;\r\n try {\r\n const qIdx = url.indexOf('?');\r\n if (qIdx !== -1) params = new URLSearchParams(url.substring(qIdx + 1));\r\n else params = new URL(url).searchParams;\r\n } catch(e) { params = new URLSearchParams(''); }\r\n \r\n const platform = params.get('platform') || params.get('onairos_oauth_platform');\r\n const email = params.get('email') || params.get('onairos_oauth_email');\r\n \r\n // 1. Write to LocalStorage (Same Origin as Parent) - Primary mechanism for cross-origin flow fallback\r\n if (hasSuccess && platform) {\r\n localStorage.setItem(`onairos_${platform}_success`, 'true');\r\n localStorage.setItem(`onairos_${platform}_timestamp`, Date.now().toString());\r\n if (email) localStorage.setItem(`onairos_${platform}_email`, email);\r\n }\r\n \r\n // 2. Try postMessage (only works if opener exists)\r\n try {\r\n const target = window.opener || window.parent;\r\n if (target) {\r\n target.postMessage({\r\n type: hasSuccess ? 'oauth-success' : 'oauth-error',\r\n platform: platform,\r\n email: email,\r\n error: params.get('error'),\r\n success: !!hasSuccess\r\n }, '*');\r\n }\r\n } catch (e) {}\r\n\r\n // 3. Close window\r\n window.close();\r\n // If window.close() is blocked (scripts can't close windows they didn't open),\r\n // show a message asking user to close.\r\n setTimeout(() => {\r\n document.body.innerHTML = '<div style=\"display:flex;justify-content:center;align-items:center;height:100vh;flex-direction:column;font-family:sans-serif;\"><h1>Success!</h1><p>You can close this window now.</p><button onclick=\"window.close()\" style=\"padding:10px 20px;margin-top:20px;cursor:pointer;\">Close Window</button></div>';\r\n }, 500);\r\n \r\n return; // Stop execution here\r\n }\r\n \r\n if (hasSuccess) {\r\n console.log('โœ… Deep link/OAuth return detected:', url);\r\n \r\n // Close browser if open (Capacitor) - Important for Native\r\n Browser.close().catch(() => {});\r\n\r\n // Extract params from URL\r\n let params;\r\n try {\r\n // Handle custom schemes that URL() constructor might reject if not fully standard\r\n const questionMarkIndex = url.indexOf('?');\r\n if (questionMarkIndex !== -1) {\r\n params = new URLSearchParams(url.substring(questionMarkIndex + 1));\r\n } else {\r\n params = new URL(url).searchParams;\r\n }\r\n } catch (e) {\r\n console.warn('URL parsing failed, trying fallback split:', e);\r\n params = new URLSearchParams(url.split('?')[1] || '');\r\n }\r\n\r\n let platform = params.get('platform') || params.get('onairos_oauth_platform') || 'google';\r\n let email = params.get('email') || params.get('onairos_oauth_email');\r\n \r\n // Fallback for Reddit/others that might rely on state\r\n if (!platform || platform === 'null') {\r\n const state = params.get('state');\r\n if (state) {\r\n try {\r\n // Try to decode state if it's base64\r\n const decoded = JSON.parse(atob(state));\r\n if (decoded.connectionType) platform = decoded.connectionType;\r\n if (decoded.username) email = decoded.username; // Sometimes username is email\r\n } catch (e) {\r\n console.log('State decoding failed (not base64 JSON or invalid)');\r\n }\r\n }\r\n }\r\n\r\n if (email) email = decodeURIComponent(email);\r\n \r\n console.log(`โœ… Detected return from ${platform} for ${email || 'unknown user'}`);\r\n \r\n // Set state to restore flow\r\n setOauthReturnDetected(true);\r\n \r\n // 1. SUPPORT UNIVERSAL ONBOARDING (YouTube, LinkedIn, Reddit, etc.)\r\n sessionStorage.setItem('onairos_oauth_return_success', 'true');\r\n sessionStorage.setItem('onairos_oauth_return_platform', platform);\r\n\r\n // Dispatch event to update UI immediately if component is mounted\r\n if (typeof window !== 'undefined') {\r\n window.dispatchEvent(new CustomEvent('onairos-oauth-success', { \r\n detail: { platform: platform, email: email } \r\n }));\r\n }\r\n \r\n if (platform) {\r\n localStorage.setItem(`onairos_${platform}_success`, 'true');\r\n localStorage.setItem(`onairos_${platform}_timestamp`, Date.now().toString());\r\n }\r\n\r\n // 2. SUPPORT EMAIL AUTH (Gmail)\r\n if (platform === 'google' || platform === 'gmail') {\r\n localStorage.setItem('onairos_gmail_success', 'true');\r\n localStorage.setItem('onairos_gmail_timestamp', Date.now().toString());\r\n if (email) localStorage.setItem('onairos_gmail_email', email);\r\n }\r\n \r\n // Restore session if possible (only for Login flow really, but safe to update)\r\n if (email) {\r\n // MERGE with existing userData to preserve connectedAccounts\r\n const existingUserData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\r\n const userData = {\r\n ...existingUserData, // Preserve existing data (like connectedAccounts)\r\n email: email,\r\n verified: true,\r\n onboardingComplete: false,\r\n provider: platform\r\n };\r\n console.log('๐Ÿ“ฆ Merging OAuth return with existing userData:', { existing: existingUserData.connectedAccounts, merged: userData.connectedAccounts });\r\n localStorage.setItem('onairosUser', JSON.stringify(userData));\r\n setUserData(userData);\r\n }\r\n \r\n // Open modal and go to onboarding immediately\r\n setShowOverlay(true);\r\n setCurrentFlow('onboarding');\r\n \r\n // Clean up URL if possible (on web)\r\n if (window.history && window.history.replaceState && url.startsWith('http')) {\r\n const cleanUrl = window.location.pathname;\r\n window.history.replaceState({}, '', cleanUrl);\r\n }\r\n }\r\n } catch (e) {\r\n console.error('Error handling deep link:', e);\r\n }\r\n };\r\n\r\n // Native Deep Link Listener (Runs once, stays active)\r\n useEffect(() => {\r\n let appListener = null;\r\n const setupListener = async () => {\r\n // Only run on native platforms (iOS/Android)\r\n const isNative = typeof window !== 'undefined' && window.Capacitor?.isNativePlatform?.();\r\n if (!isNative) return;\r\n\r\n let AppPlugin = App;\r\n if (!AppPlugin || !AppPlugin.addListener) {\r\n if (typeof window !== 'undefined' && window.Capacitor?.Plugins?.App) {\r\n AppPlugin = window.Capacitor.Plugins.App;\r\n }\r\n }\r\n\r\n if (!AppPlugin || !AppPlugin.addListener) {\r\n console.warn('โš ๏ธ App plugin not found for deep linking listener');\r\n return;\r\n }\r\n\r\n try {\r\n appListener = await AppPlugin.addListener('appUrlOpen', (data) => {\r\n console.log('๐Ÿ“ฑ Native deep link received:', data.url);\r\n handleDeepLink(data.url);\r\n });\r\n console.log('โœ… App deep link listener registered successfully');\r\n } catch (e) {\r\n console.warn('โš ๏ธ Failed to setup App listener:', e);\r\n }\r\n };\r\n setupListener();\r\n \r\n return () => {\r\n if (appListener) appListener.remove();\r\n };\r\n }, []);\r\n\r\n // Web/Initial Check (Respects oauthReturnDetected)\r\n useEffect(() => {\r\n if (oauthReturnDetected) return;\r\n \r\n handleDeepLink(window.location.href);\r\n \r\n const checkWindowUrl = () => handleDeepLink(window.location.href);\r\n window.addEventListener('popstate', checkWindowUrl);\r\n \r\n return () => window.removeEventListener('popstate', checkWindowUrl);\r\n }, [oauthReturnDetected]);\r\n\r\n // Check for existing user session\r\n useEffect(() => {\r\n const checkExistingSession = () => {\r\n // In test mode, always start fresh to see the full flow\r\n if (testMode) {\r\n console.log('๐Ÿงช Test mode: Starting fresh flow, clearing any cached user data');\r\n localStorage.removeItem('onairosUser');\r\n setCurrentFlow('welcome');\r\n return;\r\n }\r\n \r\n const savedUser = localStorage.getItem('onairosUser');\r\n if (savedUser) {\r\n try {\r\n const user = JSON.parse(savedUser);\r\n setUserData(user);\r\n // If user has completed onboarding and PIN setup, go directly to data request\r\n if (user.onboardingComplete && user.pinCreated) {\r\n setCurrentFlow('dataRequest');\r\n } else if (user.verified && !user.onboardingComplete) {\r\n setCurrentFlow('onboarding');\r\n } else if (user.onboardingComplete && !user.pinCreated) {\r\n setCurrentFlow('pin');\r\n }\r\n } catch (error) {\r\n console.error('Error parsing saved user data:', error);\r\n localStorage.removeItem('onairosUser');\r\n }\r\n }\r\n };\r\n\r\n checkExistingSession();\r\n }, [testMode]);\r\n\r\n // Check for OAuth return (Google login redirect back)\r\n useEffect(() => {\r\n if (oauthReturnDetected) return; // Prevent double-processing\r\n \r\n const checkOAuthReturn = () => {\r\n // Check URL params for OAuth completion\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const oauthSuccess = urlParams.get('onairos_oauth_success');\r\n const oauthPlatform = urlParams.get('onairos_oauth_platform');\r\n const oauthEmail = urlParams.get('onairos_oauth_email');\r\n\r\n // Check for generic OAuth return (any platform)\r\n if (oauthSuccess === 'true' && oauthPlatform) {\r\n setOauthReturnDetected(true);\r\n \r\n // Clean up URL\r\n const newUrl = window.location.pathname;\r\n window.history.replaceState({}, '', newUrl);\r\n \r\n if (oauthPlatform === 'gmail' && oauthEmail) {\r\n console.log('โœ… Gmail OAuth return detected in URL params');\r\n \r\n // Create user data from OAuth\r\n const authData = {\r\n email: oauthEmail,\r\n verified: true,\r\n isNewUser: true, // Assume new user for now, backend will correct this\r\n provider: 'google'\r\n };\r\n \r\n // Save to localStorage - MERGE with existing to preserve connectedAccounts\r\n const existingUserData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\r\n const userData = {\r\n ...existingUserData, // Preserve existing data (like connectedAccounts)\r\n email: oauthEmail,\r\n verified: true,\r\n onboardingComplete: false,\r\n provider: 'google'\r\n };\r\n console.log('๐Ÿ“ฆ Merging Google OAuth with existing userData:', { existing: existingUserData.connectedAccounts, merged: userData.connectedAccounts });\r\n localStorage.setItem('onairosUser', JSON.stringify(userData));\r\n setUserData(userData);\r\n \r\n // Open modal and go to onboarding\r\n setShowOverlay(true);\r\n setCurrentFlow('onboarding');\r\n \r\n // Clean up OAuth localStorage\r\n localStorage.removeItem('onairos_gmail_success');\r\n localStorage.removeItem('onairos_gmail_timestamp');\r\n localStorage.removeItem('onairos_oauth_email');\r\n localStorage.removeItem('onairos_return_url');\r\n localStorage.removeItem('onairos_oauth_context');\r\n \r\n } else {\r\n // Other platforms (Universal Onboarding connectors)\r\n console.log(`โœ… ${oauthPlatform} OAuth return detected - restoring onboarding flow`);\r\n \r\n // Ensure we have user session to show the modal correctly\r\n // (User should already be logged in if they were connecting apps)\r\n const savedUser = localStorage.getItem('onairosUser');\r\n if (savedUser) {\r\n setUserData(JSON.parse(savedUser));\r\n }\r\n \r\n // Open modal and restore flow\r\n setShowOverlay(true);\r\n setCurrentFlow('onboarding');\r\n \r\n // Pass the success signal to UniversalOnboarding via a temporary storage flag\r\n // that works even if cross-domain cleared the original context\r\n sessionStorage.setItem('onairos_oauth_return_success', 'true');\r\n sessionStorage.setItem('onairos_oauth_return_platform', oauthPlatform);\r\n }\r\n \r\n return;\r\n }\r\n\r\n // Also check localStorage for OAuth completion (fallback)\r\n const gmailSuccess = localStorage.getItem('onairos_gmail_success');\r\n const gmailTimestamp = localStorage.getItem('onairos_gmail_timestamp');\r\n const gmailEmail = localStorage.getItem('onairos_gmail_email') || localStorage.getItem('onairos_oauth_email');\r\n\r\n if (gmailSuccess === 'true' && gmailTimestamp && gmailEmail) {\r\n const now = Date.now();\r\n const timestamp = parseInt(gmailTimestamp, 10);\r\n \r\n // Only process if timestamp is recent (within last 60 seconds)\r\n if (now - timestamp < 60000) {\r\n console.log('โœ… Gmail OAuth return detected in localStorage');\r\n setOauthReturnDetected(true);\r\n \r\n // Create user data from OAuth - MERGE with existing to preserve connectedAccounts\r\n const existingUserData = JSON.parse(localStorage.getItem('onairosUser') || '{}');\r\n const userData = {\r\n ...existingUserData, // Preserve existing data (like connectedAccounts)\r\n email: gmailEmail,\r\n verified: true,\r\n onboardingComplete: false,\r\n provider: 'google'\r\n };\r\n console.log('๐Ÿ“ฆ Merging Gmail OAuth with existing userData:', { existing: existingUserData.connectedAccounts, merged: userData.connectedAccounts });\r\n localStorage.setItem('onairosUser', JSON.stringify(userData));\r\n setUserData(userData);\r\n \r\n // Open modal and go to onboarding\r\n setShowOverlay(true);\r\n setCurrentFlow('onboarding');\r\n \r\n // Clean up OAuth localStorage\r\n localStorage.removeItem('onairos_gmail_success');\r\n localStorage.removeItem('onairos_gmail_timestamp');\r\n localStorage.removeItem('onairos_gmail_email');\r\n localStorage.removeItem('onairos_oauth_email');\r\n localStorage.removeItem('onairos_return_url');\r\n localStorage.removeItem('onairos_oauth_context');\r\n }\r\n }\r\n };\r\n\r\n checkOAuthReturn();\r\n }, [oauthReturnDetected]);\r\n\r\n const openTerminal = async () => {\r\n try {\r\n console.log('๐Ÿ”ฅ openTerminal called - resetting flow');\r\n console.log('๐Ÿ”ฅ testMode prop:', testMode);\r\n console.log('๐Ÿ”ฅ window.onairosApiKey:', window.onairosApiKey);\r\n // ALWAYS reset flow on open to start fresh every time\r\n setCurrentFlow('welcome');\r\n setUserData(null);\r\n try { localStorage.removeItem('onairosUser'); } catch {}\r\n setShowOverlay(true);\r\n } catch (error) {\r\n console.error('Error in openTerminal:', error);\r\n }\r\n };\r\n\r\n const handleCloseOverlay = () => {\r\n setShowOverlay(false);\r\n setError(null);\r\n // Reset flow and session so next open starts fresh\r\n setCurrentFlow('welcome');\r\n try { localStorage.removeItem('onairosUser'); } catch {}\r\n setUserData(null);\r\n };\r\n\r\n // Handle clicks on the backdrop to close modal\r\n const handleBackdropClick = (e) => {\r\n if (e.target === e.currentTarget) {\r\n handleCloseOverlay();\r\n }\r\n };\r\n\r\n const handleWelcomeContinue = () => {\r\n console.log('๐Ÿ”ฅ Welcome screen continue clicked');\r\n setCurrentFlow('email');\r\n };\r\n\r\n const handleEmailAuthSuccess = (authData) => {\r\n console.log('๐Ÿ”ฅ Email auth successful:', authData);\r\n console.log('๐Ÿ”ง User State:', {\r\n isNewUser: authData.isNewUser,\r\n userState: authData.userState,\r\n flowType: authData.flowType,\r\n existingUser: authData.existingUser,\r\n hasAccountInfo: !!authData.accountInfo,\r\n accountStatus: authData.accountStatus // NEW: Log accountStatus\r\n });\r\n\r\n // Save identity-bearing JWT immediately (email/id/userId/sub)\r\n try {\r\n const candidate = authData.jwtToken || authData.token || authData.accessToken;\r\n if (candidate) {\r\n const base64 = candidate.split('.')[1];\r\n if (base64) {\r\n const payload = JSON.parse(decodeURIComponent(atob(base64).split('').map(c => '%'+('00'+c.charCodeAt(0).toString(16)).slice(-2)).join('')));\r\n if (payload && (payload.email || payload.id || payload.userId || payload.sub)) {\r\n try { localStorage.setItem('onairos_user_token', candidate); } catch {}\r\n console.log('โœ… [OnairosButton] Identity JWT saved from email auth');\r\n } else {\r\n console.warn('โš ๏ธ [OnairosButton] Email auth returned minimal token (no id/email)');\r\n }\r\n }\r\n }\r\n } catch (e) {\r\n console.warn('โš ๏ธ [OnairosButton] Failed to parse/save email auth token');\r\n }\r\n \r\n // NEW: Use accountStatus if available (more reliable than legacy fields)\r\n const accountStatus = authData.accountStatus;\r\n let isNewUser;\r\n \r\n if (accountStatus) {\r\n // Use the new accountStatus.exists field as the source of truth\r\n isNewUser = !accountStatus.exists;\r\n console.log('โœ… Using accountStatus.exists for flow determination:', {\r\n accountExists: accountStatus.exists,\r\n hasTrainedModel: accountStatus.hasTrainedModel,\r\n hasPersonalityTraits: accountStatus.hasPersonalityTraits,\r\n connectedPlatforms: accountStatus.connectedPlatforms,\r\n needsDataConnection: accountStatus.needsDataConnection,\r\n needsTraining: accountStatus.needsTraining,\r\n canUseInference: accountStatus.canUseInference\r\n });\r\n } else {\r\n // Fallback to legacy field checking if accountStatus not available\r\n isNewUser = authData.isNewUser === true || \r\n authData.existingUser === false || \r\n authData.flowType === 'onboarding' || \r\n authData.userState === 'new' ||\r\n !authData.accountInfo;\r\n console.log('โš ๏ธ Using legacy fields for flow determination (accountStatus not available)');\r\n }\r\n \r\n console.log('๐Ÿ” Flow determination:', {\r\n finalDecision: isNewUser ? 'NEW USER โ†’ onboarding (data connectors)' : 'EXISTING USER โ†’ dataRequest (data permissions)',\r\n reasoning: {\r\n usingAccountStatus: !!accountStatus,\r\n accountExists: accountStatus?.exists,\r\n isNewUser: authData.isNewUser,\r\n existingUserFalse: authData.existingUser === false,\r\n flowTypeOnboarding: authData.flowType === 'onboarding',\r\n noAccountInfo: !authData.accountInfo\r\n }\r\n });\r\n \r\n const newUserData = {\r\n ...authData,\r\n verified: true,\r\n onboardingComplete: !isNewUser, // New users need onboarding, returning users have completed it\r\n pinCreated: !isNewUser // Assume returning users have PIN, new users need to create it\r\n };\r\n\r\n // If backend provides connected platforms for existing users, carry them into connectedAccounts\r\n // so DataRequest/Onboarding can reflect what is already connected.\r\n const normalizePlatformName = (p) => {\r\n const key = String(p || '').trim().toLowerCase();\r\n const map = {\r\n instagram: 'Instagram',\r\n youtube: 'YouTube',\r\n linkedin: 'LinkedIn',\r\n reddit: 'Reddit',\r\n pinterest: 'Pinterest',\r\n github: 'GitHub',\r\n gmail: 'Gmail',\r\n twitter: 'Twitter',\r\n x: 'Twitter',\r\n chatgpt: 'ChatGPT',\r\n claude: 'Claude',\r\n gemini: 'Gemini',\r\n grok: 'Grok',\r\n };\r\n return map[key] || (key ? key.charAt(0).toUpperCase() + key.slice(1) : '');\r\n };\r\n if (!isNewUser) {\r\n const fromAccountStatus = Array.isArray(accountStatus?.connectedPlatforms)\r\n ? accountStatus.connectedPlatforms\r\n : [];\r\n const normalized = fromAccountStatus.map(normalizePlatformName).filter(Boolean);\r\n if (normalized.length > 0) {\r\n newUserData.connectedAccounts = normalized;\r\n }\r\n }\r\n \r\n // Ensure token is stored in userData and localStorage\r\n const emailToken = authData.token || authData.jwtToken || authData.accessToken;\r\n if (emailToken) {\r\n newUserData.token = emailToken;\r\n try {\r\n localStorage.setItem('onairos_user_token', emailToken);\r\n console.log('โœ… Token from email verification saved to localStorage');\r\n } catch (e) {\r\n console.warn('โš ๏ธ Could not save token to localStorage:', e);\r\n }\r\n }\r\n \r\n setUserData(newUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(newUserData));\r\n \r\n // Flow decision logic:\r\n // - New users: go to UniversalOnboarding (connectors)\r\n // - Existing users: go straight to DataRequest (data permissions)\r\n if (isNewUser) {\r\n console.log('๐Ÿš€ Auth successful (new user) โ†’ Starting onboarding flow (data connectors page)');\r\n setCurrentFlow('onboarding');\r\n } else {\r\n console.log('๐Ÿš€ Auth successful (existing user) โ†’ Going straight to DataRequest (data permissions)');\r\n setCurrentFlow('dataRequest');\r\n }\r\n };\r\n\r\n const handleOnboardingComplete = (onboardingData) => {\r\n console.log('๐ŸŽฏ Onboarding completed:', onboardingData);\r\n console.log('๐Ÿ” Connected accounts from onboarding:', onboardingData.connectedAccounts);\r\n const updatedUserData = {\r\n ...userData,\r\n onboardingComplete: true,\r\n connectedAccounts: onboardingData.connectedAccounts || []\r\n };\r\n console.log('๐Ÿ’พ Saving userData with connectedAccounts:', updatedUserData.connectedAccounts);\r\n setUserData(updatedUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(updatedUserData));\r\n if (returnToDataRequestAfterOnboarding) {\r\n setReturnToDataRequestAfterOnboarding(false);\r\n setCurrentFlow('dataRequest');\r\n } else {\r\n setCurrentFlow('pin');\r\n }\r\n };\r\n\r\n const handlePinSetupComplete = async (pinData) => {\r\n console.log('PIN setup completed:', pinData);\r\n const updatedUserData = {\r\n ...userData,\r\n ...pinData,\r\n pinCreated: true\r\n };\r\n setUserData(updatedUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(updatedUserData));\r\n \r\n // Check if this is a wrapped app\r\n const isWrappedApp = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n \r\n if (isWrappedApp) {\r\n // Wrapped apps skip training screen - go directly to data request\r\n console.log('๐ŸŽ Wrapped app - skipping training screen, going to data request');\r\n setCurrentFlow('dataRequest');\r\n } else {\r\n // Non-wrapped apps show training screen BEFORE data request\r\n console.log('๐ŸŽ“ Non-wrapped app - showing training screen');\r\n // Reset training start watchdog state\r\n setTrainingHasStarted(false);\r\n setCurrentFlow('trainingScreen');\r\n }\r\n };\r\n\r\n // Non-wrapped ONLY: if training does not START within 30s, move forward to DataRequest anyway.\r\n // Wrapped apps must NOT do this.\r\n useEffect(() => {\r\n const isWrappedApp = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n if (isWrappedApp) return;\r\n\r\n if (currentFlow !== 'trainingScreen') return;\r\n if (trainingHasStarted) return;\r\n\r\n const timeoutId = setTimeout(() => {\r\n // Re-check conditions at fire time (effect cleanup should handle most cases).\r\n const stillWrapped = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n if (stillWrapped) return;\r\n if (currentFlow === 'trainingScreen' && !trainingHasStarted) {\r\n console.warn('โฑ๏ธ Training did not start within 30s (non-wrapped). Continuing to DataRequest.');\r\n setCurrentFlow('dataRequest');\r\n }\r\n }, 30000);\r\n\r\n return () => clearTimeout(timeoutId);\r\n }, [currentFlow, trainingHasStarted, webpageName]);\r\n\r\n const handleLoadingComplete = () => {\r\n setCurrentFlow('dataRequest');\r\n };\r\n\r\n const handleTrainingComplete = (trainingResult) => {\r\n console.log('๐ŸŽ“ Training completed:', trainingResult);\r\n const updatedUserData = {\r\n ...userData,\r\n trainingCompleted: true,\r\n ...trainingResult\r\n };\r\n setUserData(updatedUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(updatedUserData));\r\n \r\n // Move to data request after training\r\n setCurrentFlow('dataRequest');\r\n };\r\n\r\n const handleTrainingScreenComplete = (trainingResult) => {\r\n console.log('๐ŸŽ“ Training screen completed:', trainingResult);\r\n const updatedUserData = {\r\n ...userData,\r\n trainingCompleted: true,\r\n ...trainingResult\r\n };\r\n setUserData(updatedUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(updatedUserData));\r\n \r\n // Move to data request after training screen\r\n setCurrentFlow('dataRequest');\r\n };\r\n\r\n const handleDataRequestComplete = async (requestResult) => {\r\n console.log('๐Ÿ”ฅ OnairosButton: Data request completed:', requestResult);\r\n \r\n // Check if this is a wrapped app\r\n const isWrappedApp = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n \r\n // For non-wrapped apps, training and inference already happened in TrainingScreen\r\n // No need to run it again here\r\n if (!isWrappedApp && requestResult.approved?.length > 0) {\r\n console.log('โœ… Non-wrapped app: Training and inference already completed in TrainingScreen');\r\n console.log('๐Ÿ“‹ Data approval recorded:', requestResult.approved);\r\n }\r\n \r\n // Update user data with request result\r\n const updatedUserData = {\r\n ...userData,\r\n lastDataRequest: requestResult\r\n };\r\n setUserData(updatedUserData);\r\n localStorage.setItem('onairosUser', JSON.stringify(updatedUserData));\r\n\r\n // Handle data fetching if autoFetch is enabled\r\n // For non-wrapped apps, training already happened in TrainingScreen, so skip this\r\n let finalResult = requestResult;\r\n \r\n if (autoFetch && requestResult.approved?.length > 0 && isWrappedApp) {\r\n console.log('๐Ÿš€ Auto-fetching data from Onairos API for wrapped app...');\r\n \r\n try {\r\n // 1. Get the API URL from the backend\r\n const urlResponse = await fetch('https://api2.onairos.uk/getAPIurlMobile', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify({\r\n Info: {\r\n appId: webpageName,\r\n account: userData?.email || userData?.username,\r\n confirmations: requestResult.approved.map(id => ({ data: id === 'personality' ? 'Large' : id === 'basic' ? 'Basic' : id })),\r\n EncryptedUserPin: userData?.EncryptedUserPin || 'pending_pin_integration',\r\n storage: 's3',\r\n proofMode: proofMode\r\n }\r\n })\r\n });\r\n\r\n const urlData = await urlResponse.json();\r\n console.log('๐Ÿ”— API URL received:', urlData.apiUrl);\r\n console.log('๐ŸŽฏ webpageName sent as appId:', webpageName);\r\n\r\n if (urlData.apiUrl && urlData.token) {\r\n // Only show wrapped loading page if app name contains \"wrapped\"\r\n const isWrappedApp = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n console.log('๐ŸŽ Is wrapped app?', isWrappedApp, '(checking:', webpageName, ')');\r\n if (isWrappedApp) {\r\n setCurrentFlow('wrappedLoading');\r\n console.log('๐Ÿ“Š Showing wrapped loading screen for wrapped app');\r\n } else {\r\n console.log('๐Ÿ“Š Skipping loading screen - not a wrapped app');\r\n }\r\n \r\n // Emit custom event for host app\r\n if (typeof window !== 'undefined') {\r\n const eventDetail = { apiUrl: urlData.apiUrl, approved: requestResult.approved };\r\n window.dispatchEvent(new CustomEvent('onairos-api-call-start', { detail: eventDetail }));\r\n console.log('๐Ÿ“ก Emitted onairos-api-call-start event');\r\n }\r\n \r\n // 2. Fetch the actual data\r\n // IMPORTANT: This endpoint can take 1-3 minutes as it runs Python LLM scripts\r\n // We MUST wait for the actual response before proceeding\r\n // Always use POST for consistency and to support body data\r\n // traits-only endpoint requires POST\r\n const method = 'POST';\r\n \r\n let fetchUrl = urlData.apiUrl;\r\n let fetchBody = {\r\n email: userData?.email,\r\n includeLlmData: requestResult.approved.includes('rawMemories')\r\n };\r\n\r\n // Override for non-wrapped apps (Regular SDK training) to use Training API\r\n if (!isWrappedApp) {\r\n fetchUrl = 'https://api2.onairos.uk/mobile-training/clean';\r\n \r\n // Construct training body\r\n const connected = [];\r\n if (userData?.connectedAccounts) {\r\n if (Array.isArray(userData.connectedAccounts)) {\r\n connected.push(...userData.connectedAccounts);\r\n } else if (typeof userData.connectedAccounts === 'object') {\r\n connected.push(...Object.keys(userData.connectedAccounts).filter(k => userData.connectedAccounts[k]));\r\n }\r\n }\r\n \r\n fetchBody = {\r\n Info: {\r\n username: userData?.email || userData?.username,\r\n connectedPlatforms: connected\r\n }\r\n };\r\n \r\n console.log('๐Ÿš€ Switching to Training API for non-wrapped app:', fetchUrl);\r\n } else {\r\n console.log('๐ŸŽ WRAPPED APP DETECTED - Using traits-only endpoint from backend:', fetchUrl);\r\n console.log('๐ŸŽ This should call the wrapped dashboard generation');\r\n\r\n // Wrapped freshness: ALWAYS request a fresh-per-request variant (even if the same YouTube account is reused).\r\n // This avoids \"cached-looking\" dashboards while keeping the core metrics stable.\r\n fetchBody = {\r\n ...fetchBody,\r\n forceFresh: true,\r\n cacheBust: Date.now(),\r\n };\r\n try {\r\n const currentEmail = userData?.email;\r\n if (currentEmail) localStorage.setItem('onairos_last_wrapped_email', currentEmail);\r\n } catch {}\r\n console.log('๐Ÿงผ Wrapped forceFresh enabled (always for wrapped):', { email: userData?.email });\r\n }\r\n \r\n console.log(`๐Ÿ“ก Fetching/Training data from ${fetchUrl} (${method})...`);\r\n console.log(`๐Ÿ”‘ Using token: ${urlData.token ? urlData.token.substring(0, 20) + '...' : 'NO TOKEN'}`);\r\n try {\r\n console.log('๐Ÿ“ฆ Wrapped fetch request body:', fetchBody);\r\n } catch {}\r\n console.log(`โณ Waiting for backend response - this may take 1-3 minutes for LLM processing...`);\r\n \r\n let dataResponse;\r\n let apiResponse;\r\n let fetchCompleted = false;\r\n let fetchError = null;\r\n \r\n try {\r\n // CRITICAL: Wait for the actual fetch response - don't proceed until we get data or a real error\r\n // The backend Python script needs time to generate the wrapped dashboard\r\n console.log(`๐Ÿ”„ Starting fetch request - will wait for complete response...`);\r\n \r\n // Create abort controller with 10-minute timeout for LLM-heavy endpoints\r\n // This prevents the BROWSER from timing out, even if the server might\r\n // Note: Gateway/load balancer may timeout earlier (typically 60s), which is expected\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), 600000); // 10 minutes\r\n\r\n try {\r\n dataResponse = await fetch(fetchUrl, {\r\n method: method,\r\n headers: {\r\n 'Authorization': `Bearer ${urlData.token}`,\r\n 'Content-Type': 'application/json'\r\n },\r\n // Prevent browser/proxy caching for wrapped dashboards\r\n cache: 'no-store',\r\n // Only send body for POST\r\n body: method === 'POST' ? JSON.stringify(fetchBody) : undefined,\r\n signal: controller.signal\r\n });\r\n } finally {\r\n clearTimeout(timeoutId);\r\n }\r\n\r\n console.log(`๐Ÿ“ฅ Response status: ${dataResponse.status} ${dataResponse.statusText}`);\r\n console.log(`๐Ÿ“ฅ Response headers:`, Object.fromEntries(dataResponse.headers.entries()));\r\n\r\n // Check for 504 Gateway Timeout - implies backend is still working\r\n if (dataResponse.status === 504) {\r\n console.warn('โฑ๏ธ 504 Gateway Timeout received - Backend is likely still processing');\r\n throw new Error('Gateway Timeout (504) - Backend processing continued');\r\n }\r\n\r\n // CRITICAL: Check if response is ok before parsing JSON\r\n if (!dataResponse.ok) {\r\n throw new Error(`HTTP ${dataResponse.status}: ${dataResponse.statusText}`);\r\n }\r\n\r\n // CRITICAL: Wait for JSON parsing to complete\r\n apiResponse = await dataResponse.json();\r\n \r\n console.log('๐Ÿ” Parsed API response:', {\r\n isWrappedApp,\r\n hasStatus: !!apiResponse.status,\r\n status: apiResponse.status,\r\n hasSlides: !!apiResponse.slides,\r\n responseKeys: Object.keys(apiResponse)\r\n });\r\n \r\n // Check if dashboard is still being generated (wrapped app only)\r\n if (isWrappedApp && apiResponse.status === 'processing') {\r\n console.log('โณ Dashboard is being generated - starting polling...');\r\n const pollInterval = (apiResponse.poll_interval_seconds || 3) * 1000;\r\n const maxPolls = 60; // Max 3 minutes of polling\r\n let pollCount = 0;\r\n \r\n while (pollCount < maxPolls) {\r\n pollCount++;\r\n console.log(`๐Ÿ”„ Polling attempt ${pollCount}/${maxPolls}...`);\r\n \r\n // Wait before next poll\r\n await new Promise(resolve => setTimeout(resolve, pollInterval));\r\n \r\n try {\r\n const pollResponse = await fetch(fetchUrl, {\r\n method: method,\r\n headers: {\r\n 'Authorization': `Bearer ${urlData.token}`,\r\n 'Content-Type': 'application/json'\r\n },\r\n cache: 'no-store',\r\n body: method === 'POST' ? JSON.stringify(fetchBody) : undefined\r\n });\r\n \r\n if (pollResponse.ok) {\r\n const pollData = await pollResponse.json();\r\n \r\n // Check if we have the actual dashboard now\r\n if (pollData.slides) {\r\n console.log('โœ… Dashboard ready! Received slides.');\r\n apiResponse = pollData;\r\n break;\r\n } else if (pollData.status !== 'processing') {\r\n console.warn('โš ๏ธ Unexpected response during polling:', pollData);\r\n apiResponse = pollData;\r\n break;\r\n }\r\n \r\n console.log('โณ Still processing...');\r\n } else {\r\n console.warn(`โš ๏ธ Poll failed with status ${pollResponse.status}`);\r\n }\r\n } catch (pollErr) {\r\n console.warn('โš ๏ธ Poll request failed:', pollErr.message);\r\n }\r\n }\r\n \r\n if (!apiResponse.slides && pollCount >= maxPolls) {\r\n console.error('โŒ Polling timed out after max attempts');\r\n throw new Error('Dashboard generation timed out');\r\n }\r\n }\r\n \r\n // Mark fetch as completed successfully\r\n fetchCompleted = true;\r\n \r\n console.log('โœ… API Response received and parsed successfully');\r\n console.log('๐Ÿ“ฆ Has slides?', !!apiResponse.slides);\r\n if (apiResponse.slides) {\r\n console.log('๐Ÿ“Š Slides keys:', Object.keys(apiResponse.slides));\r\n }\r\n \r\n } catch (fetchErr) {\r\n // Mark that we encountered an error during fetch\r\n fetchError = fetchErr;\r\n fetchCompleted = false;\r\n \r\n console.error('๐Ÿšจ FETCH ERROR:', fetchErr);\r\n console.error('๐Ÿšจ Error name:', fetchErr.name);\r\n console.error('๐Ÿšจ Error message:', fetchErr.message);\r\n \r\n // Check if it's a timeout error (504 Gateway Timeout)\r\n if (fetchErr.message?.includes('504') || fetchErr.message?.includes('Gateway Timeout')) {\r\n console.error('โฑ๏ธโฑ๏ธโฑ๏ธ GATEWAY TIMEOUT (504) - Backend is still processing');\r\n console.error('โฑ๏ธ This means the backend Python LLM script is still running');\r\n console.error('โฑ๏ธ DO NOT fall back to mocks yet - backend is generating data');\r\n // Don't set apiResponse to null yet - we want to retry or wait\r\n apiResponse = null;\r\n \r\n // Flag this as a timeout specifically so the app knows to wait/retry\r\n requestResult.isTimeout = true;\r\n }\r\n // If it's a CORS error, the backend is returning data but browser blocks it\r\n else if (fetchErr.message?.includes('CORS') || fetchErr.message?.includes('Failed to fetch')) {\r\n console.error('๐Ÿšจ๐Ÿšจ๐Ÿšจ CORS BLOCKING RESPONSE - Backend generated data but browser cannot read it');\r\n console.error('๐Ÿšจ This usually means a 504/502 timeout from load balancer stripping headers');\r\n console.error('๐Ÿšจ Backend successfully generated dashboard (see server logs)');\r\n \r\n // Even though fetch failed, we still have the token and URL\r\n // Set apiResponse to null but keep token and apiUrl for retry\r\n apiResponse = null;\r\n \r\n // Treat CORS errors on this endpoint as timeouts/processing\r\n // The backend likely finished but the LB cut the connection\r\n requestResult.isTimeout = true;\r\n } else {\r\n // For other errors, still set to null but log the error\r\n console.error('โŒ Fetch failed with error:', fetchErr);\r\n apiResponse = null;\r\n }\r\n }\r\n \r\n // CRITICAL: Log fetch completion status\r\n if (fetchCompleted) {\r\n console.log('โœ… Fetch completed - data ready');\r\n } else if (requestResult.isTimeout) {\r\n console.log('โฑ๏ธ Request timed out - passing timeout flag to app');\r\n } else if (fetchError) {\r\n console.error('โŒ Fetch failed:', fetchError.message);\r\n }\r\n\r\n // Merge into result - include token and apiUrl even if fetch failed\r\n finalResult = {\r\n ...requestResult,\r\n apiResponse: apiResponse, // Raw response (null if CORS blocked)\r\n token: urlData.token, // Token used - ALWAYS include this\r\n apiUrl: urlData.apiUrl // URL used - ALWAYS include this\r\n };\r\n \r\n console.log('๐Ÿ”— Final result ready:', {\r\n hasApiResponse: !!finalResult.apiResponse,\r\n hasSlides: !!finalResult.apiResponse?.slides,\r\n hasToken: !!finalResult.token\r\n });\r\n \r\n // Add to updated user data - include token even if apiResponse is null\r\n updatedUserData.apiResponse = apiResponse;\r\n if (urlData.token) {\r\n updatedUserData.token = urlData.token;\r\n // Also store in localStorage for persistence\r\n try {\r\n localStorage.setItem('onairos_user_token', urlData.token);\r\n } catch (e) {\r\n console.warn('โš ๏ธ Could not store token in localStorage:', e);\r\n }\r\n }\r\n setUserData(updatedUserData);\r\n } else {\r\n console.warn('โš ๏ธ Failed to get API URL:', urlData);\r\n }\r\n } catch (fetchError) {\r\n console.error('โŒ Error auto-fetching data:', fetchError);\r\n \r\n // Check if it's a timeout/abort error\r\n if (fetchError.name === 'AbortError' || fetchError.message?.includes('timeout')) {\r\n console.error('โฑ๏ธ Request timed out - backend took longer than 2 minutes');\r\n }\r\n // Check if it's a CORS error\r\n else if (fetchError.message?.includes('CORS') || \r\n fetchError.message?.includes('Failed to fetch') ||\r\n fetchError.name === 'TypeError') {\r\n console.error('๐Ÿšจ CORS ERROR DETECTED');\r\n console.error('๐Ÿšจ Backend needs to allow CORS for:', window.location.origin);\r\n }\r\n \r\n // Continue with what we have - don't block the flow\r\n // The app can still proceed without apiResponse\r\n }\r\n }\r\n\r\n // Format response if requested and API response is present\r\n let formattedResult = finalResult;\r\n if (formatResponse && finalResult?.apiResponse) {\r\n try {\r\n formattedResult = {\r\n ...requestResult,\r\n apiResponse: formatOnairosResponse(requestResult.apiResponse, responseFormat)\r\n };\r\n console.log('๐Ÿ”ฅ Response formatted with dictionary:', formattedResult.apiResponse?.personalityDict || 'No personality data');\r\n } catch (error) {\r\n console.warn('๐Ÿ”ฅ Error formatting response:', error);\r\n // Continue with original result if formatting fails\r\n }\r\n }\r\n\r\n // Ensure token is included from userData if not already in finalResult\r\n if (!finalResult.token && updatedUserData.token) {\r\n finalResult.token = updatedUserData.token;\r\n console.log('๐Ÿ”‘ Added token from userData to finalResult');\r\n }\r\n \r\n // Also check localStorage as fallback\r\n if (!finalResult.token) {\r\n try {\r\n const storedToken = localStorage.getItem('onairos_user_token');\r\n if (storedToken) {\r\n finalResult.token = storedToken;\r\n console.log('๐Ÿ”‘ Added token from localStorage to finalResult');\r\n }\r\n } catch (e) {\r\n console.warn('โš ๏ธ Could not read token from localStorage:', e);\r\n }\r\n }\r\n \r\n // Add user data to the result for comprehensive formatting\r\n const completeResult = {\r\n ...formattedResult,\r\n token: finalResult.token || formattedResult.token || updatedUserData.token, // Ensure token is at root level\r\n userData: updatedUserData\r\n };\r\n\r\n // Enhanced user data formatting for better display\r\n let enhancedResult = completeResult;\r\n try {\r\n // Log formatted user data for better readability\r\n enhancedResult = logFormattedUserData(completeResult);\r\n } catch (formatError) {\r\n console.warn('โš ๏ธ Error formatting user data for display:', formatError);\r\n // Continue with unformatted result to ensure app doesn't break\r\n }\r\n \r\n // Ensure token is still present after formatting\r\n if (!enhancedResult.token && completeResult.token) {\r\n enhancedResult.token = completeResult.token;\r\n }\r\n if (!enhancedResult.token && updatedUserData.token) {\r\n enhancedResult.token = updatedUserData.token;\r\n }\r\n\r\n // Call onComplete callback if provided\r\n // For non-wrapped apps, onComplete was already called from TrainingScreen\r\n // So we only call it here for wrapped apps OR if training screen was skipped\r\n // webpageName is already in scope from the component props\r\n const isWrappedAppForCallback = webpageName && webpageName.toLowerCase().includes('wrapped');\r\n \r\n if (onComplete && isWrappedAppForCallback) {\r\n try {\r\n console.log('โœ… Calling onComplete for wrapped app with data');\r\n onComplete(enhancedResult);\r\n } catch (error) {\r\n console.error('โŒ Error in onComplete callback:', error);\r\n }\r\n } else if (onComplete && !isWrappedAppForCallback) {\r\n console.log('โญ๏ธ Skipping onComplete for non-wrapped app (already called from TrainingScreen)');\r\n } else {\r\n console.log('๐Ÿ”ฅ No onComplete callback provided');\r\n }\r\n\r\n // WRAPPED APPS: Set up listener for app to signal when dashboard is ready\r\n // This is event-driven - overlay stays until dashboard signals it's ready\r\n // isWrappedApp already declared above\r\n \r\n if (isWrappedApp) {\r\n console.log('๐ŸŽ Wrapped app - waiting for dashboard ready signal');\r\n console.log('๐Ÿ”Š Setting up onairos-dashboard-ready event listener');\r\n \r\n // Listen for custom event from the wrapped app indicating dashboard is ready\r\n const handleDashboardReady = (event) => {\r\n console.log('โœ…โœ…โœ… Dashboard ready signal received - closing SDK overlay');\r\n console.log('๐Ÿ“Š Event details:', event);\r\n handleCloseOverlay();\r\n window.removeEventListener('onairos-dashboard-ready', handleDashboardReady);\r\n };\r\n \r\n window.addEventListener('onairos-dashboard-ready', handleDashboardReady);\r\n console.log('๐Ÿ‘‚ Event listener attached, waiting for signal...');\r\n \r\n // Keep overlay open indefinitely until we get the ready signal\r\n // No fallback timeout - if the app doesn't signal, the overlay stays\r\n // This ensures we never show a flash of the portal page\r\n } else {\r\n // For non-wrapped apps, just close the modal - training already happened in TrainingScreen\r\n console.log('โœ… Non-wrapped app: Training complete, closing overlay');\r\n handleCloseOverlay();\r\n }\r\n };\r\n\r\n const getFlowTitle = () => {\r\n switch (currentFlow) {\r\n case 'welcome':\r\n return ''; // WelcomeScreen handles its own titles\r\n case 'email':\r\n return ''; // EmailAuth handles its own titles\r\n case 'onboarding':\r\n return 'Connect Your Data';\r\n case 'pin':\r\n return 'Secure Your Account';\r\n case 'training':\r\n return 'Training Your Model';\r\n case 'trainingScreen':\r\n return 'Training Your Model';\r\n case 'dataRequest':\r\n return 'Data Request';\r\n default:\r\n return '';\r\n }\r\n };\r\n\r\n const getFlowSubtitle = () => {\r\n switch (currentFlow) {\r\n case 'welcome':\r\n return ''; // WelcomeScreen handles its own subtitles\r\n case 'email':\r\n return ''; // EmailAuth handles its own subtitles\r\n case 'onboarding':\r\n return 'Choose which accounts to connect for a personalized experience';\r\n case 'pin':\r\n return 'Create a secure PIN to protect your data';\r\n case 'training':\r\n return 'Building your personalized insights';\r\n case 'trainingScreen':\r\n return 'Building your personalized insights';\r\n case 'dataRequest':\r\n return `Select the data you want to share with ${webpageName}`;\r\n default:\r\n return '';\r\n }\r\n };\r\n\r\n const getFlowIcon = () => {\r\n switch (currentFlow) {\r\n case 'welcome':\r\n return ''; // WelcomeScreen handles its own layout\r\n case 'email':\r\n return ''; // EmailAuth handles its own layout\r\n case 'onboarding':\r\n return '๐Ÿ”—';\r\n case 'pin':\r\n return '๐Ÿ”’';\r\n case 'training':\r\n return 'โšก';\r\n case 'trainingScreen':\r\n return 'โšก';\r\n case 'dataRequest':\r\n return '๐Ÿ“Š';\r\n default:\r\n return '';\r\n }\r\n };\r\n\r\n const renderContent = () => {\r\n const commonProps = {\r\n isMobile: isMobileDevice,\r\n testMode: testMode\r\n };\r\n\r\n switch (currentFlow) {\r\n case 'welcome':\r\n return (\r\n <WelcomeScreen \r\n {...commonProps}\r\n onContinue={handleWelcomeContinue}\r\n onClose={handleCloseOverlay}\r\n webpageName={webpageName}\r\n appIcon={appIcon}\r\n />\r\n );\r\n case 'email':\r\n return (\r\n <div className={isMobileDevice ? \"flex-1 min-h-0 flex flex-col\" : \"flex-1 min-h-0 flex flex-col\"}>\r\n <EmailAuth \r\n {...commonProps}\r\n onSuccess={handleEmailAuthSuccess}\r\n />\r\n </div>\r\n );\r\n case 'onboarding':\r\n return (\r\n <UniversalOnboarding \r\n {...commonProps}\r\n onComplete={handleOnboardingComplete}\r\n onBack={() => {\r\n if (returnToDataRequestAfterOnboarding) {\r\n setReturnToDataRequestAfterOnboarding(false);\r\n setCurrentFlow('dataRequest');\r\n } else {\r\n setCurrentFlow('email');\r\n }\r\n }}\r\n appIcon={appIcon || \"https://onairos.sirv.com/Images/OnairosBlack.png\"}\r\n appName={webpageName}\r\n username={userData?.email || userData?.username}\r\n priorityPlatform={priorityPlatform}\r\n rawMemoriesOnly={rawMemoriesOnly}\r\n rawMemoriesConfig={rawMemoriesConfig}\r\n />\r\n );\r\n case 'pin':\r\n return (\r\n <div className={isMobileDevice ? \"flex-1 min-h-0\" : \"\"}>\r\n <PinSetup \r\n onComplete={handlePinSetupComplete}\r\n onBack={() => setCurrentFlow('onboarding')}\r\n userEmail={userData?.email}\r\n />\r\n </div>\r\n );\r\n case 'training':\r\n return (\r\n <TrainingComponent \r\n onComplete={handleTrainingComplete}\r\n userEmail={userData?.email}\r\n appName={webpageName}\r\n connectedAccounts={userData?.connectedAccounts || []}\r\n testMode={testMode}\r\n />\r\n );\r\n case 'trainingScreen':\r\n console.log('๐ŸŽ“ Rendering TrainingScreen with userData:', {\r\n hasUserData: !!userData,\r\n hasToken: !!userData?.token,\r\n tokenPreview: userData?.token ? userData.token.substring(0, 20) + '...' : 'NO TOKEN',\r\n email: userData?.email,\r\n connectedAccounts: userData?.connectedAccounts\r\n });\r\n return (\r\n <TrainingScreen \r\n onComplete={handleTrainingScreenComplete}\r\n onTrainingStart={() => setTrainingHasStarted(true)}\r\n userEmail={userData?.email}\r\n connectedAccounts={userData?.connectedAccounts || []}\r\n userToken={userData?.token}\r\n />\r\n );\r\n case 'dataRequest':\r\n console.log('๐ŸŽฏ Rendering DataRequest:', {\r\n connectedAccounts: userData?.connectedAccounts,\r\n isArray: Array.isArray(userData?.connectedAccounts),\r\n userData: userData\r\n });\r\n return (\r\n <DataRequest \r\n onComplete={handleDataRequestComplete}\r\n onConnectMoreApps={() => {\r\n // Go back to UniversalOnboarding but return here afterwards.\r\n // Connected apps are persisted in localStorage by UniversalOnboarding.\r\n setReturnToDataRequestAfterOnboarding(true);\r\n setCurrentFlow('onboarding');\r\n }}\r\n userEmail={userData?.email || userData?.userName}\r\n requestData={requestData}\r\n appName={webpageName}\r\n autoFetch={autoFetch}\r\n testMode={testMode}\r\n appIcon={appIcon}\r\n connectedPlatforms={userData?.connectedAccounts || []}\r\n rawMemoriesOnly={rawMemoriesOnly}\r\n rawMemoriesConfig={rawMemoriesConfig}\r\n showTime={time}\r\n />\r\n );\r\n case 'wrappedLoading':\r\n return (\r\n <div className=\"flex-1 min-h-0\">\r\n <WrappedLoadingPage appName={webpageName} />\r\n </div>\r\n );\r\n case 'loading':\r\n return <LoadingScreen onComplete={handleLoadingComplete} />;\r\n default:\r\n return (\r\n <div className=\"flex flex-col items-center space-y-4 p-6\">\r\n <div className=\"animate-spin h-8 w-8 border-2 border-blue-600 rounded-full border-t-transparent\"></div>\r\n <p className=\"text-gray-600\">Loading...</p>\r\n </div>\r\n );\r\n }\r\n };\r\n\r\n // Styling and button class based on visual type\r\n const buttonClass = \r\n `flex items-center justify-center font-bold rounded cursor-pointer ${\r\n buttonType === 'pill' ? 'px-4 py-2' : 'w-12 h-12'\r\n } bg-transparent OnairosConnect`;\r\n\r\n const buttonStyle = {\r\n flexDirection: textLayout === 'below' ? 'column' : 'row',\r\n backgroundColor: 'transparent',\r\n color: textColor,\r\n border: '1px solid transparent',\r\n };\r\n\r\n // Icon and text style based on the visualType\r\n const logoStyle = {\r\n width: '20px',\r\n height: '20px',\r\n marginRight: visualType === 'full' ? '12px' : '0',\r\n };\r\n\r\n const getText = () => {\r\n switch (loginType) {\r\n case 'signUp':\r\n return 'Sign Up with Onairos';\r\n case 'signOut':\r\n return 'Sign Out of Onairos';\r\n default:\r\n return 'Sign In with Onairos';\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <button\r\n className={buttonClass}\r\n onClick={openTerminal}\r\n style={buttonStyle}\r\n >\r\n {(visualType === 'full' || visualType === 'icon') && (\r\n <img\r\n src={login ? \"https://onairos.sirv.com/Images/OnairosWhite.png\" : \"https://onairos.sirv.com/Images/OnairosBlack.png\"}\r\n alt=\"Onairos Logo\"\r\n style={logoStyle}\r\n />\r\n )}\r\n {visualType !== 'icon' && (\r\n <span className={`${textColor === 'black' ? 'text-black' : 'text-white'} ${visualType === 'icon' ? 'sr-only' : ''} ${textLayout === 'right' ? 'ml-2' : textLayout === 'left' ? 'mr-2' : ''}`}>\r\n {getText()}\r\n </span>\r\n )}\r\n </button>\r\n\r\n {/* Modal with New Design */}\r\n {showOverlay && (\r\n <>\r\n {isMobileDevice ? (\r\n // Mobile Browser: Use ModalPageLayout with mobile-optimized props\r\n <ModalPageLayout\r\n visible={showOverlay}\r\n onClose={handleCloseOverlay}\r\n showBackButton={currentFlow !== 'welcome' && currentFlow !== 'email' && currentFlow !== 'loading' && currentFlow !== 'wrappedLoading'}\r\n onBack={() => {\r\n if (currentFlow === 'onboarding') setCurrentFlow('email');\r\n else if (currentFlow === 'pin') setCurrentFlow('onboarding');\r\n else if (currentFlow === 'dataRequest') setCurrentFlow('onboarding');\r\n else if (currentFlow === 'training') setCurrentFlow('pin');\r\n }}\r\n showCloseButton={currentFlow === 'welcome' || currentFlow === 'email'}\r\n title=\"\"\r\n subtitle=\"\"\r\n icon={null}\r\n centerContent={true}\r\n contentClassName=\"!p-0\"\r\n modalClassName=\"onairos-modal onairos-modal-mobile\"\r\n >\r\n <div className=\"onairos-modal-shell flex-1 min-h-0 flex flex-col\">\r\n {renderContent()}\r\n </div>\r\n </ModalPageLayout>\r\n ) : (\r\n // Desktop Layout\r\n <ModalPageLayout\r\n visible={showOverlay}\r\n onClose={handleCloseOverlay}\r\n showBackButton={currentFlow === 'training' || currentFlow === 'onboarding' || currentFlow === 'pin' || currentFlow === 'dataRequest'}\r\n onBack={() => {\r\n if (currentFlow === 'email') setCurrentFlow('welcome');\r\n if (currentFlow === 'onboarding') setCurrentFlow('email');\r\n if (currentFlow === 'pin') setCurrentFlow('onboarding'); \r\n if (currentFlow === 'training') setCurrentFlow('pin');\r\n if (currentFlow === 'dataRequest') setCurrentFlow('onboarding');\r\n }}\r\n title=\"\"\r\n subtitle=\"\"\r\n icon={null}\r\n centerContent={true}\r\n contentClassName={currentFlow !== 'welcome' ? \"!p-0\" : \"\"}\r\n modalClassName=\"onairos-modal\"\r\n >\r\n <div className=\"onairos-modal-shell\">\r\n {renderContent()}\r\n </div>\r\n </ModalPageLayout>\r\n )}\r\n </>\r\n )}\r\n </>\r\n );\r\n}\r\n\r\nexport default OnairosButton;"],"names":["WelcomeScreen","_ref","onContinue","onClose","useEffect","script","document","createElement","src","async","head","appendChild","existingScript","querySelector","removeChild","React","className","style","height","alt","onClick","fill","stroke","viewBox","strokeLinecap","strokeLinejoin","strokeWidth","d","COLORS","btnGradStart","btnGradEnd","btnLabel","btnBorder","iconCircleGradientStart","iconCircleGradientEnd","background","backgroundSecondary","textPrimary","textSecondary","textMuted","border","borderLight","success","error","warning","info","hover","pressed","focus","IconCircle","size","children","concat","width","borderRadius","fontSize","color","backgroundColor","_ref2","label","iconRight","loading","disabled","testId","textStyle","centered","props","_objectWithoutProperties","_excluded","setPressed","useState","buttonStyle","_objectSpread","position","overflow","minWidth","maxWidth","margin","cursor","opacity","boxShadow","transition","pressedOverlayStyle","top","left","right","bottom","labelStyle","fontFamily","fontWeight","textAlign","_extends","onMouseDown","handleMouseDown","onMouseUp","handleMouseUp","onMouseLeave","handleMouseLeave","display","justifyContent","alignItems","EmailAuth","onSuccess","testMode","email","setEmail","codeDigits","setCodeDigits","Array","step","setStep","isLoading","setIsLoading","setError","emailSent","setEmailSent","emailServiceMessage","setEmailServiceMessage","code","join","isCodeComplete","every","length","resetCodeDigits","sleep","ms","Promise","resolve","setTimeout","postJson","url","apiKey","body","fetch","method","headers","JSON","stringify","handleOAuthSuccess","console","log","gmailEmail","normalizedEmail","trim","toLowerCase","baseUrl","window","onairosBaseUrl","onairosApiKey","accountInfo","accountStatus","existingUser","accountCheckResponse","Info","identifier","ok","accountData","json","_accountStatus","_accountStatus2","_accountStatus3","_accountStatus4","_accountStatus5","_accountStatus6","_accountStatus7","AccountInfo","exists","hasTrainedModel","hasPersonalityTraits","connectedPlatforms","needsDataConnection","needsTraining","canUseInference","accountCheckError","warn","verified","token","userName","split","isNewUser","flowType","adminMode","userCreated","accountDetails","createdAt","Date","toISOString","ssoProvider","checkGmailOAuthSuccess","gmailSuccess","localStorage","getItem","gmailTimestamp","oauthContext","timestampNum","parseInt","now","removeItem","checkOAuthCompletion","urlParams","URLSearchParams","location","search","oauthSuccess","get","oauthPlatform","oauthEmail","newUrl","pathname","history","replaceState","timestamp","firstInput","handleEmailSubmit","e","preventDefault","test","validateEmail","data","rawEmail","res","action","_unused","legacyRes","msg","err","_unused2","Error","requestEmailVerification","message","handleGoogleSuccess","credential","credentialResponse","base64","replace","jsonPayload","decodeURIComponent","atob","map","c","charCodeAt","toString","slice","userInfo","parse","name","picture","email_verified","sdkConfig","backendError","handleGoogleError","handleCodeSubmit","simulatedResponse","testAccount","codeToSubmit","rawCode","_ref3","normalizedCode","String","includes","attempt","errMsg","attemptsRemaining","_unused3","verifyEmailCode","_accountStatus8","_accountStatus9","_accountStatus0","_accountStatus1","_accountStatus10","_accountStatus11","_accountStatus12","jwtToken","provider","type","value","onChange","target","placeholder","WebkitTextFillColor","required","GoogleLogin","onError","text","shape","logo_alignment","lineHeight","borderColor","from","_","index","key","inputMode","pattern","maxLength","autoComplete","onPaste","_e$clipboardData","_e$currentTarget$pare","pasted","clipboardData","getData","nextDigits","i","focusIndex","Math","min","nextInput","currentTarget","parentElement","digitsOnly","_e$target$parentEleme","_e$target$parentEleme2","onKeyDown","_e$currentTarget$pare2","prevInput","caretColor","PrimaryButton","flex","minHeight","Check","isCapacitor","_window$Capacitor","_window$webkit","Capacitor","Plugins","webkit","messageHandlers","bridge","isReactNative","navigator","product","global","undefined","nativeModuleProxy","isMobileApp","isMobileBrowser","userAgent","innerWidth","BOOKMARKLET_HREF","ConnectChatGPTModal","open","onConnected","userToken","getUserToken","directToken","userData","substring","bookmarkletHref","createPortal","inset","zIndex","pointerEvents","fillRule","clipRule","animation","href","title","draggable","onDragStart","dataTransfer","setData","effectAllowed","alert","suppressHydrationWarning","handleGotIt","chatgptIcon","claudeIcon","geminiIcon","grokIcon","process","env","REACT_APP_ONAIROS_API_KEY","REACT_APP_ONAIROS_BASE_URL","sdkType","enableHealthMonitoring","enableAutoRefresh","enableConnectionValidation","fadeSlideInKeyframes","UniversalOnboarding","_window$Capacitor$isN","onComplete","onBack","appIcon","appName","username","priorityPlatform","rawMemoriesOnly","rawMemoriesConfig","isMobile","isMobileProp","lottieRef","useRef","lastFrameRef","rafRef","connectedAccounts","setConnectedAccounts","isConnecting","setIsConnecting","connectingPlatform","setConnectingPlatform","selected","setSelected","currentPage","setCurrentPage","showChatGPTModal","setShowChatGPTModal","touchStartX","touchDeltaX","isActualMobileDevice","isNativePlatform","call","vh","setVh","innerHeight","onResize","addEventListener","removeEventListener","isSmallMobile","personaSide","PERSONA_TOP","SLOT","max","floor","CIRCLE","GAP_PAGE1","GAP_PAGE2","ACTIVE_SCALE","ICONS_H","igGradId","round","useId","Brand","ChatGPT","objectFit","Claude","Gemini","Grok","Instagram","id","cx","cy","r","offset","stopColor","YouTube","Reddit","LinkedIn","Twitter","aiLinks","descriptions","allPlatforms","connector","icon","directLink","platforms","page","handleAuthSuccess","platform","detail","plat","find","p","s","existingArray","existingObj","isArray","reduce","acc","updated","connectedArray","Object","entries","filter","v","k","setItem","checkOAuthSuccess","sessionSuccess","sessionStorage","sessionPlatform","_ref4","_ref5","platformConnector","localStorageKey","timestampKey","_ref6","_ref7","_ref8","_ref9","accountsObj","handleSwitch","_JSON$parse","isCapacitorNative","effectiveMobile","returnUrl","origin","sessionPayload","bodyPayload","session","candidates","youtube","linkedin","reddit","pinterest","instagram","github","facebook","gmail","oauthUrl","keys","candidateLower","Browser","addListener","listenerError","windowName","presentationStyle","popup","closed","messageHandler","event","clearInterval","pollInterval","close","pollCount","maxPolls","setInterval","connectToPlatform","connectedCount","values","Boolean","current","totalFrames","personaAnim","progress","start","startTs","performance","t","eased","frame","goToAndStop","requestAnimationFrame","cancelAnimationFrame","scrollbarWidth","msOverflowStyle","transform","Lottie","animationData","autoplay","loop","paddingTop","paddingBottom","onTouchStart","touches","clientX","onTouchMove","onTouchEnd","dx","gridAutoFlow","gridTemplateColumns","columnGap","justifyItems","paddingInline","idx","on","isSel","shift","_window$Capacitor2","_window$Capacitor2$is","hasCapacitor","transformOrigin","marginTop","marginBottom","n","maxHeight","role","stopPropagation","WebkitTapHighlightColor","userSelect","touchAction","xmlns","connected","_ref0","_ref1","totalConnections","PinSetup","userEmail","pin","setPin","pinRequirements","setPinRequirements","uppercase","number","allRequirementsMet","handleSubmit","pinCreated","Icon","base","DataTypeToggle","dataType","enabled","onToggle","isNative","handle","options","onConnectMoreApps","showTime","basic","rawMemories","preferences","personality","freq","setFreq","isWrappedApp","toggle","val","selectedCount","getConnected","mapped","u","availableOptions","opt","hasLLMConnections","llmPlatforms","some","freqToPercent","f","rect","getBoundingClientRect","ratio","WebkitOverflowScrolling","Pinterest","GitHub","Facebook","Gmail","approved","declined","TrainingComponent","_steps$currentStep","_steps$currentStep2","_steps$currentStep3","_steps$currentStep4","_steps$currentStep5","currentStep","setCurrentStep","setProgress","isComplete","setIsComplete","steps","description","duration","interval","stepTimeout","stepDuration","stepProgress","prev","newProgress","completionDelay","trainingComplete","simulatedTraining","clearTimeout","trainingPhrases","TrainingScreen","onTrainingStart","currentPhrase","setCurrentPhrase","currentStage","setCurrentStage","socket","progressTimer","didSignalStart","signalTrainingStarted","storedToken","io","auth","transports","reconnection","timeout","socketId","emit","percentage","stage","result","_result$trainingResul","_result$trainingResul2","_result$trainingResul3","status","traits","trainingResults","userTraits","hasLlmData","llmData","inferenceResults","disconnect","fallback","reason","runTrainingAndInference","rainAnim","LoadingScreen","dotCount","setDotCount","loadingStates","stateInterval","nextStep","dotInterval","currentState","aspectRatio","repeat","WrappedLoadingPage","setAnimationData","messageIndex","setMessageIndex","messages","then","catch","err2","timer","next","messageTimer","PERSONALITY_TYPES","TRAIT_CATEGORIES","formatOnairosResponse","apiResponse","_apiResponse$Inferenc","arguments","includeDictionary","includeArray","formatted","InferenceResult","scores","_apiResponse$Inferenc2","personalityDict","forEach","_formatted$InferenceR","traitResult","traitDict","category","formatUserDataForDisplay","_result$userData","_result$userData2","_result$userData3","_result$userData4","_result$userData5","_result$userData6","_result$userData7","userDataSummary","requestInfo","userHash","dataTypesRequested","approvedData","userProfile","userType","onboardingComplete","modelReady","formatConnectedAccounts","aiData","formatAIResponseData","hasApiResponse","hasErrors","apiError","prettyPrint","lines","push","toLocaleString","summary","hasData","dataTypes","toUpperCase","createPrettyPrintVersion","accounts","count","account","connectedAt","a","_apiResponse$data","_apiResponse$Inferenc3","available","_apiResponse$data2","_apiResponse$data3","_apiResponse$data4","_apiResponse$data5","_apiResponse$Inferenc4","dashboard","slides","apps","personalityData","preferencesData","output","logFormattedUserData","PageLayout","subtitle","showHeader","showCloseButton","showBackButton","contentClassName","centerContent","isSmallScreen","layoutStyle","flexDirection","headerStyle","padding","contentStyle","titleStyle","subtitleStyle","ModalPageLayout","visible","onBackdropClick","backdropStyle","modalStyle","modalClassName","pageLayoutProps","_excluded2","mobileModalHeightPx","setMobileModalHeightPx","_window$visualViewpor","h","visualViewport","_window$visualViewpor3","_window$visualViewpor4","_window$visualViewpor5","_window$visualViewpor6","compute","_window$visualViewpor2","_window$visualViewpor7","_window$visualViewpor8","_window$visualViewpor9","_window$visualViewpor0","modalHeight","modalMaxHeight","modalMaxWidth","backdropAlign","backdropPadding","backdropStyles","willChange","hasBackdropStyleOverride","backdropStyleOverride","modalStyles","borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius","marginLeft","marginRight","flexShrink","hasModalStyleOverride","modalStyleWasApplied","modalStyleOverride","modalStyleKeys","backdropStyleKeys","modalMinHeight","OnairosButton","requestData","webpageName","inferenceData","autoFetch","proofMode","textLayout","textColor","login","buttonType","loginReturn","loginType","visualType","enableTraining","formatResponse","responseFormat","time","showOverlay","setShowOverlay","currentFlow","setCurrentFlow","trainingHasStarted","setTrainingHasStarted","setUserData","oauthReturnDetected","setOauthReturnDetected","returnToDataRequestAfterOnboarding","setReturnToDataRequestAfterOnboarding","isMobileDevice","setIsMobileDevice","computeMobile","_document$documentEle","_document$body","documentElement","clientWidth","parent","isCapNative","detectedMobile","dataset","onairosPrevOverflow","isDesktop","modal","pageContent","shell","getMetrics","el","styles","getComputedStyle","paddingLeft","paddingRight","classList","viewportWidth","handleDeepLink","hasSuccess","hasError","isPopup","opener","params","qIdx","indexOf","URL","searchParams","postMessage","innerHTML","questionMarkIndex","state","decoded","connectionType","dispatchEvent","CustomEvent","existingUserData","existing","merged","startsWith","cleanUrl","appListener","_window$Capacitor3","_window$Capacitor3$is","AppPlugin","App","_window$Capacitor4","setupListener","remove","checkWindowUrl","checkExistingSession","savedUser","user","checkOAuthReturn","handleCloseOverlay","handleWelcomeContinue","handleEmailAuthSuccess","authData","userState","hasAccountInfo","candidate","accessToken","payload","userId","sub","accountExists","finalDecision","reasoning","usingAccountStatus","existingUserFalse","flowTypeOnboarding","noAccountInfo","newUserData","normalizePlatformName","twitter","x","chatgpt","claude","gemini","grok","charAt","normalized","emailToken","handleOnboardingComplete","onboardingData","updatedUserData","handlePinSetupComplete","pinData","timeoutId","handleLoadingComplete","handleTrainingComplete","trainingResult","trainingCompleted","handleTrainingScreenComplete","handleDataRequestComplete","_requestResult$approv","_requestResult$approv2","_finalResult","requestResult","lastDataRequest","finalResult","urlResponse","appId","confirmations","EncryptedUserPin","storage","urlData","apiUrl","_finalResult$apiRespo","eventDetail","dataResponse","fetchUrl","fetchBody","includeLlmData","forceFresh","cacheBust","currentEmail","_unused4","_unused5","fetchCompleted","fetchError","controller","AbortController","abort","cache","signal","statusText","fromEntries","hasStatus","hasSlides","responseKeys","poll_interval_seconds","pollResponse","pollData","pollErr","fetchErr","_fetchErr$message","_fetchErr$message2","_fetchErr$message3","_fetchErr$message4","isTimeout","hasToken","_fetchError$message","_fetchError$message2","_fetchError$message3","formattedResult","_formattedResult$apiR","completeResult","enhancedResult","formatError","isWrappedAppForCallback","handleDashboardReady","renderContent","commonProps","hasUserData","tokenPreview","DataRequest","buttonClass","logoStyle","getText"],"sourceRoot":""}