@oxyhq/services 5.16.17 → 5.16.19
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/README.md +7 -8
- package/lib/commonjs/core/mixins/OxyServices.security.js +42 -0
- package/lib/commonjs/core/mixins/OxyServices.security.js.map +1 -1
- package/lib/commonjs/crypto/index.js +0 -7
- package/lib/commonjs/crypto/index.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +2 -2
- package/lib/commonjs/crypto/polyfill.js +4 -4
- package/lib/commonjs/i18n/locales/en-US.json +1 -1
- package/lib/commonjs/index.js +0 -7
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/interfaces.js +2 -0
- package/lib/commonjs/models/interfaces.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +19 -1
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +1 -27
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/Section.js +2 -1
- package/lib/commonjs/ui/components/Section.js.map +1 -1
- package/lib/commonjs/ui/components/SectionTitle.js +1 -2
- package/lib/commonjs/ui/components/SectionTitle.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js +3 -3
- package/lib/commonjs/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +61 -9
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +65 -17
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useDeviceManagement.js +1 -1
- package/lib/commonjs/ui/context/hooks/useLanguageManagement.js +1 -1
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js +3 -3
- package/lib/commonjs/ui/context/hooks/useStorage.js +2 -2
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +1 -1
- package/lib/commonjs/ui/hooks/useIdentityMutations.js +4 -4
- package/lib/commonjs/ui/hooks/useIdentityMutations.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +22 -7
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +13 -13
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +17 -17
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +2 -2
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +10 -9
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +15 -15
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +1 -1
- package/lib/commonjs/ui/screens/HelpSupportScreen.js +3 -3
- package/lib/commonjs/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/HistoryViewScreen.js +2 -2
- package/lib/commonjs/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +3 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js +4 -4
- package/lib/commonjs/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js +1 -2
- package/lib/commonjs/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +44 -16
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +3 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +2 -2
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +8 -5
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/utils/errorHandlers.js +49 -2
- package/lib/commonjs/ui/utils/errorHandlers.js.map +1 -1
- package/lib/commonjs/ui/utils/sessionHelpers.js +0 -2
- package/lib/commonjs/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/commonjs/utils/languageUtils.js +11 -11
- package/lib/commonjs/utils/languageUtils.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.security.js +42 -0
- package/lib/module/core/mixins/OxyServices.security.js.map +1 -1
- package/lib/module/crypto/index.js +2 -3
- package/lib/module/crypto/index.js.map +1 -1
- package/lib/module/crypto/keyManager.js +2 -2
- package/lib/module/crypto/polyfill.js +4 -4
- package/lib/module/i18n/locales/en-US.json +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/interfaces.js +2 -0
- package/lib/module/models/interfaces.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +19 -1
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +1 -29
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/Section.js +2 -1
- package/lib/module/ui/components/Section.js.map +1 -1
- package/lib/module/ui/components/SectionTitle.js +1 -2
- package/lib/module/ui/components/SectionTitle.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileViewer.js +3 -3
- package/lib/module/ui/components/fileManagement/FileViewer.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +62 -10
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +65 -18
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useDeviceManagement.js +1 -1
- package/lib/module/ui/context/hooks/useDeviceManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js +1 -1
- package/lib/module/ui/context/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useSessionManagement.js +3 -3
- package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/context/hooks/useStorage.js +2 -2
- package/lib/module/ui/context/hooks/useStorage.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js +1 -1
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
- package/lib/module/ui/hooks/useIdentityMutations.js +4 -4
- package/lib/module/ui/hooks/useIdentityMutations.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +22 -7
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +13 -13
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +17 -17
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +2 -2
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +11 -10
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +15 -15
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +1 -1
- package/lib/module/ui/screens/HelpSupportScreen.js +3 -3
- package/lib/module/ui/screens/HelpSupportScreen.js.map +1 -1
- package/lib/module/ui/screens/HistoryViewScreen.js +2 -2
- package/lib/module/ui/screens/HistoryViewScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +4 -2
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/LegalDocumentsScreen.js +4 -4
- package/lib/module/ui/screens/LegalDocumentsScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js +1 -2
- package/lib/module/ui/screens/PremiumSubscriptionScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +44 -16
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/SavesCollectionsScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js +3 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -3
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -6
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/module/ui/utils/errorHandlers.js +46 -0
- package/lib/module/ui/utils/errorHandlers.js.map +1 -1
- package/lib/module/ui/utils/sessionHelpers.js +0 -2
- package/lib/module/ui/utils/sessionHelpers.js.map +1 -1
- package/lib/module/utils/languageUtils.js +11 -11
- package/lib/module/utils/languageUtils.js.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.security.d.ts +12 -0
- package/lib/typescript/core/mixins/OxyServices.security.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +2 -0
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/crypto/index.d.ts +1 -2
- package/lib/typescript/crypto/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts +2 -2
- package/lib/typescript/crypto/polyfill.d.ts +2 -2
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +1 -1
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
- package/lib/typescript/ui/components/Section.d.ts.map +1 -1
- package/lib/typescript/ui/components/SectionTitle.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +6 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +8 -4
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts +1 -1
- package/lib/typescript/ui/context/hooks/useStorage.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useIdentityMutations.d.ts +15 -3
- package/lib/typescript/ui/hooks/useIdentityMutations.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PremiumSubscriptionScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SavesCollectionsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/utils/errorHandlers.d.ts +5 -0
- package/lib/typescript/ui/utils/errorHandlers.d.ts.map +1 -1
- package/lib/typescript/ui/utils/sessionHelpers.d.ts.map +1 -1
- package/package.json +1 -2
- package/src/core/mixins/OxyServices.security.ts +44 -0
- package/src/crypto/index.ts +2 -6
- package/src/crypto/keyManager.ts +2 -2
- package/src/crypto/polyfill.ts +4 -4
- package/src/i18n/locales/en-US.json +1 -1
- package/src/index.ts +2 -4
- package/src/models/interfaces.ts +4 -0
- package/src/ui/components/FollowButton.tsx +19 -1
- package/src/ui/components/GroupedItem.tsx +1 -29
- package/src/ui/components/Section.tsx +1 -0
- package/src/ui/components/SectionTitle.tsx +0 -1
- package/src/ui/components/fileManagement/FileViewer.tsx +3 -3
- package/src/ui/context/OxyContext.tsx +53 -14
- package/src/ui/context/hooks/useAuthOperations.ts +83 -26
- package/src/ui/context/hooks/useDeviceManagement.ts +1 -1
- package/src/ui/context/hooks/useLanguageManagement.ts +2 -2
- package/src/ui/context/hooks/useSessionManagement.ts +3 -3
- package/src/ui/context/hooks/useStorage.ts +2 -2
- package/src/ui/hooks/queries/useAccountQueries.ts +1 -1
- package/src/ui/hooks/queries/useServicesQueries.ts +1 -1
- package/src/ui/hooks/useIdentityMutations.ts +6 -6
- package/src/ui/hooks/useSessionSocket.ts +8 -7
- package/src/ui/screens/AccountCenterScreen.tsx +13 -13
- package/src/ui/screens/AccountOverviewScreen.tsx +17 -17
- package/src/ui/screens/AccountSettingsScreen.tsx +2 -2
- package/src/ui/screens/AccountSwitcherScreen.tsx +8 -8
- package/src/ui/screens/AppInfoScreen.tsx +15 -15
- package/src/ui/screens/FeedbackScreen.tsx +1 -1
- package/src/ui/screens/FileManagementScreen.tsx +1 -1
- package/src/ui/screens/HelpSupportScreen.tsx +3 -3
- package/src/ui/screens/HistoryViewScreen.tsx +2 -2
- package/src/ui/screens/LanguageSelectorScreen.tsx +4 -1
- package/src/ui/screens/LegalDocumentsScreen.tsx +4 -4
- package/src/ui/screens/PaymentGatewayScreen.tsx +1 -1
- package/src/ui/screens/PremiumSubscriptionScreen.tsx +0 -1
- package/src/ui/screens/ProfileScreen.tsx +61 -22
- package/src/ui/screens/SavesCollectionsScreen.tsx +10 -1
- package/src/ui/screens/karma/KarmaAboutScreen.tsx +8 -1
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +2 -2
- package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -6
- package/src/ui/utils/errorHandlers.ts +58 -0
- package/src/ui/utils/sessionHelpers.ts +0 -2
- package/src/utils/languageUtils.ts +11 -11
- package/lib/commonjs/crypto/recoveryPhrase.js +0 -152
- package/lib/commonjs/crypto/recoveryPhrase.js.map +0 -1
- package/lib/commonjs/ui/context/utils/errorHandlers.js +0 -100
- package/lib/commonjs/ui/context/utils/errorHandlers.js.map +0 -1
- package/lib/commonjs/ui/context/utils/sessionHelpers.js +0 -103
- package/lib/commonjs/ui/context/utils/sessionHelpers.js.map +0 -1
- package/lib/commonjs/ui/context/utils/storageHelpers.js +0 -119
- package/lib/commonjs/ui/context/utils/storageHelpers.js.map +0 -1
- package/lib/module/crypto/recoveryPhrase.js +0 -147
- package/lib/module/crypto/recoveryPhrase.js.map +0 -1
- package/lib/module/ui/context/utils/errorHandlers.js +0 -93
- package/lib/module/ui/context/utils/errorHandlers.js.map +0 -1
- package/lib/module/ui/context/utils/sessionHelpers.js +0 -96
- package/lib/module/ui/context/utils/sessionHelpers.js.map +0 -1
- package/lib/module/ui/context/utils/storageHelpers.js +0 -111
- package/lib/module/ui/context/utils/storageHelpers.js.map +0 -1
- package/lib/typescript/crypto/recoveryPhrase.d.ts +0 -59
- package/lib/typescript/crypto/recoveryPhrase.d.ts.map +0 -1
- package/lib/typescript/ui/context/utils/errorHandlers.d.ts +0 -30
- package/lib/typescript/ui/context/utils/errorHandlers.d.ts.map +0 -1
- package/lib/typescript/ui/context/utils/sessionHelpers.d.ts +0 -59
- package/lib/typescript/ui/context/utils/sessionHelpers.d.ts.map +0 -1
- package/lib/typescript/ui/context/utils/storageHelpers.d.ts +0 -31
- package/lib/typescript/ui/context/utils/storageHelpers.d.ts.map +0 -1
- package/src/crypto/recoveryPhrase.ts +0 -166
- package/src/ui/context/utils/errorHandlers.ts +0 -146
- package/src/ui/context/utils/sessionHelpers.ts +0 -146
- package/src/ui/context/utils/storageHelpers.ts +0 -134
|
@@ -3,11 +3,11 @@ import type { ApiError, User } from '../../../models/interfaces';
|
|
|
3
3
|
import type { AuthState } from '../../stores/authStore';
|
|
4
4
|
import type { ClientSession, SessionLoginResponse } from '../../../models/session';
|
|
5
5
|
import { DeviceManager } from '../../../utils/deviceManager';
|
|
6
|
-
import { fetchSessionsWithFallback, mapSessionsToClient } from '
|
|
7
|
-
import { handleAuthError, isInvalidSessionError } from '
|
|
8
|
-
import type { StorageInterface } from '
|
|
6
|
+
import { fetchSessionsWithFallback, mapSessionsToClient } from '../../utils/sessionHelpers';
|
|
7
|
+
import { handleAuthError, isInvalidSessionError } from '../../utils/errorHandlers';
|
|
8
|
+
import type { StorageInterface } from '../../utils/storageHelpers';
|
|
9
9
|
import type { OxyServices } from '../../../core';
|
|
10
|
-
import { KeyManager, SignatureService
|
|
10
|
+
import { KeyManager, SignatureService } from '../../../crypto';
|
|
11
11
|
|
|
12
12
|
export interface UseAuthOperationsOptions {
|
|
13
13
|
oxyServices: OxyServices;
|
|
@@ -34,9 +34,9 @@ export interface UseAuthOperationsOptions {
|
|
|
34
34
|
|
|
35
35
|
export interface UseAuthOperationsResult {
|
|
36
36
|
/** Create a new identity locally (offline-first) and optionally sync with server */
|
|
37
|
-
createIdentity: () => Promise<{
|
|
38
|
-
/** Import an existing identity from
|
|
39
|
-
importIdentity: (
|
|
37
|
+
createIdentity: () => Promise<{ synced: boolean }>;
|
|
38
|
+
/** Import an existing identity from backup file data */
|
|
39
|
+
importIdentity: (backupData: { encrypted: string; salt: string; iv: string; publicKey: string }, password: string) => Promise<{ synced: boolean }>;
|
|
40
40
|
/** Sign in with existing identity on device */
|
|
41
41
|
signIn: (deviceName?: string) => Promise<User>;
|
|
42
42
|
/** Logout from current session */
|
|
@@ -274,18 +274,19 @@ export const useAuthOperations = ({
|
|
|
274
274
|
);
|
|
275
275
|
|
|
276
276
|
/**
|
|
277
|
-
* Create a new identity
|
|
277
|
+
* Create a new identity (offline-first)
|
|
278
278
|
* Identity is purely cryptographic - no username or email required
|
|
279
279
|
*/
|
|
280
280
|
const createIdentity = useCallback(
|
|
281
|
-
async (): Promise<{
|
|
281
|
+
async (): Promise<{ synced: boolean }> => {
|
|
282
282
|
if (!storage) throw new Error('Storage not initialized');
|
|
283
283
|
|
|
284
284
|
setAuthState({ isLoading: true, error: null });
|
|
285
285
|
|
|
286
286
|
try {
|
|
287
|
-
// Generate new
|
|
288
|
-
const {
|
|
287
|
+
// Generate new key pair directly (works offline)
|
|
288
|
+
const { publicKey, privateKey } = await KeyManager.generateKeyPair();
|
|
289
|
+
await KeyManager.importKeyPair(privateKey);
|
|
289
290
|
|
|
290
291
|
// Mark as not synced
|
|
291
292
|
await storage.setItem('oxy_identity_synced', 'false');
|
|
@@ -301,7 +302,6 @@ export const useAuthOperations = ({
|
|
|
301
302
|
setIdentitySynced(true);
|
|
302
303
|
|
|
303
304
|
return {
|
|
304
|
-
recoveryPhrase: words,
|
|
305
305
|
synced: true,
|
|
306
306
|
};
|
|
307
307
|
} catch (syncError) {
|
|
@@ -311,13 +311,12 @@ export const useAuthOperations = ({
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
return {
|
|
314
|
-
recoveryPhrase: words,
|
|
315
314
|
synced: false,
|
|
316
315
|
};
|
|
317
316
|
}
|
|
318
317
|
} catch (error) {
|
|
319
318
|
// CRITICAL: Never delete identity on error - it may have been successfully created
|
|
320
|
-
// Only log the error and let the user recover using their
|
|
319
|
+
// Only log the error and let the user recover using their backup file
|
|
321
320
|
// Identity deletion should ONLY happen when explicitly requested by the user
|
|
322
321
|
if (__DEV__ && logger) {
|
|
323
322
|
logger('Error during identity creation (identity may still exist):', error);
|
|
@@ -330,7 +329,7 @@ export const useAuthOperations = ({
|
|
|
330
329
|
await storage.setItem('oxy_identity_synced', 'false').catch(() => {});
|
|
331
330
|
setIdentitySynced(false);
|
|
332
331
|
if (__DEV__ && logger) {
|
|
333
|
-
logger('Identity was created but sync failed - user can sync later using
|
|
332
|
+
logger('Identity was created but sync failed - user can sync later using backup file');
|
|
334
333
|
}
|
|
335
334
|
} else {
|
|
336
335
|
// No identity exists - this was a generation failure, safe to clean up sync flag
|
|
@@ -342,7 +341,7 @@ export const useAuthOperations = ({
|
|
|
342
341
|
defaultMessage: 'Failed to create identity',
|
|
343
342
|
code: REGISTER_ERROR_CODE,
|
|
344
343
|
onError,
|
|
345
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
344
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
346
345
|
logger,
|
|
347
346
|
});
|
|
348
347
|
loginFailure(message);
|
|
@@ -405,6 +404,13 @@ export const useAuthOperations = ({
|
|
|
405
404
|
// Sign in
|
|
406
405
|
const user = await performSignIn(publicKey);
|
|
407
406
|
|
|
407
|
+
// Check if user has username - required for syncing
|
|
408
|
+
if (!user.username) {
|
|
409
|
+
const usernameError = new Error('USERNAME_REQUIRED');
|
|
410
|
+
(usernameError as any).code = 'USERNAME_REQUIRED';
|
|
411
|
+
throw usernameError;
|
|
412
|
+
}
|
|
413
|
+
|
|
408
414
|
// TanStack Query will automatically retry any pending mutations
|
|
409
415
|
|
|
410
416
|
return user;
|
|
@@ -413,7 +419,7 @@ export const useAuthOperations = ({
|
|
|
413
419
|
defaultMessage: 'Failed to sync identity',
|
|
414
420
|
code: REGISTER_ERROR_CODE,
|
|
415
421
|
onError,
|
|
416
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
422
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
417
423
|
logger,
|
|
418
424
|
});
|
|
419
425
|
loginFailure(message);
|
|
@@ -427,17 +433,68 @@ export const useAuthOperations = ({
|
|
|
427
433
|
);
|
|
428
434
|
|
|
429
435
|
/**
|
|
430
|
-
* Import identity from
|
|
436
|
+
* Import identity from backup file data (offline-first)
|
|
431
437
|
*/
|
|
432
438
|
const importIdentity = useCallback(
|
|
433
|
-
async (
|
|
439
|
+
async (backupData: { encrypted: string; salt: string; iv: string; publicKey: string }, password: string): Promise<{ synced: boolean }> => {
|
|
434
440
|
if (!storage) throw new Error('Storage not initialized');
|
|
435
441
|
|
|
442
|
+
// Validate arguments - ensure backupData is an object, not a string (old signature)
|
|
443
|
+
if (!backupData || typeof backupData !== 'object' || Array.isArray(backupData)) {
|
|
444
|
+
throw new Error('Invalid backup data. Please use the backup file import feature.');
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
if (!backupData.encrypted || !backupData.salt || !backupData.iv || !backupData.publicKey) {
|
|
448
|
+
throw new Error('Invalid backup data structure. Missing required fields.');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (!password || typeof password !== 'string') {
|
|
452
|
+
throw new Error('Password is required for backup file import.');
|
|
453
|
+
}
|
|
454
|
+
|
|
436
455
|
setAuthState({ isLoading: true, error: null });
|
|
437
456
|
|
|
438
457
|
try {
|
|
439
|
-
//
|
|
440
|
-
const
|
|
458
|
+
// Decrypt private key from backup data
|
|
459
|
+
const Crypto = await import('expo-crypto');
|
|
460
|
+
|
|
461
|
+
// Convert hex strings to Uint8Array
|
|
462
|
+
const saltBytes = new Uint8Array(
|
|
463
|
+
backupData.salt.match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || []
|
|
464
|
+
);
|
|
465
|
+
const ivBytes = new Uint8Array(
|
|
466
|
+
backupData.iv.match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || []
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
// Derive key from password (same algorithm as EncryptedBackupGenerator)
|
|
470
|
+
const saltHex = Array.from(saltBytes).map(b => b.toString(16).padStart(2, '0')).join('');
|
|
471
|
+
let key = password + saltHex;
|
|
472
|
+
for (let i = 0; i < 10000; i++) {
|
|
473
|
+
key = await Crypto.digestStringAsync(
|
|
474
|
+
Crypto.CryptoDigestAlgorithm.SHA256,
|
|
475
|
+
key
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
const keyBytes = new Uint8Array(32);
|
|
479
|
+
for (let i = 0; i < 64 && i < key.length; i += 2) {
|
|
480
|
+
keyBytes[i / 2] = parseInt(key.substring(i, i + 2), 16);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// Decrypt private key (XOR decryption - same as encryption)
|
|
484
|
+
const encryptedBytes = Buffer.from(backupData.encrypted, 'base64');
|
|
485
|
+
const decryptedBytes = new Uint8Array(encryptedBytes.length);
|
|
486
|
+
for (let i = 0; i < encryptedBytes.length; i++) {
|
|
487
|
+
decryptedBytes[i] = encryptedBytes[i] ^ keyBytes[i % keyBytes.length] ^ ivBytes[i % ivBytes.length];
|
|
488
|
+
}
|
|
489
|
+
const privateKey = new TextDecoder().decode(decryptedBytes);
|
|
490
|
+
|
|
491
|
+
// Import the key pair
|
|
492
|
+
const publicKey = await KeyManager.importKeyPair(privateKey);
|
|
493
|
+
|
|
494
|
+
// Verify public key matches
|
|
495
|
+
if (publicKey !== backupData.publicKey) {
|
|
496
|
+
throw new Error('Backup file is corrupted or password is incorrect');
|
|
497
|
+
}
|
|
441
498
|
|
|
442
499
|
// Mark as not synced
|
|
443
500
|
await storage.setItem('oxy_identity_synced', 'false');
|
|
@@ -471,10 +528,10 @@ export const useAuthOperations = ({
|
|
|
471
528
|
}
|
|
472
529
|
} catch (error) {
|
|
473
530
|
const message = handleAuthError(error, {
|
|
474
|
-
defaultMessage: 'Failed to import identity',
|
|
531
|
+
defaultMessage: 'Failed to import identity. Please check your password and backup file.',
|
|
475
532
|
code: REGISTER_ERROR_CODE,
|
|
476
533
|
onError,
|
|
477
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
534
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
478
535
|
logger,
|
|
479
536
|
});
|
|
480
537
|
loginFailure(message);
|
|
@@ -508,7 +565,7 @@ export const useAuthOperations = ({
|
|
|
508
565
|
defaultMessage: 'Sign in failed',
|
|
509
566
|
code: LOGIN_ERROR_CODE,
|
|
510
567
|
onError,
|
|
511
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
568
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
512
569
|
logger,
|
|
513
570
|
});
|
|
514
571
|
loginFailure(message);
|
|
@@ -554,7 +611,7 @@ export const useAuthOperations = ({
|
|
|
554
611
|
defaultMessage: 'Logout failed',
|
|
555
612
|
code: LOGOUT_ERROR_CODE,
|
|
556
613
|
onError,
|
|
557
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
614
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
558
615
|
logger,
|
|
559
616
|
status: isInvalid ? 401 : undefined,
|
|
560
617
|
});
|
|
@@ -592,7 +649,7 @@ export const useAuthOperations = ({
|
|
|
592
649
|
defaultMessage: 'Logout all failed',
|
|
593
650
|
code: LOGOUT_ALL_ERROR_CODE,
|
|
594
651
|
onError,
|
|
595
|
-
setAuthError: (msg) => setAuthState({ error: msg }),
|
|
652
|
+
setAuthError: (msg: string) => setAuthState({ error: msg }),
|
|
596
653
|
logger,
|
|
597
654
|
});
|
|
598
655
|
throw error instanceof Error ? error : new Error('Logout all failed');
|
|
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
|
|
|
2
2
|
import type { ApiError } from '../../../models/interfaces';
|
|
3
3
|
import { DeviceManager } from '../../../utils/deviceManager';
|
|
4
4
|
import type { OxyServices } from '../../../core';
|
|
5
|
-
import { handleAuthError } from '
|
|
5
|
+
import { handleAuthError } from '../../utils/errorHandlers';
|
|
6
6
|
|
|
7
7
|
export interface UseDeviceManagementOptions {
|
|
8
8
|
oxyServices: OxyServices;
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
normalizeLanguageCode,
|
|
8
8
|
type LanguageMetadata,
|
|
9
9
|
} from '../../../utils/languageUtils';
|
|
10
|
-
import type { StorageInterface } from '
|
|
11
|
-
import { extractErrorMessage } from '
|
|
10
|
+
import type { StorageInterface } from '../../utils/storageHelpers';
|
|
11
|
+
import { extractErrorMessage } from '../../utils/errorHandlers';
|
|
12
12
|
|
|
13
13
|
export interface UseLanguageManagementOptions {
|
|
14
14
|
storage: StorageInterface | null;
|
|
@@ -2,9 +2,9 @@ import { useCallback, useMemo, useRef, useState } from 'react';
|
|
|
2
2
|
import type { ApiError, User } from '../../../models/interfaces';
|
|
3
3
|
import type { ClientSession } from '../../../models/session';
|
|
4
4
|
import { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual } from '../../../utils/sessionUtils';
|
|
5
|
-
import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch } from '
|
|
6
|
-
import { getStorageKeys, type StorageInterface } from '
|
|
7
|
-
import { handleAuthError, isInvalidSessionError } from '
|
|
5
|
+
import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch } from '../../utils/sessionHelpers';
|
|
6
|
+
import { getStorageKeys, type StorageInterface } from '../../utils/storageHelpers';
|
|
7
|
+
import { handleAuthError, isInvalidSessionError } from '../../utils/errorHandlers';
|
|
8
8
|
import type { OxyServices } from '../../../core';
|
|
9
9
|
import type { QueryClient } from '@tanstack/react-query';
|
|
10
10
|
import { clearQueryCache } from '../../hooks/queryClient';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import type { ApiError } from '../../../models/interfaces';
|
|
3
|
-
import { createPlatformStorage, type StorageInterface } from '
|
|
4
|
-
import { extractErrorMessage } from '
|
|
3
|
+
import { createPlatformStorage, type StorageInterface } from '../../utils/storageHelpers';
|
|
4
|
+
import { extractErrorMessage } from '../../utils/errorHandlers';
|
|
5
5
|
|
|
6
6
|
export interface UseStorageOptions {
|
|
7
7
|
onError?: (error: ApiError) => void;
|
|
@@ -132,7 +132,7 @@ export const usePrivacySettings = (userId?: string, options?: { enabled?: boolea
|
|
|
132
132
|
const targetUserId = userId || user?.id;
|
|
133
133
|
|
|
134
134
|
return useQuery({
|
|
135
|
-
queryKey: queryKeys.privacy.settings(
|
|
135
|
+
queryKey: queryKeys.privacy.settings(targetUserId),
|
|
136
136
|
queryFn: async () => {
|
|
137
137
|
if (!targetUserId) {
|
|
138
138
|
throw new Error('User ID is required');
|
|
@@ -2,7 +2,7 @@ import { useQuery } from '@tanstack/react-query';
|
|
|
2
2
|
import type { ClientSession } from '../../../models/session';
|
|
3
3
|
import { queryKeys } from './queryKeys';
|
|
4
4
|
import { useOxy } from '../../context/OxyContext';
|
|
5
|
-
import { fetchSessionsWithFallback, mapSessionsToClient } from '../../
|
|
5
|
+
import { fetchSessionsWithFallback, mapSessionsToClient } from '../../utils/sessionHelpers';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Get all active sessions for the current user
|
|
@@ -8,7 +8,6 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
|
8
8
|
import type { User } from '../../models/interfaces';
|
|
9
9
|
|
|
10
10
|
export interface CreateIdentityResult {
|
|
11
|
-
recoveryPhrase: string[];
|
|
12
11
|
synced: boolean;
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -34,7 +33,7 @@ export function useCreateIdentity(
|
|
|
34
33
|
},
|
|
35
34
|
onError: (error) => {
|
|
36
35
|
// Never delete identity on error - just log it
|
|
37
|
-
// User can recover using
|
|
36
|
+
// User can recover using backup file
|
|
38
37
|
if (__DEV__) {
|
|
39
38
|
console.warn('[useCreateIdentity] Identity creation error (identity may still exist):', error);
|
|
40
39
|
}
|
|
@@ -45,16 +44,17 @@ export function useCreateIdentity(
|
|
|
45
44
|
}
|
|
46
45
|
|
|
47
46
|
/**
|
|
48
|
-
* Hook for importing an identity from
|
|
47
|
+
* Hook for importing an identity from backup file
|
|
49
48
|
* Never deletes identity on error - preserves user data
|
|
50
49
|
*/
|
|
51
50
|
export function useImportIdentity(
|
|
52
|
-
importIdentityFn: (
|
|
51
|
+
importIdentityFn: (backupData: { encrypted: string; salt: string; iv: string; publicKey: string }, password: string) => Promise<ImportIdentityResult>
|
|
53
52
|
) {
|
|
54
53
|
const queryClient = useQueryClient();
|
|
55
54
|
|
|
56
55
|
return useMutation({
|
|
57
|
-
mutationFn:
|
|
56
|
+
mutationFn: (variables: { backupData: { encrypted: string; salt: string; iv: string; publicKey: string }; password: string }) =>
|
|
57
|
+
importIdentityFn(variables.backupData, variables.password),
|
|
58
58
|
onSuccess: (data) => {
|
|
59
59
|
queryClient.invalidateQueries({ queryKey: ['user'] });
|
|
60
60
|
queryClient.invalidateQueries({ queryKey: ['identity'] });
|
|
@@ -89,7 +89,7 @@ export function useSyncIdentity(
|
|
|
89
89
|
},
|
|
90
90
|
onError: (error) => {
|
|
91
91
|
// Never delete identity on error - just log it
|
|
92
|
-
// User can retry sync later or use
|
|
92
|
+
// User can retry sync later or use backup file
|
|
93
93
|
if (__DEV__) {
|
|
94
94
|
console.warn('[useSyncIdentity] Sync failed, but identity is preserved:', error);
|
|
95
95
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef } from 'react';
|
|
2
2
|
import io from 'socket.io-client';
|
|
3
3
|
import { toast } from '../../lib/sonner';
|
|
4
|
+
import { logger } from '../../utils/loggerUtils';
|
|
4
5
|
|
|
5
6
|
interface UseSessionSocketProps {
|
|
6
7
|
userId: string | null | undefined;
|
|
@@ -113,7 +114,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
113
114
|
await clearSessionStateRef.current();
|
|
114
115
|
} catch (error) {
|
|
115
116
|
if (__DEV__) {
|
|
116
|
-
|
|
117
|
+
logger.error('Failed to clear session state after session_removed', error instanceof Error ? error : new Error(String(error)), { component: 'useSessionSocket' });
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
} else {
|
|
@@ -121,7 +122,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
121
122
|
refreshSessionsRef.current().catch((error) => {
|
|
122
123
|
// Silently handle errors from refresh - they're expected if sessions were removed
|
|
123
124
|
if (__DEV__) {
|
|
124
|
-
|
|
125
|
+
logger.debug('Failed to refresh sessions after session_removed', { component: 'useSessionSocket' }, error as unknown);
|
|
125
126
|
}
|
|
126
127
|
});
|
|
127
128
|
}
|
|
@@ -146,7 +147,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
146
147
|
await clearSessionStateRef.current();
|
|
147
148
|
} catch (error) {
|
|
148
149
|
if (__DEV__) {
|
|
149
|
-
|
|
150
|
+
logger.error('Failed to clear session state after device_removed', error instanceof Error ? error : new Error(String(error)), { component: 'useSessionSocket' });
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
} else {
|
|
@@ -154,7 +155,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
154
155
|
refreshSessionsRef.current().catch((error) => {
|
|
155
156
|
// Silently handle errors from refresh - they're expected if sessions were removed
|
|
156
157
|
if (__DEV__) {
|
|
157
|
-
|
|
158
|
+
logger.debug('Failed to refresh sessions after device_removed', { component: 'useSessionSocket' }, error as unknown);
|
|
158
159
|
}
|
|
159
160
|
});
|
|
160
161
|
}
|
|
@@ -179,7 +180,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
179
180
|
await clearSessionStateRef.current();
|
|
180
181
|
} catch (error) {
|
|
181
182
|
if (__DEV__) {
|
|
182
|
-
|
|
183
|
+
logger.error('Failed to clear session state after sessions_removed', error instanceof Error ? error : new Error(String(error)), { component: 'useSessionSocket' });
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
} else {
|
|
@@ -187,7 +188,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
187
188
|
refreshSessionsRef.current().catch((error) => {
|
|
188
189
|
// Silently handle errors from refresh - they're expected if sessions were removed
|
|
189
190
|
if (__DEV__) {
|
|
190
|
-
|
|
191
|
+
logger.debug('Failed to refresh sessions after sessions_removed', { component: 'useSessionSocket' }, error as unknown);
|
|
191
192
|
}
|
|
192
193
|
});
|
|
193
194
|
}
|
|
@@ -196,7 +197,7 @@ export function useSessionSocket({ userId, activeSessionId, currentDeviceId, ref
|
|
|
196
197
|
refreshSessionsRef.current().catch((error) => {
|
|
197
198
|
// Log but don't throw - refresh errors shouldn't break the socket handler
|
|
198
199
|
if (__DEV__) {
|
|
199
|
-
|
|
200
|
+
logger.debug('Failed to refresh sessions after session_update', { component: 'useSessionSocket' }, error as unknown);
|
|
200
201
|
}
|
|
201
202
|
});
|
|
202
203
|
|
|
@@ -102,9 +102,9 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
102
102
|
<QuickActions
|
|
103
103
|
theme={normalizedTheme}
|
|
104
104
|
actions={useMemo(() => [
|
|
105
|
-
{ id: 'overview', icon: '
|
|
106
|
-
{ id: 'settings', icon: '
|
|
107
|
-
{ id: 'sessions', icon: 'shield-
|
|
105
|
+
{ id: 'overview', icon: 'account-circle', iconColor: colors.iconSecurity, title: t('accountCenter.quickActions.overview') || 'Overview', onPress: () => navigate?.('AccountOverview') },
|
|
106
|
+
{ id: 'settings', icon: 'cog', iconColor: colors.iconData, title: t('accountCenter.quickActions.editProfile') || 'Edit Profile', onPress: () => navigate?.('EditProfile') },
|
|
107
|
+
{ id: 'sessions', icon: 'shield-check', iconColor: colors.iconSecurity, title: t('accountCenter.quickActions.sessions') || 'Sessions', onPress: () => navigate?.('SessionManagement') },
|
|
108
108
|
{ id: 'premium', icon: 'star', iconColor: colors.iconPayments, title: t('accountCenter.quickActions.premium') || 'Premium', onPress: () => navigate?.('PremiumSubscription') },
|
|
109
109
|
...(user?.isPremium ? [{ id: 'billing', icon: 'card', iconColor: colors.iconPersonalInfo, title: t('accountCenter.quickActions.billing') || 'Billing', onPress: () => navigate?.('PaymentGateway') }] : []),
|
|
110
110
|
...(sessions && sessions.length > 1 ? [{ id: 'switch', icon: 'swap-horizontal', iconColor: colors.iconStorage, title: t('accountCenter.quickActions.switch') || 'Switch', onPress: () => navigate?.('AccountSwitcher') }] : []),
|
|
@@ -119,7 +119,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
119
119
|
items={useMemo(() => [
|
|
120
120
|
{
|
|
121
121
|
id: 'overview',
|
|
122
|
-
icon: '
|
|
122
|
+
icon: 'account-circle',
|
|
123
123
|
iconColor: colors.iconSecurity,
|
|
124
124
|
title: t('accountCenter.items.accountOverview.title') || 'Account Overview',
|
|
125
125
|
subtitle: t('accountCenter.items.accountOverview.subtitle') || 'Complete account information',
|
|
@@ -127,7 +127,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
127
127
|
},
|
|
128
128
|
{
|
|
129
129
|
id: 'settings',
|
|
130
|
-
icon: '
|
|
130
|
+
icon: 'cog',
|
|
131
131
|
iconColor: colors.iconData,
|
|
132
132
|
title: t('accountCenter.items.editProfile.title') || 'Edit Profile',
|
|
133
133
|
subtitle: t('accountCenter.items.editProfile.subtitle') || 'Manage your profile and preferences',
|
|
@@ -135,7 +135,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
135
135
|
},
|
|
136
136
|
{
|
|
137
137
|
id: 'sessions',
|
|
138
|
-
icon: 'shield-
|
|
138
|
+
icon: 'shield-check',
|
|
139
139
|
iconColor: colors.iconSecurity,
|
|
140
140
|
title: t('accountCenter.items.manageSessions.title') || 'Manage Sessions',
|
|
141
141
|
subtitle: t('accountCenter.items.manageSessions.subtitle') || 'Security and active devices',
|
|
@@ -177,7 +177,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
177
177
|
items={useMemo(() => [
|
|
178
178
|
{
|
|
179
179
|
id: 'switch',
|
|
180
|
-
icon: '
|
|
180
|
+
icon: 'account-group',
|
|
181
181
|
iconColor: colors.iconStorage,
|
|
182
182
|
title: t('accountCenter.items.switchAccount.title') || 'Switch Account',
|
|
183
183
|
subtitle: t('accountCenter.items.switchAccount.subtitle', { count: sessions.length }) || `${sessions.length} accounts available`,
|
|
@@ -185,7 +185,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
id: 'add',
|
|
188
|
-
icon: '
|
|
188
|
+
icon: 'account-plus',
|
|
189
189
|
iconColor: colors.iconPersonalInfo,
|
|
190
190
|
title: t('accountCenter.items.addAccount.title') || 'Add Another Account',
|
|
191
191
|
subtitle: t('accountCenter.items.addAccount.subtitle') || 'Sign in with a different account',
|
|
@@ -204,7 +204,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
204
204
|
items={useMemo(() => [
|
|
205
205
|
{
|
|
206
206
|
id: 'add',
|
|
207
|
-
icon: '
|
|
207
|
+
icon: 'account-plus',
|
|
208
208
|
iconColor: colors.iconPersonalInfo,
|
|
209
209
|
title: t('accountCenter.items.addAccount.title') || 'Add Another Account',
|
|
210
210
|
subtitle: t('accountCenter.items.addAccount.subtitle') || 'Sign in with a different account',
|
|
@@ -222,7 +222,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
222
222
|
items={useMemo(() => [
|
|
223
223
|
...(Platform.OS !== 'web' ? [{
|
|
224
224
|
id: 'notifications',
|
|
225
|
-
icon: '
|
|
225
|
+
icon: 'bell',
|
|
226
226
|
iconColor: colors.iconStorage,
|
|
227
227
|
title: t('accountCenter.items.notifications.title') || 'Notifications',
|
|
228
228
|
subtitle: t('accountCenter.items.notifications.subtitle') || 'Manage notification settings',
|
|
@@ -230,7 +230,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
230
230
|
}] : []),
|
|
231
231
|
{
|
|
232
232
|
id: 'language',
|
|
233
|
-
icon: '
|
|
233
|
+
icon: 'translate',
|
|
234
234
|
iconColor: colors.iconPersonalInfo,
|
|
235
235
|
title: t('language.title') || 'Language',
|
|
236
236
|
subtitle: t('language.subtitle') || 'Choose your preferred language',
|
|
@@ -246,7 +246,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
246
246
|
},
|
|
247
247
|
{
|
|
248
248
|
id: 'appinfo',
|
|
249
|
-
icon: 'information
|
|
249
|
+
icon: 'information',
|
|
250
250
|
iconColor: '#8E8E93',
|
|
251
251
|
title: t('accountCenter.items.appInfo.title') || 'App Information',
|
|
252
252
|
subtitle: t('accountCenter.items.appInfo.subtitle') || 'Version and system details',
|
|
@@ -260,7 +260,7 @@ const AccountCenterScreen: React.FC<BaseScreenProps> = ({
|
|
|
260
260
|
{/* Sign Out Section */}
|
|
261
261
|
<Section >
|
|
262
262
|
<GroupedItem
|
|
263
|
-
icon="
|
|
263
|
+
icon="logout"
|
|
264
264
|
iconColor={dangerColor}
|
|
265
265
|
title={isLoading ? (t('accountCenter.signingOut') || 'Signing out...') : (t('common.actions.signOut') || 'Sign Out')}
|
|
266
266
|
|