@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
JavaScript
"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