@oxyhq/services 5.3.2 → 5.3.3
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.
- package/lib/commonjs/ui/navigation/OxyRouter.js +5 -0
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +70 -26
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ModernAccountSwitcherScreen.js +532 -0
- package/lib/commonjs/ui/screens/ModernAccountSwitcherScreen.js.map +1 -0
- package/lib/module/ui/navigation/OxyRouter.js +5 -0
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +72 -28
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/ModernAccountSwitcherScreen.js +527 -0
- package/lib/module/ui/screens/ModernAccountSwitcherScreen.js.map +1 -0
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ModernAccountSwitcherScreen.d.ts +5 -0
- package/lib/typescript/ui/screens/ModernAccountSwitcherScreen.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/ui/navigation/OxyRouter.tsx +5 -0
- package/src/ui/screens/AccountSwitcherScreen.tsx +85 -25
- package/src/ui/screens/ModernAccountSwitcherScreen.tsx +552 -0
|
@@ -8,17 +8,26 @@ import {
|
|
|
8
8
|
ScrollView,
|
|
9
9
|
Alert,
|
|
10
10
|
Platform,
|
|
11
|
+
Image,
|
|
12
|
+
Dimensions,
|
|
11
13
|
} from 'react-native';
|
|
12
14
|
import { BaseScreenProps } from '../navigation/types';
|
|
13
15
|
import { useOxy } from '../context/OxyContext';
|
|
14
16
|
import { SecureClientSession } from '../../models/secureSession';
|
|
15
17
|
import { fontFamilies } from '../styles/fonts';
|
|
18
|
+
import { User } from '../../models/interfaces';
|
|
19
|
+
|
|
20
|
+
interface SessionWithUser extends SecureClientSession {
|
|
21
|
+
userProfile?: User;
|
|
22
|
+
isLoadingProfile?: boolean;
|
|
23
|
+
}
|
|
16
24
|
|
|
17
25
|
const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
18
26
|
onClose,
|
|
19
27
|
theme,
|
|
20
28
|
navigate,
|
|
21
29
|
goBack,
|
|
30
|
+
oxyServices,
|
|
22
31
|
}) => {
|
|
23
32
|
const {
|
|
24
33
|
user,
|
|
@@ -30,17 +39,68 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
30
39
|
isLoading
|
|
31
40
|
} = useOxy();
|
|
32
41
|
|
|
42
|
+
const [sessionsWithUsers, setSessionsWithUsers] = useState<SessionWithUser[]>([]);
|
|
33
43
|
const [switchingToUserId, setSwitchingToUserId] = useState<string | null>(null);
|
|
34
44
|
const [removingUserId, setRemovingUserId] = useState<string | null>(null);
|
|
35
45
|
|
|
46
|
+
const screenWidth = Dimensions.get('window').width;
|
|
36
47
|
const isDarkTheme = theme === 'dark';
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
|
|
49
|
+
// Modern color scheme
|
|
50
|
+
const colors = {
|
|
51
|
+
background: isDarkTheme ? '#000000' : '#FFFFFF',
|
|
52
|
+
surface: isDarkTheme ? '#1C1C1E' : '#F2F2F7',
|
|
53
|
+
card: isDarkTheme ? '#2C2C2E' : '#FFFFFF',
|
|
54
|
+
text: isDarkTheme ? '#FFFFFF' : '#000000',
|
|
55
|
+
secondaryText: isDarkTheme ? '#8E8E93' : '#6D6D70',
|
|
56
|
+
accent: '#007AFF',
|
|
57
|
+
destructive: '#FF3B30',
|
|
58
|
+
success: '#34C759',
|
|
59
|
+
border: isDarkTheme ? '#38383A' : '#C6C6C8',
|
|
60
|
+
activeCard: isDarkTheme ? '#0A84FF20' : '#007AFF15',
|
|
61
|
+
shadow: isDarkTheme ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.1)',
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Load user profiles for sessions
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const loadUserProfiles = async () => {
|
|
67
|
+
if (!sessions.length || !oxyServices) return;
|
|
68
|
+
|
|
69
|
+
const updatedSessions: SessionWithUser[] = sessions.map(session => ({
|
|
70
|
+
...session,
|
|
71
|
+
isLoadingProfile: true,
|
|
72
|
+
}));
|
|
73
|
+
setSessionsWithUsers(updatedSessions);
|
|
74
|
+
|
|
75
|
+
// Load profiles for each session
|
|
76
|
+
for (let i = 0; i < sessions.length; i++) {
|
|
77
|
+
const session = sessions[i];
|
|
78
|
+
try {
|
|
79
|
+
// Try to get user profile using the session
|
|
80
|
+
const userProfile = await oxyServices.getUserBySession(session.sessionId);
|
|
81
|
+
|
|
82
|
+
setSessionsWithUsers(prev =>
|
|
83
|
+
prev.map(s =>
|
|
84
|
+
s.sessionId === session.sessionId
|
|
85
|
+
? { ...s, userProfile, isLoadingProfile: false }
|
|
86
|
+
: s
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
} catch (error) {
|
|
90
|
+
console.error(`Failed to load profile for session ${session.sessionId}:`, error);
|
|
91
|
+
setSessionsWithUsers(prev =>
|
|
92
|
+
prev.map(s =>
|
|
93
|
+
s.sessionId === session.sessionId
|
|
94
|
+
? { ...s, isLoadingProfile: false }
|
|
95
|
+
: s
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
loadUserProfiles();
|
|
103
|
+
}, [sessions, oxyServices]);
|
|
44
104
|
|
|
45
105
|
const handleSwitchSession = async (sessionId: string) => {
|
|
46
106
|
if (sessionId === user?.sessionId) return; // Already active session
|
|
@@ -134,20 +194,20 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
134
194
|
style={[
|
|
135
195
|
styles.userItem,
|
|
136
196
|
{
|
|
137
|
-
backgroundColor: isActive ?
|
|
138
|
-
borderColor: isActive ?
|
|
197
|
+
backgroundColor: isActive ? colors.activeCard : colors.surface,
|
|
198
|
+
borderColor: isActive ? colors.accent : colors.border,
|
|
139
199
|
},
|
|
140
200
|
]}
|
|
141
201
|
>
|
|
142
202
|
<View style={styles.userInfo}>
|
|
143
|
-
<Text style={[styles.username, { color:
|
|
203
|
+
<Text style={[styles.username, { color: colors.text }]}>
|
|
144
204
|
{isActive ? user?.username || 'Current Account' : 'Account Session'}
|
|
145
205
|
</Text>
|
|
146
206
|
<Text style={[styles.email, { color: isDarkTheme ? '#BBBBBB' : '#666666' }]}>
|
|
147
207
|
Last active: {new Date(session.lastActive).toLocaleDateString()}
|
|
148
208
|
</Text>
|
|
149
209
|
{isActive && (
|
|
150
|
-
<View style={[styles.activeBadge, { backgroundColor:
|
|
210
|
+
<View style={[styles.activeBadge, { backgroundColor: colors.success }]}>
|
|
151
211
|
<Text style={styles.activeBadgeText}>Active</Text>
|
|
152
212
|
</View>
|
|
153
213
|
)}
|
|
@@ -156,27 +216,27 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
156
216
|
<View style={styles.userActions}>
|
|
157
217
|
{!isActive && (
|
|
158
218
|
<TouchableOpacity
|
|
159
|
-
style={[styles.switchButton, { borderColor:
|
|
219
|
+
style={[styles.switchButton, { borderColor: colors.accent }]}
|
|
160
220
|
onPress={() => handleSwitchSession(session.sessionId)}
|
|
161
221
|
disabled={isSwitching || isRemoving}
|
|
162
222
|
>
|
|
163
223
|
{isSwitching ? (
|
|
164
|
-
<ActivityIndicator color={
|
|
224
|
+
<ActivityIndicator color={colors.accent} size="small" />
|
|
165
225
|
) : (
|
|
166
|
-
<Text style={[styles.switchButtonText, { color:
|
|
226
|
+
<Text style={[styles.switchButtonText, { color: colors.accent }]}>Switch</Text>
|
|
167
227
|
)}
|
|
168
228
|
</TouchableOpacity>
|
|
169
229
|
)}
|
|
170
230
|
|
|
171
231
|
<TouchableOpacity
|
|
172
|
-
style={[styles.removeButton, { borderColor:
|
|
232
|
+
style={[styles.removeButton, { borderColor: colors.destructive }]}
|
|
173
233
|
onPress={() => handleRemoveSession(session.sessionId)}
|
|
174
234
|
disabled={isSwitching || isRemoving || sessions.length === 1}
|
|
175
235
|
>
|
|
176
236
|
{isRemoving ? (
|
|
177
|
-
<ActivityIndicator color={
|
|
237
|
+
<ActivityIndicator color={colors.destructive} size="small" />
|
|
178
238
|
) : (
|
|
179
|
-
<Text style={[styles.removeButtonText, { color:
|
|
239
|
+
<Text style={[styles.removeButtonText, { color: colors.destructive }]}>Remove</Text>
|
|
180
240
|
)}
|
|
181
241
|
</TouchableOpacity>
|
|
182
242
|
</View>
|
|
@@ -185,12 +245,12 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
185
245
|
};
|
|
186
246
|
|
|
187
247
|
return (
|
|
188
|
-
<View style={[styles.container, { backgroundColor }]}>
|
|
248
|
+
<View style={[styles.container, { backgroundColor: colors.background }]}>
|
|
189
249
|
<View style={styles.header}>
|
|
190
250
|
<TouchableOpacity style={styles.backButton} onPress={goBack}>
|
|
191
|
-
<Text style={[styles.backButtonText, { color:
|
|
251
|
+
<Text style={[styles.backButtonText, { color: colors.accent }]}>‹ Back</Text>
|
|
192
252
|
</TouchableOpacity>
|
|
193
|
-
<Text style={[styles.title, { color:
|
|
253
|
+
<Text style={[styles.title, { color: colors.text }]}>Account Switcher</Text>
|
|
194
254
|
<View style={styles.placeholder} />
|
|
195
255
|
</View>
|
|
196
256
|
|
|
@@ -202,7 +262,7 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
202
262
|
</View>
|
|
203
263
|
|
|
204
264
|
<View style={styles.usersContainer}>
|
|
205
|
-
<Text style={[styles.sectionTitle, { color:
|
|
265
|
+
<Text style={[styles.sectionTitle, { color: colors.text }]}>
|
|
206
266
|
Sessions ({sessions.length})
|
|
207
267
|
</Text>
|
|
208
268
|
|
|
@@ -211,10 +271,10 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
211
271
|
|
|
212
272
|
<View style={styles.actionsContainer}>
|
|
213
273
|
<TouchableOpacity
|
|
214
|
-
style={[styles.actionButton, { borderColor }]}
|
|
274
|
+
style={[styles.actionButton, { borderColor: colors.border }]}
|
|
215
275
|
onPress={() => navigate('SignIn')}
|
|
216
276
|
>
|
|
217
|
-
<Text style={[styles.actionButtonText, { color:
|
|
277
|
+
<Text style={[styles.actionButtonText, { color: colors.text }]}>
|
|
218
278
|
Add Another Account
|
|
219
279
|
</Text>
|
|
220
280
|
</TouchableOpacity>
|
|
@@ -226,9 +286,9 @@ const AccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
226
286
|
disabled={isLoading}
|
|
227
287
|
>
|
|
228
288
|
{isLoading ? (
|
|
229
|
-
<ActivityIndicator color={
|
|
289
|
+
<ActivityIndicator color={colors.destructive} size="small" />
|
|
230
290
|
) : (
|
|
231
|
-
<Text style={[styles.dangerButtonText, { color:
|
|
291
|
+
<Text style={[styles.dangerButtonText, { color: colors.destructive }]}>
|
|
232
292
|
Sign Out All Sessions
|
|
233
293
|
</Text>
|
|
234
294
|
)}
|