@oxyhq/services 6.9.43 → 6.9.45
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/index.js +9 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/ActingAsBanner.js +143 -0
- package/lib/commonjs/ui/components/ActingAsBanner.js.map +1 -0
- package/lib/commonjs/ui/components/OxyPayButton.js +4 -2
- package/lib/commonjs/ui/components/OxyPayButton.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +83 -82
- package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
- package/lib/commonjs/ui/components/SettingRow.js +11 -5
- package/lib/commonjs/ui/components/SettingRow.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js +76 -121
- package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js +32 -18
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/commonjs/ui/components/icon/OxyIcon.js +5 -4
- package/lib/commonjs/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +11 -9
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/PinInput.js +3 -2
- package/lib/commonjs/ui/components/internal/PinInput.js.map +1 -1
- package/lib/commonjs/ui/components/modals/DeleteAccountModal.js +83 -219
- package/lib/commonjs/ui/components/modals/DeleteAccountModal.js.map +1 -1
- package/lib/commonjs/ui/constants/theme.js +2 -2
- package/lib/commonjs/ui/constants/theme.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +78 -3
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/navigation/routes.js +3 -2
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +33 -11
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +70 -79
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +22 -10
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +376 -82
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js +21 -9
- package/lib/commonjs/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js +346 -0
- package/lib/commonjs/ui/screens/CreateManagedAccountScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/FileManagementScreen.js +83 -50
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/HistoryViewScreen.js +80 -101
- package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +66 -93
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +101 -66
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/fileManagement.js +0 -21
- package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
- package/lib/module/index.js +3 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/ActingAsBanner.js +140 -0
- package/lib/module/ui/components/ActingAsBanner.js.map +1 -0
- package/lib/module/ui/components/OxyPayButton.js +4 -2
- package/lib/module/ui/components/OxyPayButton.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +84 -83
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/components/SettingRow.js +11 -5
- package/lib/module/ui/components/SettingRow.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileDetailsModal.js +76 -122
- package/lib/module/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
- package/lib/module/ui/components/fileManagement/UploadPreview.js +32 -19
- package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/module/ui/components/icon/OxyIcon.js +5 -4
- package/lib/module/ui/components/icon/OxyIcon.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +11 -9
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/PinInput.js +3 -2
- package/lib/module/ui/components/internal/PinInput.js.map +1 -1
- package/lib/module/ui/components/modals/DeleteAccountModal.js +83 -220
- package/lib/module/ui/components/modals/DeleteAccountModal.js.map +1 -1
- package/lib/module/ui/constants/theme.js +2 -2
- package/lib/module/ui/constants/theme.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +78 -3
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/navigation/routes.js +3 -2
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +32 -11
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +71 -80
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +22 -10
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +375 -82
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountVerificationScreen.js +22 -10
- package/lib/module/ui/screens/AccountVerificationScreen.js.map +1 -1
- package/lib/module/ui/screens/CreateManagedAccountScreen.js +342 -0
- package/lib/module/ui/screens/CreateManagedAccountScreen.js.map +1 -0
- package/lib/module/ui/screens/FileManagementScreen.js +85 -52
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/HistoryViewScreen.js +80 -101
- package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +66 -94
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +101 -67
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/utils/fileManagement.js +0 -20
- package/lib/module/ui/utils/fileManagement.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ActingAsBanner.d.ts +4 -0
- package/lib/typescript/commonjs/ui/components/ActingAsBanner.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/OxyPayButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts +0 -1
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SettingRow.d.ts +2 -2
- package/lib/typescript/commonjs/ui/components/SettingRow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts +3 -4
- package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/UploadPreview.d.ts +2 -3
- package/lib/typescript/commonjs/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/icon/OxyIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/internal/PinInput.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts +2 -2
- package/lib/typescript/commonjs/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +6 -0
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts +5 -0
- package/lib/typescript/commonjs/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/HistoryViewScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +0 -4
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ActingAsBanner.d.ts +4 -0
- package/lib/typescript/module/ui/components/ActingAsBanner.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/OxyPayButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts +0 -1
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SettingRow.d.ts +2 -2
- package/lib/typescript/module/ui/components/SettingRow.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts +3 -4
- package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/UploadPreview.d.ts +2 -3
- package/lib/typescript/module/ui/components/fileManagement/UploadPreview.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/icon/OxyIcon.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/internal/GroupedPillButtons.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/internal/PinInput.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts +2 -2
- package/lib/typescript/module/ui/components/modals/DeleteAccountModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +6 -0
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/AccountVerificationScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts +5 -0
- package/lib/typescript/module/ui/screens/CreateManagedAccountScreen.d.ts.map +1 -0
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/HistoryViewScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/fileManagement.d.ts +0 -4
- package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +3 -0
- package/src/ui/components/ActingAsBanner.tsx +135 -0
- package/src/ui/components/OxyPayButton.tsx +5 -3
- package/src/ui/components/OxySignInButton.tsx +82 -81
- package/src/ui/components/SettingRow.tsx +14 -7
- package/src/ui/components/fileManagement/FileDetailsModal.tsx +69 -99
- package/src/ui/components/fileManagement/UploadPreview.tsx +58 -46
- package/src/ui/components/icon/OxyIcon.tsx +5 -4
- package/src/ui/components/internal/GroupedPillButtons.tsx +15 -12
- package/src/ui/components/internal/PinInput.tsx +4 -3
- package/src/ui/components/modals/DeleteAccountModal.tsx +79 -221
- package/src/ui/constants/theme.ts +2 -2
- package/src/ui/context/OxyContext.tsx +85 -0
- package/src/ui/navigation/routes.ts +3 -1
- package/src/ui/screens/AccountCenterScreen.tsx +40 -122
- package/src/ui/screens/AccountOverviewScreen.tsx +63 -98
- package/src/ui/screens/AccountSettingsScreen.tsx +21 -7
- package/src/ui/screens/AccountSwitcherScreen.tsx +344 -87
- package/src/ui/screens/AccountVerificationScreen.tsx +24 -16
- package/src/ui/screens/CreateManagedAccountScreen.tsx +338 -0
- package/src/ui/screens/FileManagementScreen.tsx +62 -54
- package/src/ui/screens/HistoryViewScreen.tsx +57 -204
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +73 -93
- package/src/ui/screens/SessionManagementScreen.tsx +101 -73
- package/src/ui/utils/fileManagement.ts +0 -30
- package/lib/commonjs/ui/utils/confirmAction.js +0 -28
- package/lib/commonjs/ui/utils/confirmAction.js.map +0 -1
- package/lib/module/ui/utils/confirmAction.js +0 -25
- package/lib/module/ui/utils/confirmAction.js.map +0 -1
- package/lib/typescript/commonjs/ui/utils/confirmAction.d.ts +0 -7
- package/lib/typescript/commonjs/ui/utils/confirmAction.d.ts.map +0 -1
- package/lib/typescript/module/ui/utils/confirmAction.d.ts +0 -7
- package/lib/typescript/module/ui/utils/confirmAction.d.ts.map +0 -1
- package/src/ui/utils/confirmAction.ts +0 -23
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
StyleSheet,
|
|
8
8
|
ActivityIndicator,
|
|
9
9
|
ScrollView,
|
|
10
|
-
Alert,
|
|
11
10
|
Platform,
|
|
12
11
|
Image,
|
|
13
12
|
Dimensions,
|
|
@@ -17,7 +16,8 @@ import type { ClientSession } from '@oxyhq/core';
|
|
|
17
16
|
import { fontFamilies } from '../styles/fonts';
|
|
18
17
|
import type { User } from '@oxyhq/core';
|
|
19
18
|
import { toast } from '../../lib/sonner';
|
|
20
|
-
import
|
|
19
|
+
import * as Prompt from '@oxyhq/bloom/prompt';
|
|
20
|
+
import { usePromptControl } from '@oxyhq/bloom/prompt';
|
|
21
21
|
import OxyIcon from '../components/icon/OxyIcon';
|
|
22
22
|
import { Ionicons } from '@expo/vector-icons';
|
|
23
23
|
import Avatar from '../components/Avatar';
|
|
@@ -60,11 +60,15 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
60
60
|
refreshSessions,
|
|
61
61
|
isLoading = false,
|
|
62
62
|
isAuthenticated = false,
|
|
63
|
+
actingAs,
|
|
64
|
+
managedAccounts,
|
|
65
|
+
setActingAs,
|
|
63
66
|
} = useOxy();
|
|
64
67
|
|
|
65
68
|
const [sessionsWithUsers, setSessionsWithUsers] = useState<SessionWithUser[]>([]);
|
|
66
69
|
const [switchingToUserId, setSwitchingToUserId] = useState<string | null>(null);
|
|
67
70
|
const [removingUserId, setRemovingUserId] = useState<string | null>(null);
|
|
71
|
+
const [switchingManagedId, setSwitchingManagedId] = useState<string | null>(null);
|
|
68
72
|
|
|
69
73
|
// Device session management state
|
|
70
74
|
const [showDeviceManagement, setShowDeviceManagement] = useState(false);
|
|
@@ -73,6 +77,16 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
73
77
|
const [remotingLogoutSessionId, setRemoteLogoutSessionId] = useState<string | null>(null);
|
|
74
78
|
const [loggingOutAllDevices, setLoggingOutAllDevices] = useState(false);
|
|
75
79
|
|
|
80
|
+
// Pending state for prompts
|
|
81
|
+
const [pendingRemoveSession, setPendingRemoveSession] = useState<{ sessionId: string; displayName: string } | null>(null);
|
|
82
|
+
const [pendingRemoteLogout, setPendingRemoteLogout] = useState<{ sessionId: string; deviceName: string } | null>(null);
|
|
83
|
+
|
|
84
|
+
// Prompt controls
|
|
85
|
+
const removeSessionPrompt = usePromptControl();
|
|
86
|
+
const logoutAllPrompt = usePromptControl();
|
|
87
|
+
const remoteLogoutPrompt = usePromptControl();
|
|
88
|
+
const logoutAllDevicesPrompt = usePromptControl();
|
|
89
|
+
|
|
76
90
|
const screenWidth = Dimensions.get('window').width;
|
|
77
91
|
const { t } = useI18n();
|
|
78
92
|
|
|
@@ -167,49 +181,74 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
167
181
|
}
|
|
168
182
|
}, [activeSessionId, switchSession, onClose, t, switchingToUserId]);
|
|
169
183
|
|
|
170
|
-
const
|
|
171
|
-
if (removingUserId) return;
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
setRemovingUserId(null);
|
|
187
|
-
}
|
|
184
|
+
const confirmRemoveSession = useCallback((sessionId: string, displayName: string) => {
|
|
185
|
+
if (removingUserId) return;
|
|
186
|
+
setPendingRemoveSession({ sessionId, displayName });
|
|
187
|
+
removeSessionPrompt.open();
|
|
188
|
+
}, [removingUserId, removeSessionPrompt]);
|
|
189
|
+
|
|
190
|
+
const handleRemoveSession = useCallback(async () => {
|
|
191
|
+
if (!pendingRemoveSession) return;
|
|
192
|
+
const { sessionId } = pendingRemoveSession;
|
|
193
|
+
setRemovingUserId(sessionId);
|
|
194
|
+
try {
|
|
195
|
+
await removeSession(sessionId);
|
|
196
|
+
toast.success(t('accountSwitcher.toasts.removeSuccess') || 'Account removed successfully!');
|
|
197
|
+
} catch (error) {
|
|
198
|
+
if (__DEV__) {
|
|
199
|
+
console.error('Remove session failed:', error);
|
|
188
200
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
201
|
+
toast.error(t('accountSwitcher.toasts.removeFailed') || 'There was a problem removing the account. Please try again.');
|
|
202
|
+
} finally {
|
|
203
|
+
setRemovingUserId(null);
|
|
204
|
+
setPendingRemoveSession(null);
|
|
205
|
+
}
|
|
206
|
+
}, [pendingRemoveSession, removeSession, t]);
|
|
207
|
+
|
|
208
|
+
const confirmLogoutAll = useCallback(() => {
|
|
209
|
+
logoutAllPrompt.open();
|
|
210
|
+
}, [logoutAllPrompt]);
|
|
211
|
+
|
|
212
|
+
const handleLogoutAll = useCallback(async () => {
|
|
213
|
+
try {
|
|
214
|
+
await logoutAll();
|
|
215
|
+
toast.success(t('accountSwitcher.toasts.signOutAllSuccess') || 'All accounts signed out successfully!');
|
|
216
|
+
if (onClose) {
|
|
217
|
+
onClose();
|
|
218
|
+
}
|
|
219
|
+
} catch (error) {
|
|
220
|
+
if (__DEV__) {
|
|
221
|
+
console.error('Logout all failed:', error);
|
|
209
222
|
}
|
|
210
|
-
|
|
223
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
224
|
+
toast.error(t('accountSwitcher.toasts.signOutAllFailed', { error: errorMessage }) || `There was a problem signing out: ${errorMessage}`);
|
|
225
|
+
}
|
|
211
226
|
}, [logoutAll, onClose, t]);
|
|
212
227
|
|
|
228
|
+
const handleSwitchToManagedAccount = useCallback(async (accountId: string) => {
|
|
229
|
+
if (actingAs === accountId) return; // Already acting as this account
|
|
230
|
+
if (switchingManagedId) return; // Already switching
|
|
231
|
+
|
|
232
|
+
setSwitchingManagedId(accountId);
|
|
233
|
+
try {
|
|
234
|
+
setActingAs(accountId);
|
|
235
|
+
toast.success(t('accountSwitcher.toasts.switchSuccess') || 'Switched identity successfully!');
|
|
236
|
+
onClose?.();
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (__DEV__) {
|
|
239
|
+
console.error('Switch managed account failed:', error);
|
|
240
|
+
}
|
|
241
|
+
toast.error('Failed to switch identity. Please try again.');
|
|
242
|
+
} finally {
|
|
243
|
+
setSwitchingManagedId(null);
|
|
244
|
+
}
|
|
245
|
+
}, [actingAs, switchingManagedId, setActingAs, t, onClose]);
|
|
246
|
+
|
|
247
|
+
const handleSwitchBackToPrimary = useCallback(() => {
|
|
248
|
+
setActingAs(null);
|
|
249
|
+
toast.success('Switched back to primary account');
|
|
250
|
+
}, [setActingAs]);
|
|
251
|
+
|
|
213
252
|
// Device session management functions - optimized with useCallback
|
|
214
253
|
const loadAllDeviceSessions = useCallback(async () => {
|
|
215
254
|
const currentActiveSessionId = activeSessionId ?? null;
|
|
@@ -229,30 +268,32 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
229
268
|
}
|
|
230
269
|
}, [oxyServices, activeSessionId, t]);
|
|
231
270
|
|
|
232
|
-
const
|
|
233
|
-
if (remotingLogoutSessionId) return;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
setRemoteLogoutSessionId(null);
|
|
250
|
-
}
|
|
271
|
+
const confirmRemoteSessionLogout = useCallback((sessionId: string, deviceName: string) => {
|
|
272
|
+
if (remotingLogoutSessionId) return;
|
|
273
|
+
setPendingRemoteLogout({ sessionId, deviceName });
|
|
274
|
+
remoteLogoutPrompt.open();
|
|
275
|
+
}, [remotingLogoutSessionId, remoteLogoutPrompt]);
|
|
276
|
+
|
|
277
|
+
const handleRemoteSessionLogout = useCallback(async () => {
|
|
278
|
+
if (!pendingRemoteLogout) return;
|
|
279
|
+
const { sessionId } = pendingRemoteLogout;
|
|
280
|
+
setRemoteLogoutSessionId(sessionId);
|
|
281
|
+
try {
|
|
282
|
+
await oxyServices?.logoutSession((activeSessionId ?? null) || '', sessionId);
|
|
283
|
+
await loadAllDeviceSessions();
|
|
284
|
+
toast.success(t('accountSwitcher.toasts.remoteSignOutSuccess', { deviceName: pendingRemoteLogout.deviceName }) || `Signed out from ${pendingRemoteLogout.deviceName} successfully!`);
|
|
285
|
+
} catch (error) {
|
|
286
|
+
if (__DEV__) {
|
|
287
|
+
console.error('Remote logout failed:', error);
|
|
251
288
|
}
|
|
252
|
-
|
|
253
|
-
|
|
289
|
+
toast.error(t('accountSwitcher.toasts.remoteSignOutFailed') || 'There was a problem signing out from the device. Please try again.');
|
|
290
|
+
} finally {
|
|
291
|
+
setRemoteLogoutSessionId(null);
|
|
292
|
+
setPendingRemoteLogout(null);
|
|
293
|
+
}
|
|
294
|
+
}, [pendingRemoteLogout, activeSessionId, oxyServices, loadAllDeviceSessions, t]);
|
|
254
295
|
|
|
255
|
-
const
|
|
296
|
+
const confirmLogoutAllDevices = useCallback(() => {
|
|
256
297
|
const otherDevicesCount = deviceSessions.filter(session => !session.isCurrent).length;
|
|
257
298
|
|
|
258
299
|
if (otherDevicesCount === 0) {
|
|
@@ -260,27 +301,25 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
260
301
|
return;
|
|
261
302
|
}
|
|
262
303
|
|
|
263
|
-
if (loggingOutAllDevices) return;
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
toast.error(t('accountSwitcher.toasts.signOutOthersFailed') || 'There was a problem signing out from other devices. Please try again.');
|
|
278
|
-
} finally {
|
|
279
|
-
setLoggingOutAllDevices(false);
|
|
280
|
-
}
|
|
304
|
+
if (loggingOutAllDevices) return;
|
|
305
|
+
logoutAllDevicesPrompt.open();
|
|
306
|
+
}, [deviceSessions, loggingOutAllDevices, logoutAllDevicesPrompt, t]);
|
|
307
|
+
|
|
308
|
+
const handleLogoutAllDevices = useCallback(async () => {
|
|
309
|
+
setLoggingOutAllDevices(true);
|
|
310
|
+
try {
|
|
311
|
+
await oxyServices?.logoutAllDeviceSessions((activeSessionId ?? null) || '');
|
|
312
|
+
await loadAllDeviceSessions();
|
|
313
|
+
toast.success(t('accountSwitcher.toasts.signOutOthersSuccess') || 'Signed out from all other devices successfully!');
|
|
314
|
+
} catch (error) {
|
|
315
|
+
if (__DEV__) {
|
|
316
|
+
console.error('Logout all devices failed:', error);
|
|
281
317
|
}
|
|
282
|
-
|
|
283
|
-
|
|
318
|
+
toast.error(t('accountSwitcher.toasts.signOutOthersFailed') || 'There was a problem signing out from other devices. Please try again.');
|
|
319
|
+
} finally {
|
|
320
|
+
setLoggingOutAllDevices(false);
|
|
321
|
+
}
|
|
322
|
+
}, [activeSessionId, oxyServices, loadAllDeviceSessions, t]);
|
|
284
323
|
|
|
285
324
|
// Memoize filtered sessions for performance
|
|
286
325
|
const otherSessions = useMemo(
|
|
@@ -288,6 +327,11 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
288
327
|
[sessionsWithUsers, activeSessionId]
|
|
289
328
|
);
|
|
290
329
|
|
|
330
|
+
const otherDevicesCount = useMemo(
|
|
331
|
+
() => deviceSessions.filter(session => !session.isCurrent).length,
|
|
332
|
+
[deviceSessions]
|
|
333
|
+
);
|
|
334
|
+
|
|
291
335
|
return (
|
|
292
336
|
<View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
|
|
293
337
|
{/* Header */}
|
|
@@ -412,7 +456,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
412
456
|
</TouchableOpacity>
|
|
413
457
|
<TouchableOpacity
|
|
414
458
|
style={styles.removeButton}
|
|
415
|
-
onPress={() =>
|
|
459
|
+
onPress={() => confirmRemoveSession(sessionWithUser.sessionId, displayName)}
|
|
416
460
|
disabled={isSwitching || isRemoving}
|
|
417
461
|
>
|
|
418
462
|
{isRemoving ? (
|
|
@@ -428,6 +472,151 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
428
472
|
</View>
|
|
429
473
|
)}
|
|
430
474
|
|
|
475
|
+
{/* Acting as banner - show switch-back when acting as a managed account */}
|
|
476
|
+
{actingAs && (
|
|
477
|
+
<View style={styles.section}>
|
|
478
|
+
<TouchableOpacity
|
|
479
|
+
style={[styles.settingItem, styles.firstSettingItem, styles.lastSettingItem, styles.actingAsBanner]}
|
|
480
|
+
onPress={handleSwitchBackToPrimary}
|
|
481
|
+
activeOpacity={0.7}
|
|
482
|
+
>
|
|
483
|
+
<View style={styles.settingInfo}>
|
|
484
|
+
<Text style={styles.settingLabel}>Switch back to primary account</Text>
|
|
485
|
+
<Text style={styles.settingDescription}>You are currently acting as another identity</Text>
|
|
486
|
+
</View>
|
|
487
|
+
<View style={styles.switchBackButton}>
|
|
488
|
+
<Text style={styles.switchBackButtonText}>Switch Back</Text>
|
|
489
|
+
</View>
|
|
490
|
+
</TouchableOpacity>
|
|
491
|
+
</View>
|
|
492
|
+
)}
|
|
493
|
+
|
|
494
|
+
{/* Managed Accounts */}
|
|
495
|
+
{managedAccounts.length > 0 && (
|
|
496
|
+
<View style={styles.section}>
|
|
497
|
+
<Text style={styles.sectionTitle}>Managed Accounts</Text>
|
|
498
|
+
<Text style={styles.sectionSubtitle}>Identities you manage</Text>
|
|
499
|
+
|
|
500
|
+
{managedAccounts.map((managed, index) => {
|
|
501
|
+
const account = managed.account;
|
|
502
|
+
if (!account) return null;
|
|
503
|
+
|
|
504
|
+
const isActive = actingAs === managed.accountId;
|
|
505
|
+
const isSwitching = switchingManagedId === managed.accountId;
|
|
506
|
+
const isFirst = index === 0;
|
|
507
|
+
const isLast = index === managedAccounts.length - 1;
|
|
508
|
+
|
|
509
|
+
const managedDisplayName = typeof account.name === 'object'
|
|
510
|
+
? account.name.full || account.name.first || account.username
|
|
511
|
+
: account.name || account.username || 'Unknown';
|
|
512
|
+
|
|
513
|
+
// Determine the manager role for badge display
|
|
514
|
+
const myRole = managed.managers?.find(
|
|
515
|
+
(m) => m.userId === user?.id
|
|
516
|
+
)?.role ?? 'owner';
|
|
517
|
+
|
|
518
|
+
return (
|
|
519
|
+
<TouchableOpacity
|
|
520
|
+
key={`managed-${managed.accountId}`}
|
|
521
|
+
style={[
|
|
522
|
+
styles.settingItem,
|
|
523
|
+
isFirst && styles.firstSettingItem,
|
|
524
|
+
isLast && styles.lastSettingItem,
|
|
525
|
+
isActive && styles.currentAccountCard,
|
|
526
|
+
]}
|
|
527
|
+
onPress={() => handleSwitchToManagedAccount(managed.accountId)}
|
|
528
|
+
disabled={isActive || isSwitching}
|
|
529
|
+
activeOpacity={0.7}
|
|
530
|
+
>
|
|
531
|
+
<View style={styles.userIcon}>
|
|
532
|
+
{account.avatar ? (
|
|
533
|
+
<Image source={{ uri: oxyServices.getFileDownloadUrl(account.avatar, 'thumb') }} style={styles.accountAvatarImage} />
|
|
534
|
+
) : (
|
|
535
|
+
<View style={[styles.accountAvatarFallback, styles.managedAvatarFallback]}>
|
|
536
|
+
<Text style={styles.accountAvatarText}>
|
|
537
|
+
{managedDisplayName.charAt(0).toUpperCase()}
|
|
538
|
+
</Text>
|
|
539
|
+
</View>
|
|
540
|
+
)}
|
|
541
|
+
{isActive && (
|
|
542
|
+
<View style={styles.activeBadge}>
|
|
543
|
+
<OxyIcon name="checkmark" size={12} color="#fff" />
|
|
544
|
+
</View>
|
|
545
|
+
)}
|
|
546
|
+
</View>
|
|
547
|
+
<View style={styles.settingInfo}>
|
|
548
|
+
<View>
|
|
549
|
+
<Text style={styles.settingLabel}>{managedDisplayName}</Text>
|
|
550
|
+
<Text style={styles.settingDescription}>@{account.username}</Text>
|
|
551
|
+
</View>
|
|
552
|
+
</View>
|
|
553
|
+
<View style={styles.accountActions}>
|
|
554
|
+
<View style={styles.roleBadge}>
|
|
555
|
+
<Text style={styles.roleBadgeText}>{myRole}</Text>
|
|
556
|
+
</View>
|
|
557
|
+
{isActive ? (
|
|
558
|
+
<View style={styles.currentBadge}>
|
|
559
|
+
<Text style={styles.currentBadgeText}>Current</Text>
|
|
560
|
+
</View>
|
|
561
|
+
) : (
|
|
562
|
+
<TouchableOpacity
|
|
563
|
+
style={styles.switchButton}
|
|
564
|
+
onPress={() => handleSwitchToManagedAccount(managed.accountId)}
|
|
565
|
+
disabled={isSwitching}
|
|
566
|
+
>
|
|
567
|
+
{isSwitching ? (
|
|
568
|
+
<ActivityIndicator size="small" color="#fff" />
|
|
569
|
+
) : (
|
|
570
|
+
<Text style={styles.switchButtonText}>Act As</Text>
|
|
571
|
+
)}
|
|
572
|
+
</TouchableOpacity>
|
|
573
|
+
)}
|
|
574
|
+
</View>
|
|
575
|
+
</TouchableOpacity>
|
|
576
|
+
);
|
|
577
|
+
})}
|
|
578
|
+
|
|
579
|
+
{/* Create New Identity */}
|
|
580
|
+
<TouchableOpacity
|
|
581
|
+
style={[styles.settingItem, styles.firstSettingItem, styles.lastSettingItem, { marginTop: 8 }]}
|
|
582
|
+
onPress={() => navigate?.('CreateManagedAccount')}
|
|
583
|
+
activeOpacity={0.7}
|
|
584
|
+
>
|
|
585
|
+
<View style={styles.userIcon}>
|
|
586
|
+
<View style={[styles.accountAvatarFallback, { backgroundColor: '#007AFF20' }]}>
|
|
587
|
+
<OxyIcon name="add" size={20} color="#007AFF" />
|
|
588
|
+
</View>
|
|
589
|
+
</View>
|
|
590
|
+
<View style={styles.settingInfo}>
|
|
591
|
+
<Text style={[styles.settingLabel, { color: '#007AFF' }]}>Create New Identity</Text>
|
|
592
|
+
<Text style={styles.settingDescription}>Add a managed sub-account</Text>
|
|
593
|
+
</View>
|
|
594
|
+
</TouchableOpacity>
|
|
595
|
+
</View>
|
|
596
|
+
)}
|
|
597
|
+
|
|
598
|
+
{/* Create first managed account (when none exist yet) */}
|
|
599
|
+
{managedAccounts.length === 0 && isAuthenticated && (
|
|
600
|
+
<View style={styles.section}>
|
|
601
|
+
<Text style={styles.sectionTitle}>Managed Accounts</Text>
|
|
602
|
+
<TouchableOpacity
|
|
603
|
+
style={[styles.settingItem, styles.firstSettingItem, styles.lastSettingItem]}
|
|
604
|
+
onPress={() => navigate?.('CreateManagedAccount')}
|
|
605
|
+
activeOpacity={0.7}
|
|
606
|
+
>
|
|
607
|
+
<View style={styles.userIcon}>
|
|
608
|
+
<View style={[styles.accountAvatarFallback, { backgroundColor: '#007AFF20' }]}>
|
|
609
|
+
<OxyIcon name="add" size={20} color="#007AFF" />
|
|
610
|
+
</View>
|
|
611
|
+
</View>
|
|
612
|
+
<View style={styles.settingInfo}>
|
|
613
|
+
<Text style={[styles.settingLabel, { color: '#007AFF' }]}>Create New Identity</Text>
|
|
614
|
+
<Text style={styles.settingDescription}>Create a managed sub-account you control</Text>
|
|
615
|
+
</View>
|
|
616
|
+
</TouchableOpacity>
|
|
617
|
+
</View>
|
|
618
|
+
)}
|
|
619
|
+
|
|
431
620
|
{/* Quick Actions */}
|
|
432
621
|
<View style={styles.section}>
|
|
433
622
|
<Text style={styles.sectionTitle}>Quick Actions</Text>
|
|
@@ -456,7 +645,7 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
456
645
|
iconColor: '#FF3B30',
|
|
457
646
|
title: 'Sign Out All Accounts',
|
|
458
647
|
subtitle: 'Remove all accounts from this device',
|
|
459
|
-
onPress:
|
|
648
|
+
onPress: confirmLogoutAll,
|
|
460
649
|
disabled: sessionsWithUsers.length === 0,
|
|
461
650
|
},
|
|
462
651
|
]}
|
|
@@ -508,12 +697,12 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
508
697
|
iconColor: session.isCurrent ? '#34C759' : '#8E8E93',
|
|
509
698
|
title: `${session.deviceName} ${session.isCurrent ? `(${t('accountSwitcher.device.thisDevice') || 'This device'})` : ''}`,
|
|
510
699
|
subtitle: t('accountSwitcher.device.lastActive', { date: new Date(session.lastActive).toLocaleDateString() }) || `Last active: ${new Date(session.lastActive).toLocaleDateString()}`,
|
|
511
|
-
onPress: session.isCurrent ? undefined : () =>
|
|
700
|
+
onPress: session.isCurrent ? undefined : () => confirmRemoteSessionLogout(session.sessionId, session.deviceName),
|
|
512
701
|
disabled: session.isCurrent || remotingLogoutSessionId === session.sessionId,
|
|
513
702
|
customContent: !session.isCurrent ? (
|
|
514
703
|
<TouchableOpacity
|
|
515
704
|
style={styles.removeButton}
|
|
516
|
-
onPress={() =>
|
|
705
|
+
onPress={() => confirmRemoteSessionLogout(session.sessionId, session.deviceName)}
|
|
517
706
|
disabled={remotingLogoutSessionId === session.sessionId}
|
|
518
707
|
>
|
|
519
708
|
{remotingLogoutSessionId === session.sessionId ? (
|
|
@@ -566,6 +755,38 @@ const ModernAccountSwitcherScreen: React.FC<BaseScreenProps> = ({
|
|
|
566
755
|
</>
|
|
567
756
|
)}
|
|
568
757
|
</ScrollView>
|
|
758
|
+
<Prompt.Basic
|
|
759
|
+
control={removeSessionPrompt}
|
|
760
|
+
title={t('accountSwitcher.confirms.removeTitle') || 'Remove Account'}
|
|
761
|
+
description={pendingRemoveSession ? (t('accountSwitcher.confirms.remove', { displayName: pendingRemoveSession.displayName }) || `Are you sure you want to remove ${pendingRemoveSession.displayName} from this device? You'll need to sign in again to access this account.`) : ''}
|
|
762
|
+
onConfirm={handleRemoveSession}
|
|
763
|
+
confirmButtonCta={t('common.remove') || 'Remove'}
|
|
764
|
+
confirmButtonColor='negative'
|
|
765
|
+
/>
|
|
766
|
+
<Prompt.Basic
|
|
767
|
+
control={logoutAllPrompt}
|
|
768
|
+
title={t('accountSwitcher.confirms.logoutAllTitle') || 'Sign Out All'}
|
|
769
|
+
description={t('accountSwitcher.confirms.logoutAll') || 'Are you sure you want to sign out of all accounts? This will remove all saved accounts from this device.'}
|
|
770
|
+
onConfirm={handleLogoutAll}
|
|
771
|
+
confirmButtonCta={t('common.signOutAll') || 'Sign Out All'}
|
|
772
|
+
confirmButtonColor='negative'
|
|
773
|
+
/>
|
|
774
|
+
<Prompt.Basic
|
|
775
|
+
control={remoteLogoutPrompt}
|
|
776
|
+
title={t('accountSwitcher.confirms.remoteLogoutTitle') || 'Remote Sign Out'}
|
|
777
|
+
description={pendingRemoteLogout ? (t('accountSwitcher.confirms.remoteLogout', { deviceName: pendingRemoteLogout.deviceName }) || `Are you sure you want to sign out from "${pendingRemoteLogout.deviceName}"? This will end the session on that device.`) : ''}
|
|
778
|
+
onConfirm={handleRemoteSessionLogout}
|
|
779
|
+
confirmButtonCta={t('common.signOut') || 'Sign Out'}
|
|
780
|
+
confirmButtonColor='negative'
|
|
781
|
+
/>
|
|
782
|
+
<Prompt.Basic
|
|
783
|
+
control={logoutAllDevicesPrompt}
|
|
784
|
+
title={t('accountSwitcher.confirms.logoutOthersTitle') || 'Sign Out Other Devices'}
|
|
785
|
+
description={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.`}
|
|
786
|
+
onConfirm={handleLogoutAllDevices}
|
|
787
|
+
confirmButtonCta={t('common.signOutAll') || 'Sign Out All'}
|
|
788
|
+
confirmButtonColor='negative'
|
|
789
|
+
/>
|
|
569
790
|
</View>
|
|
570
791
|
);
|
|
571
792
|
};
|
|
@@ -729,6 +950,42 @@ const styles = StyleSheet.create({
|
|
|
729
950
|
fontSize: 16,
|
|
730
951
|
fontWeight: '600',
|
|
731
952
|
},
|
|
953
|
+
sectionSubtitle: {
|
|
954
|
+
fontSize: 13,
|
|
955
|
+
color: '#888',
|
|
956
|
+
marginBottom: 12,
|
|
957
|
+
},
|
|
958
|
+
managedAvatarFallback: {
|
|
959
|
+
backgroundColor: '#5856D6',
|
|
960
|
+
},
|
|
961
|
+
roleBadge: {
|
|
962
|
+
backgroundColor: '#F2F2F7',
|
|
963
|
+
paddingHorizontal: 8,
|
|
964
|
+
paddingVertical: 3,
|
|
965
|
+
borderRadius: 8,
|
|
966
|
+
},
|
|
967
|
+
roleBadgeText: {
|
|
968
|
+
color: '#666',
|
|
969
|
+
fontSize: 11,
|
|
970
|
+
fontWeight: '500',
|
|
971
|
+
textTransform: 'capitalize',
|
|
972
|
+
},
|
|
973
|
+
actingAsBanner: {
|
|
974
|
+
borderWidth: 2,
|
|
975
|
+
borderColor: '#FF9500',
|
|
976
|
+
backgroundColor: '#FF950010',
|
|
977
|
+
},
|
|
978
|
+
switchBackButton: {
|
|
979
|
+
backgroundColor: '#FF9500',
|
|
980
|
+
paddingHorizontal: 14,
|
|
981
|
+
paddingVertical: 8,
|
|
982
|
+
borderRadius: 16,
|
|
983
|
+
},
|
|
984
|
+
switchBackButtonText: {
|
|
985
|
+
color: '#fff',
|
|
986
|
+
fontSize: 13,
|
|
987
|
+
fontWeight: '600',
|
|
988
|
+
},
|
|
732
989
|
});
|
|
733
990
|
|
|
734
991
|
export default ModernAccountSwitcherScreen;
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
TextInput,
|
|
8
8
|
TouchableOpacity,
|
|
9
9
|
ActivityIndicator,
|
|
10
|
-
Alert,
|
|
11
10
|
} from 'react-native';
|
|
12
11
|
import type { BaseScreenProps } from '../types/navigation';
|
|
13
12
|
import { toast } from '../../lib/sonner';
|
|
13
|
+
import * as Prompt from '@oxyhq/bloom/prompt';
|
|
14
|
+
import { usePromptControl } from '@oxyhq/bloom/prompt';
|
|
14
15
|
import { Header, Section } from '../components';
|
|
15
16
|
import { useI18n } from '../hooks/useI18n';
|
|
16
17
|
import { useTheme } from '@oxyhq/bloom/theme';
|
|
@@ -27,9 +28,19 @@ const AccountVerificationScreen: React.FC<BaseScreenProps> = ({
|
|
|
27
28
|
const [reason, setReason] = useState('');
|
|
28
29
|
const [evidence, setEvidence] = useState('');
|
|
29
30
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
31
|
+
const [successMessage, setSuccessMessage] = useState('');
|
|
30
32
|
|
|
31
33
|
const bloomTheme = useTheme();
|
|
32
34
|
|
|
35
|
+
// Prompt controls
|
|
36
|
+
const successPrompt = usePromptControl();
|
|
37
|
+
|
|
38
|
+
const handleSuccessAcknowledged = useCallback(() => {
|
|
39
|
+
setReason('');
|
|
40
|
+
setEvidence('');
|
|
41
|
+
goBack?.();
|
|
42
|
+
}, [goBack]);
|
|
43
|
+
|
|
33
44
|
const handleSubmit = useCallback(async () => {
|
|
34
45
|
if (!reason.trim()) {
|
|
35
46
|
toast.error(t('accountVerification.reasonRequired') || 'Please provide a reason for verification');
|
|
@@ -48,20 +59,10 @@ const AccountVerificationScreen: React.FC<BaseScreenProps> = ({
|
|
|
48
59
|
evidence.trim() || undefined
|
|
49
60
|
);
|
|
50
61
|
|
|
51
|
-
|
|
52
|
-
t('accountVerification.
|
|
53
|
-
t('accountVerification.successMessage') || `Your verification request has been submitted. Request ID: ${result.requestId}`,
|
|
54
|
-
[
|
|
55
|
-
{
|
|
56
|
-
text: t('accountVerification.ok') || 'OK',
|
|
57
|
-
onPress: () => {
|
|
58
|
-
setReason('');
|
|
59
|
-
setEvidence('');
|
|
60
|
-
goBack?.();
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
]
|
|
62
|
+
setSuccessMessage(
|
|
63
|
+
t('accountVerification.successMessage') || `Your verification request has been submitted. Request ID: ${result.requestId}`
|
|
64
64
|
);
|
|
65
|
+
successPrompt.open();
|
|
65
66
|
} catch (error: unknown) {
|
|
66
67
|
if (__DEV__) {
|
|
67
68
|
console.error('Failed to submit verification request:', error);
|
|
@@ -72,7 +73,7 @@ const AccountVerificationScreen: React.FC<BaseScreenProps> = ({
|
|
|
72
73
|
} finally {
|
|
73
74
|
setIsSubmitting(false);
|
|
74
75
|
}
|
|
75
|
-
}, [reason, evidence, oxyServices, t,
|
|
76
|
+
}, [reason, evidence, oxyServices, t, successPrompt]);
|
|
76
77
|
|
|
77
78
|
return (
|
|
78
79
|
<View style={[styles.container, { backgroundColor: bloomTheme.colors.background }]}>
|
|
@@ -158,6 +159,14 @@ const AccountVerificationScreen: React.FC<BaseScreenProps> = ({
|
|
|
158
159
|
</Text>
|
|
159
160
|
</Section>
|
|
160
161
|
</ScrollView>
|
|
162
|
+
<Prompt.Basic
|
|
163
|
+
control={successPrompt}
|
|
164
|
+
title={t('accountVerification.successTitle') || 'Request Submitted'}
|
|
165
|
+
description={successMessage}
|
|
166
|
+
onConfirm={handleSuccessAcknowledged}
|
|
167
|
+
confirmButtonCta={t('accountVerification.ok') || 'OK'}
|
|
168
|
+
showCancel={false}
|
|
169
|
+
/>
|
|
161
170
|
</View>
|
|
162
171
|
);
|
|
163
172
|
};
|
|
@@ -214,4 +223,3 @@ const styles = StyleSheet.create({
|
|
|
214
223
|
});
|
|
215
224
|
|
|
216
225
|
export default React.memo(AccountVerificationScreen);
|
|
217
|
-
|