UNPKG

@oxyhq/services

Version:

Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀

717 lines (700 loc) • 29.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = require("react"); var _reactNative = require("react-native"); var _OxyContext = require("../context/OxyContext"); var _sonner = require("../../lib/sonner"); var _confirmAction = require("../utils/confirmAction"); var _OxyIcon = _interopRequireDefault(require("../components/icon/OxyIcon")); var _components = require("../components"); var _useI18n = require("../hooks/useI18n"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const ModernAccountSwitcherScreen = ({ onClose, theme, navigate, goBack, oxyServices }) => { const { user, sessions, activeSessionId, switchSession, removeSession, logoutAll, refreshSessions, isLoading, isAuthenticated } = (0, _OxyContext.useOxy)(); const [sessionsWithUsers, setSessionsWithUsers] = (0, _react.useState)([]); const [switchingToUserId, setSwitchingToUserId] = (0, _react.useState)(null); const [removingUserId, setRemovingUserId] = (0, _react.useState)(null); // Device session management state const [showDeviceManagement, setShowDeviceManagement] = (0, _react.useState)(false); const [deviceSessions, setDeviceSessions] = (0, _react.useState)([]); const [loadingDeviceSessions, setLoadingDeviceSessions] = (0, _react.useState)(false); const [remotingLogoutSessionId, setRemoteLogoutSessionId] = (0, _react.useState)(null); const [loggingOutAllDevices, setLoggingOutAllDevices] = (0, _react.useState)(false); const screenWidth = _reactNative.Dimensions.get('window').width; const isDarkTheme = theme === 'dark'; const { t } = (0, _useI18n.useI18n)(); // Modern color scheme - memoized for performance const colors = (0, _react.useMemo)(() => ({ background: isDarkTheme ? '#000000' : '#FFFFFF', surface: isDarkTheme ? '#1C1C1E' : '#F2F2F7', card: isDarkTheme ? '#2C2C2E' : '#FFFFFF', text: isDarkTheme ? '#FFFFFF' : '#000000', secondaryText: isDarkTheme ? '#8E8E93' : '#6D6D70', accent: '#007AFF', destructive: '#FF3B30', success: '#34C759', border: isDarkTheme ? '#38383A' : '#C6C6C8', activeCard: isDarkTheme ? '#0A84FF20' : '#007AFF15', shadow: isDarkTheme ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.1)' }), [isDarkTheme]); // Refresh sessions when screen loads (0, _react.useEffect)(() => { if (isAuthenticated && activeSessionId) { refreshSessions(); } }, [isAuthenticated, activeSessionId]); // Memoize session IDs to prevent unnecessary re-renders const sessionIds = (0, _react.useMemo)(() => sessions.map(s => s.sessionId).join(','), [sessions]); // Load user profiles for sessions // Production-ready: Optimized with batching, memoization, and error handling (0, _react.useEffect)(() => { let cancelled = false; const loadUserProfiles = async () => { if (!sessions.length || !oxyServices || cancelled) return; // Sessions are already deduplicated by userId at the core level (OxyContext) const uniqueSessions = sessions; // Initialize loading state setSessionsWithUsers(uniqueSessions.map(session => ({ ...session, isLoadingProfile: true }))); // Batch load profiles for better performance using batch endpoint try { const sessionIds = uniqueSessions.map(s => s.sessionId); const batchResults = await oxyServices.getUsersBySessions(sessionIds); // Create a map for O(1) lookup const userProfileMap = new Map(); batchResults.forEach(({ sessionId, user }) => { userProfileMap.set(sessionId, user); }); if (cancelled) return; // Update sessions with loaded profiles - optimized with Map for O(1) lookup setSessionsWithUsers(prev => { return prev.map(session => { const userProfile = userProfileMap.get(session.sessionId); return { ...session, userProfile: userProfile || undefined, isLoadingProfile: false }; }); }); } catch (error) { if (!cancelled && __DEV__) { console.error('Failed to load user profiles:', error); } if (!cancelled) { setSessionsWithUsers(prev => prev.map(s => ({ ...s, isLoadingProfile: false }))); } } }; loadUserProfiles(); return () => { cancelled = true; }; }, [sessionIds, oxyServices, sessions]); const handleSwitchSession = (0, _react.useCallback)(async sessionId => { if (sessionId === activeSessionId) return; // Already active session if (switchingToUserId) return; // Already switching setSwitchingToUserId(sessionId); try { await switchSession(sessionId); _sonner.toast.success(t('accountSwitcher.toasts.switchSuccess') || 'Account switched successfully!'); if (onClose) { onClose(); } } catch (error) { if (__DEV__) { console.error('Switch session failed:', error); } _sonner.toast.error(t('accountSwitcher.toasts.switchFailed') || 'There was a problem switching accounts. Please try again.'); } finally { setSwitchingToUserId(null); } }, [activeSessionId, switchSession, onClose, t, switchingToUserId]); const handleRemoveSession = (0, _react.useCallback)(async (sessionId, displayName) => { if (removingUserId) return; // Already removing (0, _confirmAction.confirmAction)(t('accountSwitcher.confirms.remove', { displayName }) || `Are you sure you want to remove ${displayName} from this device? You'll need to sign in again to access this account.`, async () => { setRemovingUserId(sessionId); try { await removeSession(sessionId); _sonner.toast.success(t('accountSwitcher.toasts.removeSuccess') || 'Account removed successfully!'); } catch (error) { if (__DEV__) { console.error('Remove session failed:', error); } _sonner.toast.error(t('accountSwitcher.toasts.removeFailed') || 'There was a problem removing the account. Please try again.'); } finally { setRemovingUserId(null); } }); }, [removeSession, t, removingUserId]); const handleLogoutAll = (0, _react.useCallback)(() => { (0, _confirmAction.confirmAction)(t('accountSwitcher.confirms.logoutAll') || 'Are you sure you want to sign out of all accounts? This will remove all saved accounts from this device.', async () => { try { await logoutAll(); _sonner.toast.success(t('accountSwitcher.toasts.signOutAllSuccess') || 'All accounts signed out successfully!'); if (onClose) { onClose(); } } catch (error) { if (__DEV__) { console.error('Logout all failed:', error); } const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; _sonner.toast.error(t('accountSwitcher.toasts.signOutAllFailed', { error: errorMessage }) || `There was a problem signing out: ${errorMessage}`); } }); }, [logoutAll, onClose, t]); // Device session management functions - optimized with useCallback const loadAllDeviceSessions = (0, _react.useCallback)(async () => { if (!oxyServices || !activeSessionId) return; setLoadingDeviceSessions(true); try { const allSessions = await oxyServices.getDeviceSessions(activeSessionId); setDeviceSessions(allSessions || []); } catch (error) { if (__DEV__) { console.error('Failed to load device sessions:', error); } _sonner.toast.error(t('accountSwitcher.toasts.deviceLoadFailed') || 'Failed to load device sessions. Please try again.'); } finally { setLoadingDeviceSessions(false); } }, [oxyServices, activeSessionId, t]); const handleRemoteSessionLogout = (0, _react.useCallback)((sessionId, deviceName) => { if (remotingLogoutSessionId) return; // Already processing (0, _confirmAction.confirmAction)(t('accountSwitcher.confirms.remoteLogout', { deviceName }) || `Are you sure you want to sign out from "${deviceName}"? This will end the session on that device.`, async () => { setRemoteLogoutSessionId(sessionId); try { await oxyServices?.logoutSession(activeSessionId || '', sessionId); await loadAllDeviceSessions(); _sonner.toast.success(t('accountSwitcher.toasts.remoteSignOutSuccess', { deviceName }) || `Signed out from ${deviceName} successfully!`); } catch (error) { if (__DEV__) { console.error('Remote logout failed:', error); } _sonner.toast.error(t('accountSwitcher.toasts.remoteSignOutFailed') || 'There was a problem signing out from the device. Please try again.'); } finally { setRemoteLogoutSessionId(null); } }); }, [activeSessionId, oxyServices, loadAllDeviceSessions, t, remotingLogoutSessionId]); const handleLogoutAllDevices = (0, _react.useCallback)(() => { const otherDevicesCount = deviceSessions.filter(session => !session.isCurrent).length; if (otherDevicesCount === 0) { _sonner.toast.info(t('accountSwitcher.toasts.noOtherDeviceSessions') || 'No other device sessions found to sign out from.'); return; } if (loggingOutAllDevices) return; // Already processing (0, _confirmAction.confirmAction)(t('accountSwitcher.confirms.logoutOthers', { count: otherDevicesCount }) || `Are you sure you want to sign out from all ${otherDevicesCount} other device(s)? This will end sessions on all other devices except this one.`, async () => { setLoggingOutAllDevices(true); try { await oxyServices?.logoutAllDeviceSessions(activeSessionId || ''); await loadAllDeviceSessions(); _sonner.toast.success(t('accountSwitcher.toasts.signOutOthersSuccess') || 'Signed out from all other devices successfully!'); } catch (error) { if (__DEV__) { console.error('Logout all devices failed:', error); } _sonner.toast.error(t('accountSwitcher.toasts.signOutOthersFailed') || 'There was a problem signing out from other devices. Please try again.'); } finally { setLoggingOutAllDevices(false); } }); }, [deviceSessions, activeSessionId, oxyServices, loadAllDeviceSessions, t, loggingOutAllDevices]); // Memoize filtered sessions for performance const otherSessions = (0, _react.useMemo)(() => sessionsWithUsers.filter(s => s.sessionId !== activeSessionId), [sessionsWithUsers, activeSessionId]); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.container, { backgroundColor: '#f2f2f2' }], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Header, { title: t('accountSwitcher.title') || 'Account Switcher', theme: theme, onBack: goBack, onClose: onClose, showBackButton: true, showCloseButton: true, elevation: "subtle", rightAction: { icon: "refresh", onPress: refreshSessions } }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, { style: styles.content, children: isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.loadingContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "large", color: "#007AFF" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.loadingText, children: t('accountSwitcher.loading') || 'Loading accounts...' })] }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [isAuthenticated && user && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.section, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.sectionTitle, children: t('accountSwitcher.sections.current') || 'Current Account' }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.settingItem, styles.firstSettingItem, styles.lastSettingItem, styles.currentAccountCard], children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.userIcon, children: [typeof user.avatar === 'string' && user.avatar ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, { source: { uri: oxyServices.getFileDownloadUrl(user.avatar, 'thumb') }, style: styles.accountAvatarImage }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.accountAvatarFallback, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.accountAvatarText, children: (typeof user.name === 'string' ? user.name : user.name?.first || user.username)?.charAt(0).toUpperCase() }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.activeBadge, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, { name: "checkmark", size: 12, color: "#fff" }) })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.settingInfo, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.settingLabel, children: typeof user.name === 'string' ? user.name : user.name?.full || user.name?.first || user.username }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.settingDescription, children: user.email || user.username })] }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.currentBadge, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.currentBadgeText, children: t('accountSwitcher.currentBadge') || 'Current' }) })] })] }), otherSessions.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.section, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.sectionTitle, children: t('accountSwitcher.sections.otherWithCount', { count: otherSessions.length }) || `Other Accounts (${otherSessions.length})` }), otherSessions.map((sessionWithUser, index, filteredArray) => { const isFirst = index === 0; const isLast = index === filteredArray.length - 1; const isSwitching = switchingToUserId === sessionWithUser.sessionId; const isRemoving = removingUserId === sessionWithUser.sessionId; const { userProfile, isLoadingProfile } = sessionWithUser; const displayName = typeof userProfile?.name === 'object' ? userProfile.name.full || userProfile.name.first || userProfile.username : userProfile?.name || userProfile?.username || 'Unknown User'; return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: [styles.settingItem, isFirst && styles.firstSettingItem, isLast && styles.lastSettingItem], children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.userIcon, children: isLoadingProfile ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.accountAvatarFallback, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "small", color: "#007AFF" }) }) : typeof userProfile?.avatar === 'string' && userProfile.avatar ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, { source: { uri: oxyServices.getFileDownloadUrl(userProfile.avatar, 'thumb') }, style: styles.accountAvatarImage }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.accountAvatarFallback, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.accountAvatarText, children: displayName.charAt(0).toUpperCase() }) }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.settingInfo, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.settingLabel, children: displayName }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, { style: styles.settingDescription, children: ["@", userProfile?.username || 'unknown'] })] }) }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.accountActions, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: styles.switchButton, onPress: () => handleSwitchSession(sessionWithUser.sessionId), disabled: isSwitching || isRemoving, children: isSwitching ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "small", color: "#007AFF" }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.switchButtonText, children: "Switch" }) }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: styles.removeButton, onPress: () => handleRemoveSession(sessionWithUser.sessionId, displayName), disabled: isSwitching || isRemoving, children: isRemoving ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "small", color: "#FF3B30" }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, { name: "trash", size: 16, color: "#FF3B30" }) })] })] }, `session-${sessionWithUser.sessionId}-${index}`); })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.section, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.sectionTitle, children: "Quick Actions" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.GroupedSection, { items: [{ id: 'add-account', icon: 'person-add', iconColor: '#007AFF', title: 'Add Another Account', subtitle: 'Sign in with a different account', onPress: () => navigate?.('SignIn') }, { id: 'device-management', icon: 'phone-portrait', iconColor: '#5856D6', title: `${showDeviceManagement ? 'Hide' : 'Manage'} Device Sessions`, subtitle: 'View and manage sessions on other devices', onPress: () => setShowDeviceManagement(!showDeviceManagement) }, { id: 'sign-out-all', icon: 'log-out', iconColor: '#FF3B30', title: 'Sign Out All Accounts', subtitle: 'Remove all accounts from this device', onPress: handleLogoutAll, disabled: sessionsWithUsers.length === 0 }], theme: theme })] }), showDeviceManagement && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.section, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.sectionTitle, children: t('accountSwitcher.sections.deviceSessions') || 'Device Sessions' }), loadingDeviceSessions ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.GroupedSection, { items: [{ id: 'loading-device-sessions', icon: 'sync', iconColor: '#007AFF', title: t('accountSwitcher.device.loadingTitle') || 'Loading device sessions...', subtitle: t('accountSwitcher.device.loadingSubtitle') || 'Please wait while we fetch your device sessions', disabled: true, customContent: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "small", color: "#007AFF", style: { marginRight: 16 } }) }], theme: theme }) : deviceSessions.length === 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.GroupedSection, { items: [{ id: 'no-device-sessions', icon: 'phone-portrait', iconColor: '#ccc', title: t('accountSwitcher.device.noneTitle') || 'No device sessions found', subtitle: t('accountSwitcher.device.noneSubtitle') || 'Device session management not available', disabled: true }], theme: theme }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.GroupedSection, { items: deviceSessions.map((session, index) => ({ id: `device-session-${session.sessionId}`, icon: session.isCurrent ? 'phone-portrait' : 'phone-portrait-outline', iconColor: session.isCurrent ? '#34C759' : '#8E8E93', title: `${session.deviceName} ${session.isCurrent ? '(' + (t('accountSwitcher.device.thisDevice') || 'This device') + ')' : ''}`, subtitle: t('accountSwitcher.device.lastActive', { date: new Date(session.lastActive).toLocaleDateString() }) || `Last active: ${new Date(session.lastActive).toLocaleDateString()}`, onPress: session.isCurrent ? undefined : () => handleRemoteSessionLogout(session.sessionId, session.deviceName), disabled: session.isCurrent || remotingLogoutSessionId === session.sessionId, customContent: !session.isCurrent ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: styles.removeButton, onPress: () => handleRemoteSessionLogout(session.sessionId, session.deviceName), disabled: remotingLogoutSessionId === session.sessionId, children: remotingLogoutSessionId === session.sessionId ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, { size: "small", color: "#FF3B30" }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, { name: "log-out", size: 16, color: "#FF3B30" }) }) : undefined })), theme: theme })] }), sessionsWithUsers.length === 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.section, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.GroupedSection, { items: [{ id: 'empty-state', icon: 'person-outline', iconColor: '#ccc', title: t('accountSwitcher.empty.title') || 'No saved accounts', subtitle: t('accountSwitcher.empty.subtitle') || 'Add another account to switch between them quickly', onPress: () => navigate?.('SignIn'), customContent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: styles.emptyStateContainer, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_OxyIcon.default, { name: "person-outline", size: 48, color: "#ccc" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.emptyStateTitle, children: t('accountSwitcher.empty.title') || 'No saved accounts' }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.emptyStateDescription, children: t('accountSwitcher.empty.subtitle') || 'Add another account to switch between them quickly' }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, { style: styles.addAccountButton, onPress: () => navigate?.('SignIn'), children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, { style: styles.addAccountButtonText, children: t('accountCenter.sections.addAccount') || 'Add Account' }) })] }) }], theme: theme }) })] }) })] }); }; const styles = _reactNative.StyleSheet.create({ container: { flex: 1, backgroundColor: '#f2f2f2' }, content: { flex: 1, padding: 16 }, section: { marginBottom: 24 }, sectionTitle: { fontSize: 16, fontWeight: '600', color: '#333', marginBottom: 12 }, settingItem: { backgroundColor: '#fff', padding: 16, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginBottom: 2 }, firstSettingItem: { borderTopLeftRadius: 24, borderTopRightRadius: 24 }, lastSettingItem: { borderBottomLeftRadius: 24, borderBottomRightRadius: 24, marginBottom: 8 }, currentAccountCard: { borderWidth: 2, borderColor: '#007AFF', backgroundColor: '#007AFF08' }, settingInfo: { flexDirection: 'row', alignItems: 'center', flex: 1 }, settingLabel: { fontSize: 16, fontWeight: '500', color: '#333', marginBottom: 2 }, settingDescription: { fontSize: 14, color: '#666' }, userIcon: { marginRight: 12, position: 'relative' }, accountAvatarImage: { width: 40, height: 40, borderRadius: 20 }, accountAvatarFallback: { width: 40, height: 40, borderRadius: 20, backgroundColor: '#d169e5', alignItems: 'center', justifyContent: 'center' }, accountAvatarText: { color: 'white', fontSize: 18, fontWeight: 'bold' }, activeBadge: { position: 'absolute', top: -2, right: -2, width: 16, height: 16, borderRadius: 8, backgroundColor: '#34C759', alignItems: 'center', justifyContent: 'center', borderWidth: 2, borderColor: '#fff' }, currentBadge: { backgroundColor: '#007AFF', paddingHorizontal: 8, paddingVertical: 4, borderRadius: 12 }, currentBadgeText: { color: '#fff', fontSize: 12, fontWeight: '600' }, accountActions: { flexDirection: 'row', alignItems: 'center', gap: 8 }, switchButton: { backgroundColor: '#007AFF', paddingHorizontal: 16, paddingVertical: 8, borderRadius: 16, minWidth: 60, alignItems: 'center' }, switchButtonText: { color: '#fff', fontSize: 14, fontWeight: '500' }, removeButton: { padding: 8, borderRadius: 16, backgroundColor: '#fff', borderWidth: 1, borderColor: '#FF3B30', alignItems: 'center', justifyContent: 'center' }, loadingContainer: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 20, gap: 12 }, loadingText: { fontSize: 16, color: '#666' }, emptyStateContainer: { alignItems: 'center', paddingVertical: 32, paddingHorizontal: 20 }, emptyStateTitle: { fontSize: 18, fontWeight: '600', color: '#333', marginTop: 16, marginBottom: 8 }, emptyStateDescription: { fontSize: 14, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 20 }, addAccountButton: { backgroundColor: '#007AFF', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 20 }, addAccountButtonText: { color: '#fff', fontSize: 16, fontWeight: '600' } }); var _default = exports.default = ModernAccountSwitcherScreen; //# sourceMappingURL=AccountSwitcherScreen.js.map