@oxyhq/services 5.7.5 → 5.8.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/README.md +76 -76
- package/lib/commonjs/core/index.js +177 -102
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +69 -28
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +15 -6
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +100 -12
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +58 -13
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedSection.js +7 -1
- package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js +356 -0
- package/lib/commonjs/ui/components/Header.js.map +1 -0
- package/lib/commonjs/ui/components/OxyProvider.js +28 -7
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/index.js +7 -0
- package/lib/commonjs/ui/components/index.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.js +606 -546
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.md +436 -0
- package/lib/commonjs/ui/context/OxyContext.js +181 -199
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/index.js +6 -0
- package/lib/commonjs/ui/hooks/index.js.map +1 -1
- package/lib/commonjs/ui/hooks/useFollow.js +59 -2
- package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +5 -2
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js +11 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -6
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +241 -598
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +1160 -406
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +135 -237
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +246 -463
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -3
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +808 -650
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/ProfileScreen.js +214 -37
- package/lib/commonjs/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js +51 -72
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +11 -29
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +30 -303
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +4 -4
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/UserLinksScreen.js +90 -0
- package/lib/commonjs/ui/screens/UserLinksScreen.js.map +1 -0
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +19 -31
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +7 -10
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js +11 -5
- package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js +11 -4
- package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js +9 -6
- package/lib/commonjs/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js +3 -30
- package/lib/commonjs/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +37 -46
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
- package/lib/commonjs/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +9 -12
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js +9 -12
- package/lib/commonjs/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +36 -6
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/stores/followStore.js +106 -1
- package/lib/commonjs/ui/stores/followStore.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +337 -0
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -0
- package/lib/commonjs/ui/styles/index.js +11 -0
- package/lib/commonjs/ui/styles/index.js.map +1 -1
- package/lib/module/core/index.js +177 -41
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +24 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +15 -6
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +101 -13
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +59 -14
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +7 -1
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/Header.js +351 -0
- package/lib/module/ui/components/Header.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +30 -9
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/index.js +1 -0
- package/lib/module/ui/components/index.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.js +607 -547
- package/lib/module/ui/components/internal/TextField.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.md +436 -0
- package/lib/module/ui/context/OxyContext.js +180 -198
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/index.js +1 -1
- package/lib/module/ui/hooks/index.js.map +1 -1
- package/lib/module/ui/hooks/useFollow.js +57 -1
- package/lib/module/ui/hooks/useFollow.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +5 -2
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/navigation/OxyRouter.js +11 -1
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +6 -6
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +242 -597
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +1161 -407
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +135 -237
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +248 -465
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +3 -3
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +809 -651
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/ProfileScreen.js +214 -37
- package/lib/module/ui/screens/ProfileScreen.js.map +1 -1
- package/lib/module/ui/screens/RecoverAccountScreen.js +53 -74
- package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +11 -29
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +32 -305
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +5 -5
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/UserLinksScreen.js +85 -0
- package/lib/module/ui/screens/UserLinksScreen.js.map +1 -0
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +19 -31
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +7 -10
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignUpIdentityStep.js +11 -5
- package/lib/module/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignUpSecurityStep.js +11 -4
- package/lib/module/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js +9 -6
- package/lib/module/ui/screens/karma/KarmaAboutScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js +3 -30
- package/lib/module/ui/screens/karma/KarmaCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js +37 -46
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js +9 -12
- package/lib/module/ui/screens/karma/KarmaLeaderboardScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +9 -12
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js +9 -12
- package/lib/module/ui/screens/karma/KarmaRulesScreen.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +36 -6
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/stores/followStore.js +106 -1
- package/lib/module/ui/stores/followStore.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +332 -0
- package/lib/module/ui/styles/authStyles.js.map +1 -0
- package/lib/module/ui/styles/index.js +1 -0
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/typescript/core/index.d.ts +68 -24
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +13 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts +1 -0
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts +6 -0
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedSection.d.ts +6 -0
- package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -1
- package/lib/typescript/ui/components/Header.d.ts +24 -0
- package/lib/typescript/ui/components/Header.d.ts.map +1 -0
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/index.d.ts +1 -0
- package/lib/typescript/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/TextField.d.ts +31 -16
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +5 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/index.d.ts +1 -1
- package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useFollow.d.ts +20 -0
- package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/OxyRouter.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/types.d.ts +9 -2
- package/lib/typescript/ui/navigation/types.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/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/ProfileScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +5 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/UserLinksScreen.d.ts +15 -0
- package/lib/typescript/ui/screens/UserLinksScreen.d.ts.map +1 -0
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +0 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignUpIdentityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignUpSecurityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaAboutScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaLeaderboardScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRulesScreen.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts +3 -1
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/stores/followStore.d.ts +10 -0
- package/lib/typescript/ui/stores/followStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +326 -0
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -0
- package/lib/typescript/ui/styles/index.d.ts +1 -0
- package/lib/typescript/ui/styles/index.d.ts.map +1 -1
- package/package.json +1 -4
- package/src/core/index.ts +195 -41
- package/src/index.ts +64 -4
- package/src/ui/components/Avatar.tsx +11 -5
- package/src/ui/components/FollowButton.tsx +95 -11
- package/src/ui/components/GroupedItem.tsx +57 -9
- package/src/ui/components/GroupedSection.tsx +12 -0
- package/src/ui/components/Header.tsx +405 -0
- package/src/ui/components/OxyProvider.tsx +37 -15
- package/src/ui/components/index.ts +1 -0
- package/src/ui/components/internal/GroupedPillButtons.tsx +1 -1
- package/src/ui/components/internal/TextField.md +436 -0
- package/src/ui/components/internal/TextField.tsx +720 -620
- package/src/ui/context/OxyContext.tsx +211 -195
- package/src/ui/hooks/index.ts +1 -1
- package/src/ui/hooks/useFollow.ts +63 -0
- package/src/ui/hooks/useSessionSocket.ts +5 -2
- package/src/ui/navigation/OxyRouter.tsx +11 -1
- package/src/ui/navigation/types.ts +10 -2
- package/src/ui/screens/AccountCenterScreen.tsx +5 -5
- package/src/ui/screens/AccountManagementDemo.tsx +9 -9
- package/src/ui/screens/AccountOverviewScreen.tsx +265 -414
- package/src/ui/screens/AccountSettingsScreen.tsx +1173 -403
- package/src/ui/screens/AccountSwitcherScreen.tsx +158 -202
- package/src/ui/screens/AppInfoScreen.tsx +270 -497
- package/src/ui/screens/FeedbackScreen.tsx +3 -3
- package/src/ui/screens/PaymentGatewayScreen.tsx +668 -365
- package/src/ui/screens/ProfileScreen.tsx +196 -33
- package/src/ui/screens/RecoverAccountScreen.tsx +46 -74
- package/src/ui/screens/SessionManagementScreen.tsx +14 -22
- package/src/ui/screens/SignInScreen.tsx +27 -294
- package/src/ui/screens/SignUpScreen.tsx +5 -5
- package/src/ui/screens/UserLinksScreen.tsx +96 -0
- package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -22
- package/src/ui/screens/internal/SignInUsernameStep.tsx +3 -10
- package/src/ui/screens/internal/SignUpIdentityStep.tsx +2 -5
- package/src/ui/screens/internal/SignUpSecurityStep.tsx +3 -4
- package/src/ui/screens/karma/KarmaAboutScreen.tsx +9 -2
- package/src/ui/screens/karma/KarmaCenterScreen.tsx +1 -20
- package/src/ui/screens/karma/KarmaFAQScreen.tsx +40 -24
- package/src/ui/screens/karma/KarmaLeaderboardScreen.tsx +9 -3
- package/src/ui/screens/karma/KarmaRewardsScreen.tsx +9 -3
- package/src/ui/screens/karma/KarmaRulesScreen.tsx +9 -3
- package/src/ui/stores/authStore.ts +34 -7
- package/src/ui/stores/followStore.ts +102 -1
- package/src/ui/styles/authStyles.ts +352 -0
- package/src/ui/styles/index.ts +1 -0
- package/lib/commonjs/core/auth-manager.js +0 -440
- package/lib/commonjs/core/auth-manager.js.map +0 -1
- package/lib/commonjs/core/use-auth.js +0 -244
- package/lib/commonjs/core/use-auth.js.map +0 -1
- package/lib/module/core/auth-manager.js +0 -432
- package/lib/module/core/auth-manager.js.map +0 -1
- package/lib/module/core/use-auth.js +0 -235
- package/lib/module/core/use-auth.js.map +0 -1
- package/lib/typescript/core/auth-manager.d.ts +0 -136
- package/lib/typescript/core/auth-manager.d.ts.map +0 -1
- package/lib/typescript/core/use-auth.d.ts +0 -79
- package/lib/typescript/core/use-auth.d.ts.map +0 -1
- package/src/__tests__/middleware.test.ts +0 -105
- package/src/__tests__/setup.ts +0 -10
- package/src/__tests__/zero-config-auth.test.ts +0 -607
- package/src/core/auth-manager.ts +0 -500
- package/src/core/use-auth.tsx +0 -245
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { createContext, useContext, useEffect, useCallback, ReactNode, useMemo } from 'react';
|
|
1
|
+
import React, { createContext, useContext, useEffect, useCallback, ReactNode, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { OxyServices } from '../../core';
|
|
3
|
-
import { User } from '../../models/interfaces';
|
|
3
|
+
import { User, ApiError } from '../../models/interfaces';
|
|
4
4
|
import { SecureLoginResponse, SecureClientSession, MinimalUserData } from '../../models/secureSession';
|
|
5
5
|
import { DeviceManager } from '../../utils/deviceManager';
|
|
6
6
|
import { useSessionSocket } from '../hooks/useSessionSocket';
|
|
@@ -49,9 +49,11 @@ const OxyContext = createContext<OxyContextState | null>(null);
|
|
|
49
49
|
// Props for the OxyContextProvider
|
|
50
50
|
export interface OxyContextProviderProps {
|
|
51
51
|
children: ReactNode;
|
|
52
|
-
oxyServices
|
|
52
|
+
oxyServices?: OxyServices; // Now optional - will be created automatically if not provided
|
|
53
|
+
baseURL?: string; // New: API base URL for automatic service creation
|
|
53
54
|
storageKeyPrefix?: string;
|
|
54
55
|
onAuthStateChange?: (user: User | null) => void;
|
|
56
|
+
onError?: (error: ApiError) => void; // New: Error callback
|
|
55
57
|
bottomSheetRef?: React.RefObject<any>;
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -110,17 +112,33 @@ const getStorage = async (): Promise<StorageInterface> => {
|
|
|
110
112
|
|
|
111
113
|
// Storage keys for secure sessions
|
|
112
114
|
const getSecureStorageKeys = (prefix = 'oxy_secure') => ({
|
|
113
|
-
|
|
114
|
-
activeSessionId: `${prefix}_active_session_id`, // ID of currently active session
|
|
115
|
+
activeSessionId: `${prefix}_active_session_id`, // Only store the active session ID
|
|
115
116
|
});
|
|
116
117
|
|
|
117
|
-
export const
|
|
118
|
+
export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
118
119
|
children,
|
|
119
|
-
oxyServices,
|
|
120
|
+
oxyServices: providedOxyServices,
|
|
121
|
+
baseURL,
|
|
120
122
|
storageKeyPrefix = 'oxy_secure',
|
|
121
123
|
onAuthStateChange,
|
|
124
|
+
onError,
|
|
122
125
|
bottomSheetRef,
|
|
123
126
|
}) => {
|
|
127
|
+
// Create oxyServices automatically if not provided
|
|
128
|
+
const oxyServicesRef = useRef<OxyServices | null>(null);
|
|
129
|
+
|
|
130
|
+
if (!oxyServicesRef.current) {
|
|
131
|
+
if (providedOxyServices) {
|
|
132
|
+
oxyServicesRef.current = providedOxyServices;
|
|
133
|
+
} else if (baseURL) {
|
|
134
|
+
oxyServicesRef.current = new OxyServices({ baseURL });
|
|
135
|
+
} else {
|
|
136
|
+
throw new Error('Either oxyServices or baseURL must be provided to OxyContextProvider');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const oxyServices = oxyServicesRef.current;
|
|
141
|
+
|
|
124
142
|
// Zustand state
|
|
125
143
|
const user = useAuthStore((state) => state.user);
|
|
126
144
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
|
@@ -156,94 +174,60 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
156
174
|
initStorage();
|
|
157
175
|
}, []);
|
|
158
176
|
|
|
159
|
-
// Effect to initialize authentication state
|
|
177
|
+
// Effect to initialize authentication state - only store session ID
|
|
160
178
|
useEffect(() => {
|
|
161
179
|
const initAuth = async () => {
|
|
162
180
|
if (!storage) return;
|
|
163
181
|
|
|
164
182
|
useAuthStore.setState({ isLoading: true });
|
|
165
183
|
try {
|
|
166
|
-
//
|
|
167
|
-
const sessionsData = await storage.getItem(keys.sessions);
|
|
184
|
+
// Only load the active session ID from storage
|
|
168
185
|
const storedActiveSessionId = await storage.getItem(keys.activeSessionId);
|
|
169
186
|
|
|
170
|
-
console.log('SecureAuth - sessionsData:', sessionsData);
|
|
171
187
|
console.log('SecureAuth - activeSessionId:', storedActiveSessionId);
|
|
172
188
|
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
189
|
+
if (storedActiveSessionId) {
|
|
190
|
+
// Validate the stored session with the backend
|
|
191
|
+
try {
|
|
192
|
+
const validation = await oxyServices.validateSession(storedActiveSessionId);
|
|
193
|
+
|
|
194
|
+
if (validation.valid) {
|
|
195
|
+
console.log('SecureAuth - session validated successfully');
|
|
196
|
+
setActiveSessionId(storedActiveSessionId);
|
|
197
|
+
|
|
198
|
+
// Get access token for API calls
|
|
199
|
+
await oxyServices.getTokenBySession(storedActiveSessionId);
|
|
200
|
+
|
|
201
|
+
// Load full user data from backend
|
|
202
|
+
const fullUser = await oxyServices.getUserBySession(storedActiveSessionId);
|
|
203
|
+
loginSuccess(fullUser);
|
|
204
|
+
setMinimalUser({
|
|
205
|
+
id: fullUser.id,
|
|
206
|
+
username: fullUser.username,
|
|
207
|
+
avatar: fullUser.avatar
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Load sessions from backend
|
|
211
|
+
const serverSessions = await oxyServices.getSessionsBySessionId(storedActiveSessionId);
|
|
212
|
+
const clientSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
|
|
213
|
+
sessionId: serverSession.sessionId,
|
|
214
|
+
deviceId: serverSession.deviceId,
|
|
215
|
+
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
216
|
+
lastActive: serverSession.lastActive || new Date().toISOString(),
|
|
217
|
+
userId: serverSession.userId || fullUser.id
|
|
218
|
+
}));
|
|
219
|
+
setSessions(clientSessions);
|
|
220
|
+
|
|
221
|
+
if (onAuthStateChange) {
|
|
222
|
+
onAuthStateChange(fullUser);
|
|
195
223
|
}
|
|
196
224
|
} else {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Update storage if we made changes
|
|
203
|
-
if (shouldUpdateStorage) {
|
|
204
|
-
await saveSessionsToStorage(migratedSessions);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
setSessions(migratedSessions);
|
|
208
|
-
|
|
209
|
-
if (storedActiveSessionId && migratedSessions.length > 0) {
|
|
210
|
-
const activeSession = migratedSessions.find(s => s.sessionId === storedActiveSessionId);
|
|
211
|
-
|
|
212
|
-
if (activeSession) {
|
|
213
|
-
console.log('SecureAuth - activeSession found:', activeSession);
|
|
214
|
-
|
|
215
|
-
// Validate session
|
|
216
|
-
try {
|
|
217
|
-
const validation = await oxyServices.validateSession(activeSession.sessionId);
|
|
218
|
-
|
|
219
|
-
if (validation.valid) {
|
|
220
|
-
console.log('SecureAuth - session validated successfully');
|
|
221
|
-
setActiveSessionId(activeSession.sessionId);
|
|
222
|
-
|
|
223
|
-
// Get access token for API calls
|
|
224
|
-
await oxyServices.getTokenBySession(activeSession.sessionId);
|
|
225
|
-
|
|
226
|
-
// Load full user data
|
|
227
|
-
const fullUser = await oxyServices.getUserBySession(activeSession.sessionId);
|
|
228
|
-
loginSuccess(fullUser);
|
|
229
|
-
setMinimalUser({
|
|
230
|
-
id: fullUser.id,
|
|
231
|
-
username: fullUser.username,
|
|
232
|
-
avatar: fullUser.avatar
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
if (onAuthStateChange) {
|
|
236
|
-
onAuthStateChange(fullUser);
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
console.log('SecureAuth - session invalid, removing');
|
|
240
|
-
await removeInvalidSession(activeSession.sessionId);
|
|
241
|
-
}
|
|
242
|
-
} catch (error) {
|
|
243
|
-
console.error('SecureAuth - session validation error:', error);
|
|
244
|
-
await removeInvalidSession(activeSession.sessionId);
|
|
245
|
-
}
|
|
225
|
+
console.log('SecureAuth - session invalid, clearing storage');
|
|
226
|
+
await clearAllStorage();
|
|
246
227
|
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error('SecureAuth - session validation error:', error);
|
|
230
|
+
await clearAllStorage();
|
|
247
231
|
}
|
|
248
232
|
}
|
|
249
233
|
} catch (err) {
|
|
@@ -257,33 +241,15 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
257
241
|
if (storage) {
|
|
258
242
|
initAuth();
|
|
259
243
|
}
|
|
260
|
-
}, [storage, oxyServices, keys, onAuthStateChange]);
|
|
244
|
+
}, [storage, oxyServices, keys, onAuthStateChange, loginSuccess, setMinimalUser]);
|
|
261
245
|
|
|
262
|
-
// Effect to restore token on app load or session switch
|
|
263
|
-
useEffect(() => {
|
|
264
|
-
const restoreToken = async () => {
|
|
265
|
-
if (activeSessionId && oxyServices) {
|
|
266
|
-
try {
|
|
267
|
-
await oxyServices.getTokenBySession(activeSessionId);
|
|
268
|
-
setTokenReady(true);
|
|
269
|
-
} catch (err) {
|
|
270
|
-
// If token restoration fails, force logout
|
|
271
|
-
await logout();
|
|
272
|
-
setTokenReady(false);
|
|
273
|
-
}
|
|
274
|
-
} else {
|
|
275
|
-
setTokenReady(true); // No session, so token is not needed
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
restoreToken();
|
|
279
|
-
// Only run when activeSessionId or oxyServices changes
|
|
280
|
-
}, [activeSessionId, oxyServices]);
|
|
281
246
|
|
|
282
|
-
|
|
247
|
+
|
|
248
|
+
// Remove invalid session - refresh sessions from backend
|
|
283
249
|
const removeInvalidSession = useCallback(async (sessionId: string): Promise<void> => {
|
|
250
|
+
// Remove from local state
|
|
284
251
|
const filteredSessions = sessions.filter(s => s.sessionId !== sessionId);
|
|
285
252
|
setSessions(filteredSessions);
|
|
286
|
-
await saveSessionsToStorage(filteredSessions);
|
|
287
253
|
|
|
288
254
|
// If there are other sessions, switch to the first one
|
|
289
255
|
if (filteredSessions.length > 0) {
|
|
@@ -301,13 +267,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
301
267
|
}
|
|
302
268
|
}, [sessions, storage, keys, onAuthStateChange, logoutStore]);
|
|
303
269
|
|
|
304
|
-
// Save
|
|
305
|
-
const saveSessionsToStorage = useCallback(async (sessionsList: SecureClientSession[]): Promise<void> => {
|
|
306
|
-
if (!storage) return;
|
|
307
|
-
await storage.setItem(keys.sessions, JSON.stringify(sessionsList));
|
|
308
|
-
}, [storage, keys.sessions]);
|
|
309
|
-
|
|
310
|
-
// Save active session ID to storage
|
|
270
|
+
// Save active session ID to storage (only session ID, no user data)
|
|
311
271
|
const saveActiveSessionId = useCallback(async (sessionId: string): Promise<void> => {
|
|
312
272
|
if (!storage) return;
|
|
313
273
|
await storage.setItem(keys.activeSessionId, sessionId);
|
|
@@ -317,7 +277,6 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
317
277
|
const clearAllStorage = useCallback(async (): Promise<void> => {
|
|
318
278
|
if (!storage) return;
|
|
319
279
|
try {
|
|
320
|
-
await storage.removeItem(keys.sessions);
|
|
321
280
|
await storage.removeItem(keys.activeSessionId);
|
|
322
281
|
} catch (err) {
|
|
323
282
|
console.error('Clear secure storage error:', err);
|
|
@@ -356,8 +315,8 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
356
315
|
}
|
|
357
316
|
}, [oxyServices, onAuthStateChange, loginSuccess, saveActiveSessionId]);
|
|
358
317
|
|
|
359
|
-
// Secure login method
|
|
360
|
-
const login = async (username: string, password: string, deviceName?: string): Promise<User> => {
|
|
318
|
+
// Secure login method - only store session ID, retrieve data from backend
|
|
319
|
+
const login = useCallback(async (username: string, password: string, deviceName?: string): Promise<User> => {
|
|
361
320
|
if (!storage) throw new Error('Storage not initialized');
|
|
362
321
|
useAuthStore.setState({ isLoading: true, error: null });
|
|
363
322
|
|
|
@@ -378,56 +337,29 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
378
337
|
deviceFingerprint
|
|
379
338
|
);
|
|
380
339
|
|
|
381
|
-
//
|
|
382
|
-
const clientSession: SecureClientSession = {
|
|
383
|
-
sessionId: response.sessionId,
|
|
384
|
-
deviceId: response.deviceId,
|
|
385
|
-
expiresAt: response.expiresAt,
|
|
386
|
-
lastActive: new Date().toISOString(),
|
|
387
|
-
userId: response.user.id
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// Check if this user already has a session (prevent duplicate accounts)
|
|
391
|
-
const existingUserSessionIndex = sessions.findIndex(s =>
|
|
392
|
-
s.userId === response.user.id
|
|
393
|
-
);
|
|
394
|
-
|
|
395
|
-
let updatedSessions: SecureClientSession[];
|
|
396
|
-
|
|
397
|
-
if (existingUserSessionIndex !== -1) {
|
|
398
|
-
// User already has a session - replace it with the new one (reused session scenario)
|
|
399
|
-
const existingSession = sessions[existingUserSessionIndex];
|
|
400
|
-
updatedSessions = [...sessions];
|
|
401
|
-
updatedSessions[existingUserSessionIndex] = clientSession;
|
|
402
|
-
|
|
403
|
-
console.log(`Reusing/updating existing session for user ${response.user.id}. Previous session: ${existingSession.sessionId}, New session: ${response.sessionId}`);
|
|
404
|
-
|
|
405
|
-
// If the replaced session was the active one, update active session
|
|
406
|
-
if (activeSessionId === existingSession.sessionId) {
|
|
407
|
-
setActiveSessionId(response.sessionId);
|
|
408
|
-
await saveActiveSessionId(response.sessionId);
|
|
409
|
-
}
|
|
410
|
-
} else {
|
|
411
|
-
// Add new session for new user
|
|
412
|
-
updatedSessions = [...sessions, clientSession];
|
|
413
|
-
console.log(`Added new session for user ${response.user.id} on device ${response.deviceId}`);
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
setSessions(updatedSessions);
|
|
417
|
-
await saveSessionsToStorage(updatedSessions);
|
|
418
|
-
|
|
419
|
-
// Set as active session
|
|
340
|
+
// Set as active session (only store session ID)
|
|
420
341
|
setActiveSessionId(response.sessionId);
|
|
421
342
|
await saveActiveSessionId(response.sessionId);
|
|
422
343
|
|
|
423
344
|
// Get access token for API calls
|
|
424
345
|
await oxyServices.getTokenBySession(response.sessionId);
|
|
425
346
|
|
|
426
|
-
// Load full user data
|
|
347
|
+
// Load full user data from backend
|
|
427
348
|
const fullUser = await oxyServices.getUserBySession(response.sessionId);
|
|
428
349
|
loginSuccess(fullUser);
|
|
429
350
|
setMinimalUser(response.user);
|
|
430
351
|
|
|
352
|
+
// Load sessions from backend
|
|
353
|
+
const serverSessions = await oxyServices.getSessionsBySessionId(response.sessionId);
|
|
354
|
+
const clientSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
|
|
355
|
+
sessionId: serverSession.sessionId,
|
|
356
|
+
deviceId: serverSession.deviceId,
|
|
357
|
+
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
358
|
+
lastActive: serverSession.lastActive || new Date().toISOString(),
|
|
359
|
+
userId: serverSession.userId || fullUser.id
|
|
360
|
+
}));
|
|
361
|
+
setSessions(clientSessions);
|
|
362
|
+
|
|
431
363
|
if (onAuthStateChange) {
|
|
432
364
|
onAuthStateChange(fullUser);
|
|
433
365
|
}
|
|
@@ -439,20 +371,19 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
439
371
|
} finally {
|
|
440
372
|
useAuthStore.setState({ isLoading: false });
|
|
441
373
|
}
|
|
442
|
-
};
|
|
374
|
+
}, [storage, oxyServices, saveActiveSessionId, loginSuccess, setMinimalUser, onAuthStateChange, loginFailure]);
|
|
443
375
|
|
|
444
376
|
// Logout method
|
|
445
|
-
const logout = async (targetSessionId?: string): Promise<void> => {
|
|
377
|
+
const logout = useCallback(async (targetSessionId?: string): Promise<void> => {
|
|
446
378
|
if (!activeSessionId) return;
|
|
447
379
|
|
|
448
380
|
try {
|
|
449
381
|
const sessionToLogout = targetSessionId || activeSessionId;
|
|
450
382
|
await oxyServices.logoutSecureSession(activeSessionId, sessionToLogout);
|
|
451
383
|
|
|
452
|
-
// Remove session from local
|
|
384
|
+
// Remove session from local state
|
|
453
385
|
const filteredSessions = sessions.filter(s => s.sessionId !== sessionToLogout);
|
|
454
386
|
setSessions(filteredSessions);
|
|
455
|
-
await saveSessionsToStorage(filteredSessions);
|
|
456
387
|
|
|
457
388
|
// If logging out active session
|
|
458
389
|
if (sessionToLogout === activeSessionId) {
|
|
@@ -475,10 +406,10 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
475
406
|
console.error('Logout error:', error);
|
|
476
407
|
useAuthStore.setState({ error: 'Logout failed' });
|
|
477
408
|
}
|
|
478
|
-
};
|
|
409
|
+
}, [activeSessionId, oxyServices, sessions, switchToSession, logoutStore, setMinimalUser, storage, keys.activeSessionId, onAuthStateChange]);
|
|
479
410
|
|
|
480
411
|
// Logout all sessions
|
|
481
|
-
const logoutAll = async (): Promise<void> => {
|
|
412
|
+
const logoutAll = useCallback(async (): Promise<void> => {
|
|
482
413
|
console.log('logoutAll called with activeSessionId:', activeSessionId);
|
|
483
414
|
|
|
484
415
|
if (!activeSessionId) {
|
|
@@ -515,10 +446,30 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
515
446
|
useAuthStore.setState({ error: `Logout all failed: ${error instanceof Error ? error.message : 'Unknown error'}` });
|
|
516
447
|
throw error;
|
|
517
448
|
}
|
|
518
|
-
};
|
|
449
|
+
}, [activeSessionId, oxyServices, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
|
|
450
|
+
|
|
451
|
+
// Effect to restore token on app load or session switch
|
|
452
|
+
useEffect(() => {
|
|
453
|
+
const restoreToken = async () => {
|
|
454
|
+
if (activeSessionId && oxyServices) {
|
|
455
|
+
try {
|
|
456
|
+
await oxyServices.getTokenBySession(activeSessionId);
|
|
457
|
+
setTokenReady(true);
|
|
458
|
+
} catch (err) {
|
|
459
|
+
// If token restoration fails, force logout
|
|
460
|
+
await logout();
|
|
461
|
+
setTokenReady(false);
|
|
462
|
+
}
|
|
463
|
+
} else {
|
|
464
|
+
setTokenReady(true); // No session, so token is not needed
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
restoreToken();
|
|
468
|
+
// Only run when activeSessionId or oxyServices changes
|
|
469
|
+
}, [activeSessionId, oxyServices, logout]);
|
|
519
470
|
|
|
520
471
|
// Sign up method
|
|
521
|
-
const signUp = async (username: string, email: string, password: string): Promise<User> => {
|
|
472
|
+
const signUp = useCallback(async (username: string, email: string, password: string): Promise<User> => {
|
|
522
473
|
if (!storage) throw new Error('Storage not initialized');
|
|
523
474
|
|
|
524
475
|
useAuthStore.setState({ isLoading: true, error: null });
|
|
@@ -540,42 +491,82 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
540
491
|
} finally {
|
|
541
492
|
useAuthStore.setState({ isLoading: false });
|
|
542
493
|
}
|
|
543
|
-
};
|
|
494
|
+
}, [storage, oxyServices, login, loginFailure]);
|
|
544
495
|
|
|
545
496
|
// Switch session method
|
|
546
|
-
const switchSession = async (sessionId: string): Promise<void> => {
|
|
497
|
+
const switchSession = useCallback(async (sessionId: string): Promise<void> => {
|
|
547
498
|
await switchToSession(sessionId);
|
|
548
|
-
};
|
|
499
|
+
}, [switchToSession]);
|
|
549
500
|
|
|
550
501
|
// Remove session method
|
|
551
|
-
const removeSession = async (sessionId: string): Promise<void> => {
|
|
502
|
+
const removeSession = useCallback(async (sessionId: string): Promise<void> => {
|
|
552
503
|
await logout(sessionId);
|
|
553
|
-
};
|
|
504
|
+
}, [logout]);
|
|
554
505
|
|
|
555
506
|
// Refresh sessions method
|
|
556
|
-
const refreshSessions = async (): Promise<void> => {
|
|
557
|
-
|
|
507
|
+
const refreshSessions = useCallback(async (): Promise<void> => {
|
|
508
|
+
console.log('refreshSessions called with activeSessionId:', activeSessionId);
|
|
509
|
+
|
|
510
|
+
if (!activeSessionId) {
|
|
511
|
+
console.log('refreshSessions: No activeSessionId, returning');
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
558
514
|
|
|
559
515
|
try {
|
|
516
|
+
console.log('refreshSessions: Calling getSessionsBySessionId...');
|
|
560
517
|
const serverSessions = await oxyServices.getSessionsBySessionId(activeSessionId);
|
|
518
|
+
console.log('refreshSessions: Server sessions received:', serverSessions);
|
|
561
519
|
|
|
562
520
|
// Update local sessions with server data
|
|
563
521
|
const updatedSessions: SecureClientSession[] = serverSessions.map(serverSession => ({
|
|
564
522
|
sessionId: serverSession.sessionId,
|
|
565
523
|
deviceId: serverSession.deviceId,
|
|
566
|
-
expiresAt: new Date().toISOString(),
|
|
567
|
-
lastActive: new Date().toISOString()
|
|
524
|
+
expiresAt: serverSession.expiresAt || new Date().toISOString(),
|
|
525
|
+
lastActive: serverSession.lastActive || new Date().toISOString(),
|
|
526
|
+
userId: serverSession.userId || user?.id
|
|
568
527
|
}));
|
|
569
528
|
|
|
529
|
+
console.log('refreshSessions: Updated sessions:', updatedSessions);
|
|
570
530
|
setSessions(updatedSessions);
|
|
571
|
-
|
|
531
|
+
console.log('refreshSessions: Sessions updated in state');
|
|
572
532
|
} catch (error) {
|
|
573
533
|
console.error('Refresh sessions error:', error);
|
|
534
|
+
|
|
535
|
+
// If the current session is invalid, try to find another valid session
|
|
536
|
+
if (sessions.length > 1) {
|
|
537
|
+
console.log('Current session invalid, trying to switch to another session...');
|
|
538
|
+
const otherSessions = sessions.filter(s => s.sessionId !== activeSessionId);
|
|
539
|
+
|
|
540
|
+
for (const session of otherSessions) {
|
|
541
|
+
try {
|
|
542
|
+
// Try to validate this session
|
|
543
|
+
await oxyServices.validateSession(session.sessionId);
|
|
544
|
+
console.log('Found valid session, switching to:', session.sessionId);
|
|
545
|
+
await switchToSession(session.sessionId);
|
|
546
|
+
return; // Successfully switched to another session
|
|
547
|
+
} catch (sessionError) {
|
|
548
|
+
console.log('Session validation failed for:', session.sessionId, sessionError);
|
|
549
|
+
continue; // Try next session
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// If no valid sessions found, clear all sessions
|
|
555
|
+
console.log('No valid sessions found, clearing all sessions');
|
|
556
|
+
setSessions([]);
|
|
557
|
+
setActiveSessionId(null);
|
|
558
|
+
logoutStore();
|
|
559
|
+
setMinimalUser(null);
|
|
560
|
+
await clearAllStorage();
|
|
561
|
+
|
|
562
|
+
if (onAuthStateChange) {
|
|
563
|
+
onAuthStateChange(null);
|
|
564
|
+
}
|
|
574
565
|
}
|
|
575
|
-
};
|
|
566
|
+
}, [activeSessionId, oxyServices, user?.id, sessions, switchToSession, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
|
|
576
567
|
|
|
577
568
|
// Device management methods
|
|
578
|
-
const getDeviceSessions = async (): Promise<any[]> => {
|
|
569
|
+
const getDeviceSessions = useCallback(async (): Promise<any[]> => {
|
|
579
570
|
if (!activeSessionId) throw new Error('No active session');
|
|
580
571
|
|
|
581
572
|
try {
|
|
@@ -584,9 +575,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
584
575
|
console.error('Get device sessions error:', error);
|
|
585
576
|
throw error;
|
|
586
577
|
}
|
|
587
|
-
};
|
|
578
|
+
}, [activeSessionId, oxyServices]);
|
|
588
579
|
|
|
589
|
-
const logoutAllDeviceSessions = async (): Promise<void> => {
|
|
580
|
+
const logoutAllDeviceSessions = useCallback(async (): Promise<void> => {
|
|
590
581
|
if (!activeSessionId) throw new Error('No active session');
|
|
591
582
|
|
|
592
583
|
try {
|
|
@@ -606,9 +597,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
606
597
|
console.error('Logout all device sessions error:', error);
|
|
607
598
|
throw error;
|
|
608
599
|
}
|
|
609
|
-
};
|
|
600
|
+
}, [activeSessionId, oxyServices, logoutStore, setMinimalUser, clearAllStorage, onAuthStateChange]);
|
|
610
601
|
|
|
611
|
-
const updateDeviceName = async (deviceName: string): Promise<void> => {
|
|
602
|
+
const updateDeviceName = useCallback(async (deviceName: string): Promise<void> => {
|
|
612
603
|
if (!activeSessionId) throw new Error('No active session');
|
|
613
604
|
|
|
614
605
|
try {
|
|
@@ -620,7 +611,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
620
611
|
console.error('Update device name error:', error);
|
|
621
612
|
throw error;
|
|
622
613
|
}
|
|
623
|
-
};
|
|
614
|
+
}, [activeSessionId, oxyServices]);
|
|
624
615
|
|
|
625
616
|
// Bottom sheet control methods
|
|
626
617
|
const showBottomSheet = useCallback((screenOrConfig?: string | { screen: string; props?: Record<string, any> }) => {
|
|
@@ -638,6 +629,7 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
638
629
|
bottomSheetRef.current.present();
|
|
639
630
|
} else {
|
|
640
631
|
console.warn('No expand or present method available on bottomSheetRef');
|
|
632
|
+
console.log('Available methods on bottomSheetRef.current:', Object.keys(bottomSheetRef.current));
|
|
641
633
|
}
|
|
642
634
|
|
|
643
635
|
// Then navigate to the specified screen if provided
|
|
@@ -657,6 +649,8 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
657
649
|
}
|
|
658
650
|
} else {
|
|
659
651
|
console.warn('bottomSheetRef is not available');
|
|
652
|
+
console.warn('To fix this, ensure you pass a bottomSheetRef to OxyProvider:');
|
|
653
|
+
console.warn('<OxyProvider baseURL="..." bottomSheetRef={yourBottomSheetRef}>');
|
|
660
654
|
}
|
|
661
655
|
}, [bottomSheetRef]);
|
|
662
656
|
|
|
@@ -672,16 +666,38 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
672
666
|
userId: user?.id,
|
|
673
667
|
activeSessionId,
|
|
674
668
|
refreshSessions,
|
|
675
|
-
logout
|
|
669
|
+
logout,
|
|
676
670
|
baseURL: oxyServices.getBaseURL(),
|
|
677
|
-
onRemoteSignOut: () => {
|
|
671
|
+
onRemoteSignOut: useCallback(() => {
|
|
678
672
|
toast.info('You have been signed out remotely.');
|
|
679
673
|
logout();
|
|
680
|
-
},
|
|
674
|
+
}, [logout]),
|
|
681
675
|
});
|
|
682
676
|
|
|
683
677
|
// Context value
|
|
684
|
-
const contextValue: OxyContextState = {
|
|
678
|
+
const contextValue: OxyContextState = useMemo(() => ({
|
|
679
|
+
user,
|
|
680
|
+
minimalUser,
|
|
681
|
+
sessions,
|
|
682
|
+
activeSessionId,
|
|
683
|
+
isAuthenticated,
|
|
684
|
+
isLoading,
|
|
685
|
+
error,
|
|
686
|
+
login,
|
|
687
|
+
logout,
|
|
688
|
+
logoutAll,
|
|
689
|
+
signUp,
|
|
690
|
+
switchSession,
|
|
691
|
+
removeSession,
|
|
692
|
+
refreshSessions,
|
|
693
|
+
getDeviceSessions,
|
|
694
|
+
logoutAllDeviceSessions,
|
|
695
|
+
updateDeviceName,
|
|
696
|
+
oxyServices,
|
|
697
|
+
bottomSheetRef,
|
|
698
|
+
showBottomSheet,
|
|
699
|
+
hideBottomSheet,
|
|
700
|
+
}), [
|
|
685
701
|
user,
|
|
686
702
|
minimalUser,
|
|
687
703
|
sessions,
|
|
@@ -691,22 +707,19 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
691
707
|
error,
|
|
692
708
|
login,
|
|
693
709
|
logout,
|
|
694
|
-
logoutAll
|
|
695
|
-
signUp
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
getDeviceSessions: async () => { return await getDeviceSessions(); },
|
|
703
|
-
logoutAllDeviceSessions: async () => { await logoutAllDeviceSessions(); },
|
|
704
|
-
updateDeviceName: async (deviceName) => { await updateDeviceName(deviceName); },
|
|
710
|
+
logoutAll,
|
|
711
|
+
signUp,
|
|
712
|
+
switchSession,
|
|
713
|
+
removeSession,
|
|
714
|
+
refreshSessions,
|
|
715
|
+
getDeviceSessions,
|
|
716
|
+
logoutAllDeviceSessions,
|
|
717
|
+
updateDeviceName,
|
|
705
718
|
oxyServices,
|
|
706
719
|
bottomSheetRef,
|
|
707
720
|
showBottomSheet,
|
|
708
721
|
hideBottomSheet,
|
|
709
|
-
|
|
722
|
+
]);
|
|
710
723
|
|
|
711
724
|
// Wrap children rendering to block until token is ready
|
|
712
725
|
if (!tokenReady) {
|
|
@@ -720,6 +733,9 @@ export const OxyContextProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
720
733
|
);
|
|
721
734
|
};
|
|
722
735
|
|
|
736
|
+
// Alias for backward compatibility
|
|
737
|
+
export const OxyContextProvider = OxyProvider;
|
|
738
|
+
|
|
723
739
|
// Hook to use the context
|
|
724
740
|
export const useOxy = (): OxyContextState => {
|
|
725
741
|
const context = useContext(OxyContext);
|
package/src/ui/hooks/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { useFollow } from './useFollow';
|
|
1
|
+
export { useFollow, useFollowerCounts } from './useFollow';
|