@oxyhq/services 5.16.0 → 5.16.2
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/core/mixins/OxyServices.assets.js +15 -0
- package/lib/commonjs/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/commonjs/core/mixins/OxyServices.user.js +14 -13
- package/lib/commonjs/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/commonjs/crypto/keyManager.js +164 -3
- package/lib/commonjs/crypto/keyManager.js.map +1 -1
- package/lib/commonjs/crypto/signatureService.js +26 -0
- package/lib/commonjs/crypto/signatureService.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedSection.js +1 -1
- package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +71 -24
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/profile/EditDisplayNameModal.js +1 -4
- package/lib/commonjs/ui/components/profile/EditDisplayNameModal.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +177 -4
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +148 -49
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js +22 -2
- package/lib/commonjs/ui/context/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/index.js +28 -0
- package/lib/commonjs/ui/hooks/mutations/index.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +314 -0
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -0
- package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js +193 -0
- package/lib/commonjs/ui/hooks/mutations/useServicesMutations.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/index.js +39 -0
- package/lib/commonjs/ui/hooks/queries/index.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/queryKeys.js +85 -0
- package/lib/commonjs/ui/hooks/queries/queryKeys.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +145 -0
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -0
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +138 -0
- package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -0
- package/lib/commonjs/ui/hooks/queryClient.js +117 -0
- package/lib/commonjs/ui/hooks/queryClient.js.map +1 -0
- package/lib/commonjs/ui/hooks/useIdentityMutations.js +111 -0
- package/lib/commonjs/ui/hooks/useIdentityMutations.js.map +1 -0
- package/lib/commonjs/ui/hooks/useProfileEditing.js +42 -58
- package/lib/commonjs/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/commonjs/ui/hooks/useQueryClient.js +20 -0
- package/lib/commonjs/ui/hooks/useQueryClient.js.map +1 -0
- package/lib/commonjs/ui/hooks/useSessionManagement.js +22 -2
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +43 -42
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +63 -58
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js +6 -6
- package/lib/commonjs/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/accountStore.js +57 -42
- package/lib/commonjs/ui/stores/accountStore.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +4 -25
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.assets.js +15 -0
- package/lib/module/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/module/core/mixins/OxyServices.user.js +14 -13
- package/lib/module/core/mixins/OxyServices.user.js.map +1 -1
- package/lib/module/crypto/keyManager.js +164 -3
- package/lib/module/crypto/keyManager.js.map +1 -1
- package/lib/module/crypto/signatureService.js +26 -0
- package/lib/module/crypto/signatureService.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +1 -1
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +72 -25
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/profile/EditDisplayNameModal.js +1 -4
- package/lib/module/ui/components/profile/EditDisplayNameModal.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +176 -4
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +148 -49
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/hooks/useSessionManagement.js +22 -2
- package/lib/module/ui/context/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/hooks/mutations/index.js +6 -0
- package/lib/module/ui/hooks/mutations/index.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +308 -0
- package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -0
- package/lib/module/ui/hooks/mutations/useServicesMutations.js +185 -0
- package/lib/module/ui/hooks/mutations/useServicesMutations.js.map +1 -0
- package/lib/module/ui/hooks/queries/index.js +7 -0
- package/lib/module/ui/hooks/queries/index.js.map +1 -0
- package/lib/module/ui/hooks/queries/queryKeys.js +78 -0
- package/lib/module/ui/hooks/queries/queryKeys.js.map +1 -0
- package/lib/module/ui/hooks/queries/useAccountQueries.js +136 -0
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -0
- package/lib/module/ui/hooks/queries/useServicesQueries.js +130 -0
- package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -0
- package/lib/module/ui/hooks/queryClient.js +110 -0
- package/lib/module/ui/hooks/queryClient.js.map +1 -0
- package/lib/module/ui/hooks/useIdentityMutations.js +105 -0
- package/lib/module/ui/hooks/useIdentityMutations.js.map +1 -0
- package/lib/module/ui/hooks/useProfileEditing.js +43 -59
- package/lib/module/ui/hooks/useProfileEditing.js.map +1 -1
- package/lib/module/ui/hooks/useQueryClient.js +15 -0
- package/lib/module/ui/hooks/useQueryClient.js.map +1 -0
- package/lib/module/ui/hooks/useSessionManagement.js +22 -2
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +43 -42
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +63 -58
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/WelcomeNewUserScreen.js +6 -6
- package/lib/module/ui/screens/WelcomeNewUserScreen.js.map +1 -1
- package/lib/module/ui/stores/accountStore.js +57 -42
- package/lib/module/ui/stores/accountStore.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +4 -25
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts +7 -1
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/OxyServices.user.d.ts +4 -5
- package/lib/typescript/core/mixins/OxyServices.user.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +1 -1
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/crypto/keyManager.d.ts +19 -2
- package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
- package/lib/typescript/crypto/signatureService.d.ts +5 -0
- package/lib/typescript/crypto/signatureService.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/interfaces.d.ts +21 -0
- package/lib/typescript/models/interfaces.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/profile/EditDisplayNameModal.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +4 -0
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts +3 -1
- package/lib/typescript/ui/context/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/mutations/index.d.ts +3 -0
- package/lib/typescript/ui/hooks/mutations/index.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts +25 -0
- package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts +23 -0
- package/lib/typescript/ui/hooks/mutations/useServicesMutations.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/queries/index.d.ts +4 -0
- package/lib/typescript/ui/hooks/queries/index.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/queries/queryKeys.d.ts +56 -0
- package/lib/typescript/ui/hooks/queries/queryKeys.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts +41 -0
- package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts +34 -0
- package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/queryClient.d.ts +19 -0
- package/lib/typescript/ui/hooks/queryClient.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useIdentityMutations.d.ts +29 -0
- package/lib/typescript/ui/hooks/useIdentityMutations.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useProfileEditing.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useQueryClient.d.ts +7 -0
- package/lib/typescript/ui/hooks/useQueryClient.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts +3 -1
- package/lib/typescript/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/WelcomeNewUserScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/accountStore.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +0 -4
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/core/mixins/OxyServices.assets.ts +16 -1
- package/src/core/mixins/OxyServices.user.ts +17 -10
- package/src/crypto/keyManager.ts +177 -2
- package/src/crypto/signatureService.ts +30 -0
- package/src/index.ts +4 -1
- package/src/models/interfaces.ts +23 -0
- package/src/ui/components/GroupedSection.tsx +1 -1
- package/src/ui/components/OxyProvider.tsx +91 -37
- package/src/ui/components/profile/EditDisplayNameModal.tsx +1 -3
- package/src/ui/context/OxyContext.tsx +185 -2
- package/src/ui/context/hooks/useAuthOperations.ts +171 -58
- package/src/ui/context/hooks/useSessionManagement.ts +24 -1
- package/src/ui/hooks/mutations/index.ts +4 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +277 -0
- package/src/ui/hooks/mutations/useServicesMutations.ts +164 -0
- package/src/ui/hooks/queries/index.ts +5 -0
- package/src/ui/hooks/queries/queryKeys.ts +73 -0
- package/src/ui/hooks/queries/useAccountQueries.ts +126 -0
- package/src/ui/hooks/queries/useServicesQueries.ts +121 -0
- package/src/ui/hooks/queryClient.ts +112 -0
- package/src/ui/hooks/useIdentityMutations.ts +115 -0
- package/src/ui/hooks/useProfileEditing.ts +46 -60
- package/src/ui/hooks/useQueryClient.ts +17 -0
- package/src/ui/hooks/useSessionManagement.ts +24 -1
- package/src/ui/screens/AccountOverviewScreen.tsx +38 -46
- package/src/ui/screens/AccountSettingsScreen.tsx +54 -54
- package/src/ui/screens/WelcomeNewUserScreen.tsx +13 -12
- package/src/ui/stores/accountStore.ts +54 -43
- package/src/ui/stores/authStore.ts +3 -17
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TanStack Query mutations for identity operations
|
|
3
|
+
* Provides offline-first mutations for identity creation, import, and sync
|
|
4
|
+
* Never deletes identity on errors - preserves user data
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
8
|
+
import type { User } from '../../models/interfaces';
|
|
9
|
+
|
|
10
|
+
export interface CreateIdentityResult {
|
|
11
|
+
recoveryPhrase: string[];
|
|
12
|
+
synced: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ImportIdentityResult {
|
|
16
|
+
synced: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Hook for creating a new identity with offline support
|
|
21
|
+
* Never deletes identity on error - preserves user data
|
|
22
|
+
*/
|
|
23
|
+
export function useCreateIdentity(
|
|
24
|
+
createIdentityFn: () => Promise<CreateIdentityResult>
|
|
25
|
+
) {
|
|
26
|
+
const queryClient = useQueryClient();
|
|
27
|
+
|
|
28
|
+
return useMutation({
|
|
29
|
+
mutationFn: createIdentityFn,
|
|
30
|
+
onSuccess: (data) => {
|
|
31
|
+
// Invalidate user queries to refetch after identity creation
|
|
32
|
+
queryClient.invalidateQueries({ queryKey: ['user'] });
|
|
33
|
+
queryClient.invalidateQueries({ queryKey: ['identity'] });
|
|
34
|
+
},
|
|
35
|
+
onError: (error) => {
|
|
36
|
+
// Never delete identity on error - just log it
|
|
37
|
+
// User can recover using recovery phrase
|
|
38
|
+
if (__DEV__) {
|
|
39
|
+
console.warn('[useCreateIdentity] Identity creation error (identity may still exist):', error);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
retry: false, // Don't retry identity creation
|
|
43
|
+
networkMode: 'offlineFirst',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Hook for importing an identity from recovery phrase
|
|
49
|
+
* Never deletes identity on error - preserves user data
|
|
50
|
+
*/
|
|
51
|
+
export function useImportIdentity(
|
|
52
|
+
importIdentityFn: (phrase: string) => Promise<ImportIdentityResult>
|
|
53
|
+
) {
|
|
54
|
+
const queryClient = useQueryClient();
|
|
55
|
+
|
|
56
|
+
return useMutation({
|
|
57
|
+
mutationFn: importIdentityFn,
|
|
58
|
+
onSuccess: (data) => {
|
|
59
|
+
queryClient.invalidateQueries({ queryKey: ['user'] });
|
|
60
|
+
queryClient.invalidateQueries({ queryKey: ['identity'] });
|
|
61
|
+
},
|
|
62
|
+
onError: (error) => {
|
|
63
|
+
// Never delete identity on error - just log it
|
|
64
|
+
if (__DEV__) {
|
|
65
|
+
console.warn('[useImportIdentity] Identity import error (identity may still exist):', error);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
retry: false,
|
|
69
|
+
networkMode: 'offlineFirst',
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Hook for syncing identity with server
|
|
75
|
+
* Never deletes identity on error - only logs and allows retry
|
|
76
|
+
*/
|
|
77
|
+
export function useSyncIdentity(
|
|
78
|
+
syncIdentityFn: () => Promise<User>
|
|
79
|
+
) {
|
|
80
|
+
const queryClient = useQueryClient();
|
|
81
|
+
|
|
82
|
+
return useMutation({
|
|
83
|
+
mutationFn: syncIdentityFn,
|
|
84
|
+
onSuccess: (user) => {
|
|
85
|
+
// Update user cache
|
|
86
|
+
queryClient.setQueryData(['user', 'current'], user);
|
|
87
|
+
queryClient.invalidateQueries({ queryKey: ['user'] });
|
|
88
|
+
queryClient.invalidateQueries({ queryKey: ['identity'] });
|
|
89
|
+
},
|
|
90
|
+
onError: (error) => {
|
|
91
|
+
// Never delete identity on error - just log it
|
|
92
|
+
// User can retry sync later or use recovery phrase
|
|
93
|
+
if (__DEV__) {
|
|
94
|
+
console.warn('[useSyncIdentity] Sync failed, but identity is preserved:', error);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
retry: (failureCount, error: any) => {
|
|
98
|
+
// Retry up to 2 times for sync operations
|
|
99
|
+
// Don't retry if it's a network error - user can retry when online
|
|
100
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
101
|
+
const isNetworkError =
|
|
102
|
+
errorMessage.includes('Network') ||
|
|
103
|
+
errorMessage.includes('Failed to fetch') ||
|
|
104
|
+
error?.code === 'NETWORK_ERROR';
|
|
105
|
+
|
|
106
|
+
if (isNetworkError) {
|
|
107
|
+
return false; // Don't retry network errors - user will retry when online
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return failureCount < 2;
|
|
111
|
+
},
|
|
112
|
+
networkMode: 'offlineFirst',
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useOxy } from '../context/OxyContext';
|
|
3
|
-
import { useAuthStore } from '../stores/authStore';
|
|
4
|
-
import { toast } from '../../lib/sonner';
|
|
1
|
+
import { useCallback } from 'react';
|
|
5
2
|
import { useI18n } from './useI18n';
|
|
3
|
+
import { useUpdateProfile } from './mutations/useAccountMutations';
|
|
4
|
+
import { useAuthStore } from '../stores/authStore';
|
|
6
5
|
|
|
7
6
|
export interface ProfileUpdateData {
|
|
8
7
|
displayName?: string;
|
|
@@ -33,74 +32,61 @@ export interface ProfileUpdateData {
|
|
|
33
32
|
* Provides functions to update profile fields and handle saving
|
|
34
33
|
*/
|
|
35
34
|
export const useProfileEditing = () => {
|
|
36
|
-
const { oxyServices, activeSessionId } = useOxy();
|
|
37
|
-
const updateUser = useAuthStore((state) => state.updateUser);
|
|
38
35
|
const { t } = useI18n();
|
|
39
|
-
const
|
|
36
|
+
const updateProfileMutation = useUpdateProfile();
|
|
40
37
|
|
|
41
38
|
/**
|
|
42
|
-
* Save profile updates to the server
|
|
39
|
+
* Save profile updates to the server using TanStack Query
|
|
43
40
|
*/
|
|
44
41
|
const saveProfile = useCallback(async (updates: ProfileUpdateData) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
setIsSaving(true);
|
|
42
|
+
// Prepare update object
|
|
43
|
+
const updateData: Record<string, any> = {};
|
|
52
44
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
: updates.location || '';
|
|
69
|
-
if (updates.locations) {
|
|
70
|
-
updateData.locations = updates.locations;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (updates.links !== undefined) {
|
|
74
|
-
updateData.links = updates.links;
|
|
75
|
-
}
|
|
76
|
-
if (updates.linksMetadata !== undefined) {
|
|
77
|
-
updateData.linksMetadata = updates.linksMetadata;
|
|
78
|
-
}
|
|
79
|
-
if (updates.avatar !== undefined) {
|
|
80
|
-
updateData.avatar = updates.avatar;
|
|
45
|
+
if (updates.username !== undefined) {
|
|
46
|
+
updateData.username = updates.username;
|
|
47
|
+
}
|
|
48
|
+
if (updates.email !== undefined) {
|
|
49
|
+
updateData.email = updates.email;
|
|
50
|
+
}
|
|
51
|
+
if (updates.bio !== undefined) {
|
|
52
|
+
updateData.bio = updates.bio;
|
|
53
|
+
}
|
|
54
|
+
if (updates.location !== undefined || updates.locations !== undefined) {
|
|
55
|
+
updateData.location = updates.locations && updates.locations.length > 0
|
|
56
|
+
? updates.locations[0].name
|
|
57
|
+
: updates.location || '';
|
|
58
|
+
if (updates.locations) {
|
|
59
|
+
updateData.locations = updates.locations;
|
|
81
60
|
}
|
|
61
|
+
}
|
|
62
|
+
if (updates.links !== undefined) {
|
|
63
|
+
updateData.links = updates.links;
|
|
64
|
+
}
|
|
65
|
+
if (updates.linksMetadata !== undefined) {
|
|
66
|
+
updateData.linksMetadata = updates.linksMetadata;
|
|
67
|
+
}
|
|
68
|
+
if (updates.avatar !== undefined) {
|
|
69
|
+
updateData.avatar = updates.avatar;
|
|
70
|
+
}
|
|
82
71
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
72
|
+
// Handle name field
|
|
73
|
+
if (updates.displayName !== undefined || updates.lastName !== undefined) {
|
|
74
|
+
const currentUser = useAuthStore.getState().user;
|
|
75
|
+
const currentName = currentUser?.name;
|
|
76
|
+
updateData.name = {
|
|
77
|
+
first: updates.displayName ?? (typeof currentName === 'object' ? currentName?.first : '') ?? '',
|
|
78
|
+
last: updates.lastName ?? (typeof currentName === 'object' ? currentName?.last : '') ?? '',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
92
81
|
|
|
93
|
-
|
|
94
|
-
|
|
82
|
+
try {
|
|
83
|
+
await updateProfileMutation.mutateAsync(updateData);
|
|
95
84
|
return true;
|
|
96
85
|
} catch (error: any) {
|
|
97
|
-
|
|
98
|
-
toast.error(error?.message || t('editProfile.toasts.updateFailed') || 'Failed to update profile');
|
|
86
|
+
// Error toast is handled by the mutation
|
|
99
87
|
return false;
|
|
100
|
-
} finally {
|
|
101
|
-
setIsSaving(false);
|
|
102
88
|
}
|
|
103
|
-
}, [
|
|
89
|
+
}, [updateProfileMutation, t]);
|
|
104
90
|
|
|
105
91
|
/**
|
|
106
92
|
* Update a single profile field
|
|
@@ -138,7 +124,7 @@ export const useProfileEditing = () => {
|
|
|
138
124
|
return {
|
|
139
125
|
saveProfile,
|
|
140
126
|
updateField,
|
|
141
|
-
isSaving,
|
|
127
|
+
isSaving: updateProfileMutation.isPending,
|
|
142
128
|
};
|
|
143
129
|
};
|
|
144
130
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useQueryClient as useTanStackQueryClient } from '@tanstack/react-query';
|
|
2
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Custom hook to access the QueryClient
|
|
6
|
+
* Provides type safety and ensures client is available
|
|
7
|
+
*/
|
|
8
|
+
export const useQueryClient = (): QueryClient => {
|
|
9
|
+
const queryClient = useTanStackQueryClient();
|
|
10
|
+
|
|
11
|
+
if (!queryClient) {
|
|
12
|
+
throw new Error('QueryClient is not available. Make sure OxyProvider is wrapping your app.');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return queryClient;
|
|
16
|
+
};
|
|
17
|
+
|
|
@@ -6,6 +6,8 @@ import { fetchSessionsWithFallback, mapSessionsToClient, validateSessionBatch }
|
|
|
6
6
|
import { getStorageKeys, type StorageInterface } from '../utils/storageHelpers';
|
|
7
7
|
import { handleAuthError, isInvalidSessionError } from '../utils/errorHandlers';
|
|
8
8
|
import type { OxyServices } from '../../core';
|
|
9
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
10
|
+
import { clearQueryCache } from './queryClient.js';
|
|
9
11
|
|
|
10
12
|
export interface UseSessionManagementOptions {
|
|
11
13
|
oxyServices: OxyServices;
|
|
@@ -19,6 +21,7 @@ export interface UseSessionManagementOptions {
|
|
|
19
21
|
setAuthError?: (message: string | null) => void;
|
|
20
22
|
logger?: (message: string, error?: unknown) => void;
|
|
21
23
|
setTokenReady?: (ready: boolean) => void;
|
|
24
|
+
queryClient?: QueryClient | null;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
export interface UseSessionManagementResult {
|
|
@@ -55,6 +58,7 @@ export const useSessionManagement = ({
|
|
|
55
58
|
setAuthError,
|
|
56
59
|
logger,
|
|
57
60
|
setTokenReady,
|
|
61
|
+
queryClient,
|
|
58
62
|
}: UseSessionManagementOptions): UseSessionManagementResult => {
|
|
59
63
|
const [sessions, setSessions] = useState<ClientSession[]>([]);
|
|
60
64
|
const [activeSessionId, setActiveSessionId] = useState<string | null>(null);
|
|
@@ -140,6 +144,8 @@ export const useSessionManagement = ({
|
|
|
140
144
|
try {
|
|
141
145
|
await storage.removeItem(storageKeys.activeSessionId);
|
|
142
146
|
await storage.removeItem(storageKeys.sessionIds);
|
|
147
|
+
// Clear identity sync state
|
|
148
|
+
await storage.removeItem('oxy_identity_synced').catch(() => {});
|
|
143
149
|
} catch (error) {
|
|
144
150
|
handleAuthError(error, {
|
|
145
151
|
defaultMessage: CLEAR_STORAGE_ERROR,
|
|
@@ -155,9 +161,26 @@ export const useSessionManagement = ({
|
|
|
155
161
|
setSessions([]);
|
|
156
162
|
setActiveSessionId(null);
|
|
157
163
|
logoutStore();
|
|
164
|
+
|
|
165
|
+
// Clear TanStack Query cache (in-memory)
|
|
166
|
+
if (queryClient) {
|
|
167
|
+
queryClient.clear();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Clear persisted query cache
|
|
171
|
+
if (storage) {
|
|
172
|
+
try {
|
|
173
|
+
await clearQueryCache(storage);
|
|
174
|
+
} catch (error) {
|
|
175
|
+
if (logger) {
|
|
176
|
+
logger('Failed to clear persisted query cache', error);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
158
181
|
await clearSessionStorage();
|
|
159
182
|
onAuthStateChange?.(null);
|
|
160
|
-
}, [clearSessionStorage, logoutStore, onAuthStateChange]);
|
|
183
|
+
}, [clearSessionStorage, logoutStore, onAuthStateChange, queryClient, storage, logger]);
|
|
161
184
|
|
|
162
185
|
const activateSession = useCallback(
|
|
163
186
|
async (sessionId: string, user: User): Promise<void> => {
|
|
@@ -27,6 +27,7 @@ import { getDisplayName, getShortDisplayName } from '../utils/user-utils';
|
|
|
27
27
|
import { useColorScheme } from '../hooks/use-color-scheme';
|
|
28
28
|
import { normalizeTheme } from '../utils/themeUtils';
|
|
29
29
|
import { useOxy } from '../context/OxyContext';
|
|
30
|
+
import { useUsersBySessions } from '../hooks/queries/useAccountQueries';
|
|
30
31
|
import {
|
|
31
32
|
SCREEN_PADDING_HORIZONTAL,
|
|
32
33
|
SECTION_GAP,
|
|
@@ -133,53 +134,44 @@ const AccountOverviewScreen: React.FC<BaseScreenProps> = ({
|
|
|
133
134
|
), [sessions, activeSessionId, user?.id]
|
|
134
135
|
);
|
|
135
136
|
|
|
136
|
-
// Load user profiles for additional accounts
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
setLoadingAdditionalAccounts(true);
|
|
145
|
-
try {
|
|
146
|
-
const accountsData = await Promise.all(
|
|
147
|
-
additionalAccounts.map(async (session) => {
|
|
148
|
-
try {
|
|
149
|
-
const userProfile = await oxyServices.getUserBySession(session.sessionId);
|
|
150
|
-
return {
|
|
151
|
-
id: session.sessionId,
|
|
152
|
-
sessionId: session.sessionId,
|
|
153
|
-
username: userProfile.username,
|
|
154
|
-
email: userProfile.email,
|
|
155
|
-
name: userProfile.name,
|
|
156
|
-
avatar: userProfile.avatar,
|
|
157
|
-
userProfile
|
|
158
|
-
};
|
|
159
|
-
} catch (error) {
|
|
160
|
-
console.error(`Failed to load profile for session ${session.sessionId}:`, error);
|
|
161
|
-
return {
|
|
162
|
-
id: session.sessionId,
|
|
163
|
-
sessionId: session.sessionId,
|
|
164
|
-
username: 'Unknown User',
|
|
165
|
-
email: 'No email available',
|
|
166
|
-
avatar: null,
|
|
167
|
-
userProfile: null
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
})
|
|
171
|
-
);
|
|
172
|
-
setAdditionalAccountsData(accountsData);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error('Failed to load additional accounts:', error);
|
|
175
|
-
setAdditionalAccountsData([]);
|
|
176
|
-
} finally {
|
|
177
|
-
setLoadingAdditionalAccounts(false);
|
|
178
|
-
}
|
|
179
|
-
};
|
|
137
|
+
// Load user profiles for additional accounts using TanStack Query
|
|
138
|
+
const sessionIds = additionalAccounts.map(s => s.sessionId);
|
|
139
|
+
const { data: usersData, isLoading: isLoadingUsers } = useUsersBySessions(sessionIds, {
|
|
140
|
+
enabled: additionalAccounts.length > 0
|
|
141
|
+
});
|
|
180
142
|
|
|
181
|
-
|
|
182
|
-
|
|
143
|
+
React.useEffect(() => {
|
|
144
|
+
if (usersData && usersData.length > 0) {
|
|
145
|
+
const accountsData = usersData.map(({ sessionId, user: userProfile }) => {
|
|
146
|
+
if (!userProfile) {
|
|
147
|
+
return {
|
|
148
|
+
id: sessionId,
|
|
149
|
+
sessionId,
|
|
150
|
+
username: 'Unknown User',
|
|
151
|
+
email: 'No email available',
|
|
152
|
+
avatar: null,
|
|
153
|
+
userProfile: null
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
id: sessionId,
|
|
158
|
+
sessionId,
|
|
159
|
+
username: userProfile.username,
|
|
160
|
+
email: userProfile.email,
|
|
161
|
+
name: userProfile.name,
|
|
162
|
+
avatar: userProfile.avatar,
|
|
163
|
+
userProfile
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
setAdditionalAccountsData(accountsData);
|
|
167
|
+
setLoadingAdditionalAccounts(false);
|
|
168
|
+
} else if (additionalAccounts.length === 0) {
|
|
169
|
+
setAdditionalAccountsData([]);
|
|
170
|
+
setLoadingAdditionalAccounts(false);
|
|
171
|
+
} else if (!isLoadingUsers) {
|
|
172
|
+
setLoadingAdditionalAccounts(false);
|
|
173
|
+
}
|
|
174
|
+
}, [usersData, additionalAccounts.length, isLoadingUsers]);
|
|
183
175
|
|
|
184
176
|
// Feature settings (with mock values)
|
|
185
177
|
const features = {
|