@oxyhq/services 5.4.8 → 5.5.1
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/index.js +0 -59
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +174 -17
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/FollowButton.js +8 -23
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/OxyProvider.js +49 -38
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +2 -8
- package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
- package/lib/commonjs/ui/hooks/index.js +15 -2
- package/lib/commonjs/ui/hooks/index.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAuthFetch.js +182 -0
- package/lib/commonjs/ui/hooks/useAuthFetch.js.map +1 -0
- package/lib/commonjs/ui/hooks/useFollow.js +10 -29
- package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
- package/lib/commonjs/ui/hooks/useOxyFollow.js +190 -0
- package/lib/commonjs/ui/hooks/useOxyFollow.js.map +1 -0
- package/lib/commonjs/ui/index.js +183 -0
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +18 -14
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +37 -19
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +27 -9
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js +2 -8
- package/lib/commonjs/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/commonjs/ui/store/index.js +51 -255
- package/lib/commonjs/ui/store/index.js.map +1 -1
- package/lib/commonjs/ui/store/setupOxyStore.js +63 -0
- package/lib/commonjs/ui/store/setupOxyStore.js.map +1 -0
- package/lib/commonjs/ui/store/slices/authSlice.js +56 -0
- package/lib/commonjs/ui/store/slices/authSlice.js.map +1 -0
- package/lib/commonjs/ui/store/slices/followSlice.js +238 -0
- package/lib/commonjs/ui/store/slices/followSlice.js.map +1 -0
- package/lib/commonjs/ui/store/slices/index.js +129 -0
- package/lib/commonjs/ui/store/slices/index.js.map +1 -0
- package/lib/commonjs/ui/store/slices/types.js +19 -0
- package/lib/commonjs/ui/store/slices/types.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/commonjs/ui/styles/shadows.js +123 -0
- package/lib/commonjs/ui/styles/shadows.js.map +1 -0
- package/lib/module/core/index.js +0 -59
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +14 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +8 -23
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/OxyProvider.js +49 -38
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +2 -8
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/hooks/index.js +2 -1
- package/lib/module/ui/hooks/index.js.map +1 -1
- package/lib/module/ui/hooks/useAuthFetch.js +177 -0
- package/lib/module/ui/hooks/useAuthFetch.js.map +1 -0
- package/lib/module/ui/hooks/useFollow.js +10 -29
- package/lib/module/ui/hooks/useFollow.js.map +1 -1
- package/lib/module/ui/hooks/useOxyFollow.js +186 -0
- package/lib/module/ui/hooks/useOxyFollow.js.map +1 -0
- package/lib/module/ui/index.js +12 -2
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +5 -1
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +37 -19
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +27 -9
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js +2 -8
- package/lib/module/ui/screens/karma/KarmaRewardsScreen.js.map +1 -1
- package/lib/module/ui/store/index.js +23 -249
- package/lib/module/ui/store/index.js.map +1 -1
- package/lib/module/ui/store/setupOxyStore.js +59 -0
- package/lib/module/ui/store/setupOxyStore.js.map +1 -0
- package/lib/module/ui/store/slices/authSlice.js +48 -0
- package/lib/module/ui/store/slices/authSlice.js.map +1 -0
- package/lib/module/ui/store/slices/followSlice.js +232 -0
- package/lib/module/ui/store/slices/followSlice.js.map +1 -0
- package/lib/module/ui/store/slices/index.js +11 -0
- package/lib/module/ui/store/slices/index.js.map +1 -0
- package/lib/module/ui/store/slices/types.js +15 -0
- package/lib/module/ui/store/slices/types.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/module/ui/styles/shadows.js +119 -0
- package/lib/module/ui/styles/shadows.js.map +1 -0
- package/lib/typescript/core/index.d.ts +0 -28
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +3 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/index.d.ts +2 -1
- package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useAuthFetch.d.ts +33 -0
- package/lib/typescript/ui/hooks/useAuthFetch.d.ts.map +1 -0
- package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useOxyFollow.d.ts +81 -0
- package/lib/typescript/ui/hooks/useOxyFollow.d.ts.map +1 -0
- package/lib/typescript/ui/index.d.ts +3 -1
- package/lib/typescript/ui/index.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/types.d.ts +22 -4
- package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountCenterScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaRewardsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/store/index.d.ts +19 -58
- package/lib/typescript/ui/store/index.d.ts.map +1 -1
- package/lib/typescript/ui/store/setupOxyStore.d.ts +29 -0
- package/lib/typescript/ui/store/setupOxyStore.d.ts.map +1 -0
- package/lib/typescript/ui/store/slices/authSlice.d.ts +32 -0
- package/lib/typescript/ui/store/slices/authSlice.d.ts.map +1 -0
- package/lib/typescript/ui/store/slices/followSlice.d.ts +120 -0
- package/lib/typescript/ui/store/slices/followSlice.d.ts.map +1 -0
- package/lib/typescript/ui/store/slices/index.d.ts +9 -0
- package/lib/typescript/ui/store/slices/index.d.ts.map +1 -0
- package/lib/typescript/ui/store/slices/types.d.ts +16 -0
- package/lib/typescript/ui/store/slices/types.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/lib/typescript/ui/styles/shadows.d.ts +233 -0
- package/lib/typescript/ui/styles/shadows.d.ts.map +1 -0
- package/package.json +14 -15
- package/src/__tests__/ui/hooks/useOxyFollow.test.tsx +92 -0
- package/src/__tests__/ui/store/setupOxyStore.test.ts +50 -0
- package/src/__tests__/validate-structure.js +91 -0
- package/src/__tests__/validation.js +42 -0
- package/src/core/index.ts +0 -66
- package/src/index.ts +36 -4
- package/src/ui/components/FollowButton.tsx +11 -25
- package/src/ui/components/OxyProvider.tsx +48 -33
- package/src/ui/components/OxySignInButton.tsx +2 -6
- package/src/ui/hooks/index.ts +2 -1
- package/src/ui/hooks/useAuthFetch.ts +200 -0
- package/src/ui/hooks/useFollow.ts +10 -30
- package/src/ui/hooks/useOxyFollow.ts +188 -0
- package/src/ui/index.ts +34 -2
- package/src/ui/navigation/types.ts +24 -4
- package/src/ui/screens/AccountCenterScreen.tsx +5 -7
- package/src/ui/screens/AppInfoScreen.tsx +40 -23
- package/src/ui/screens/FileManagementScreen.tsx +268 -248
- package/src/ui/screens/karma/KarmaRewardsScreen.tsx +2 -5
- package/src/ui/store/index.ts +31 -245
- package/src/ui/store/setupOxyStore.ts +58 -0
- package/src/ui/store/slices/authSlice.ts +43 -0
- package/src/ui/store/slices/followSlice.ts +207 -0
- package/src/ui/store/slices/index.ts +31 -0
- package/src/ui/store/slices/types.ts +33 -0
- package/src/ui/styles/index.ts +1 -0
- package/src/ui/styles/shadows.ts +112 -0
|
@@ -1,259 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const initialFollowState = {
|
|
11
|
-
followingUsers: {},
|
|
12
|
-
loadingUsers: {},
|
|
13
|
-
fetchingUsers: {},
|
|
14
|
-
errors: {}
|
|
15
|
-
};
|
|
3
|
+
/**
|
|
4
|
+
* OxyHQ Services Redux Store
|
|
5
|
+
* Framework-agnostic, tree-shakable Redux integration
|
|
6
|
+
*
|
|
7
|
+
* This module exports individual slices, reducers, actions, selectors, and helpers
|
|
8
|
+
* for easy integration into any Redux store without internal dependencies.
|
|
9
|
+
*/
|
|
16
10
|
|
|
17
|
-
//
|
|
18
|
-
export
|
|
19
|
-
userId,
|
|
20
|
-
oxyServices
|
|
21
|
-
}, {
|
|
22
|
-
rejectWithValue
|
|
23
|
-
}) => {
|
|
24
|
-
try {
|
|
25
|
-
// Use the proper core service method
|
|
26
|
-
const response = await oxyServices.getFollowStatus(userId);
|
|
27
|
-
return {
|
|
28
|
-
userId,
|
|
29
|
-
isFollowing: response.isFollowing
|
|
30
|
-
};
|
|
31
|
-
} catch (error) {
|
|
32
|
-
// Ignore authentication errors when user isn't signed in - don't update state
|
|
33
|
-
if (error?.status === 401 || error?.message?.includes('Authentication')) {
|
|
34
|
-
return rejectWithValue('Not authenticated');
|
|
35
|
-
}
|
|
36
|
-
// Log other failures and reject to not update state
|
|
37
|
-
console.warn(`Failed to fetch follow status for user ${userId}:`, error);
|
|
38
|
-
return rejectWithValue(error?.message || 'Failed to fetch follow status');
|
|
39
|
-
}
|
|
40
|
-
}, {
|
|
41
|
-
// Prevent duplicate requests for the same user ID
|
|
42
|
-
condition: ({
|
|
43
|
-
userId
|
|
44
|
-
}, {
|
|
45
|
-
getState
|
|
46
|
-
}) => {
|
|
47
|
-
const state = getState();
|
|
48
|
-
// Defensive check for follow state
|
|
49
|
-
if (!state.follow?.fetchingUsers) {
|
|
50
|
-
return true; // Allow request if state not initialized
|
|
51
|
-
}
|
|
52
|
-
const isAlreadyFetching = state.follow.fetchingUsers[userId];
|
|
53
|
-
if (isAlreadyFetching) {
|
|
54
|
-
console.log(`⚡ Deduplicating fetch request for user ${userId} - already in progress`);
|
|
55
|
-
return false; // Cancel this request
|
|
56
|
-
}
|
|
57
|
-
return true; // Allow this request
|
|
58
|
-
}
|
|
59
|
-
});
|
|
11
|
+
// Export individual slices and their components
|
|
12
|
+
export * from './slices';
|
|
60
13
|
|
|
61
|
-
//
|
|
62
|
-
export
|
|
63
|
-
userId,
|
|
64
|
-
oxyServices,
|
|
65
|
-
isCurrentlyFollowing
|
|
66
|
-
}, {
|
|
67
|
-
rejectWithValue,
|
|
68
|
-
dispatch
|
|
69
|
-
}) => {
|
|
70
|
-
try {
|
|
71
|
-
let response;
|
|
72
|
-
let newFollowState;
|
|
73
|
-
if (isCurrentlyFollowing) {
|
|
74
|
-
// Use the core service to unfollow user
|
|
75
|
-
response = await oxyServices.unfollowUser(userId);
|
|
76
|
-
newFollowState = false;
|
|
77
|
-
} else {
|
|
78
|
-
// Use the core service to follow user
|
|
79
|
-
response = await oxyServices.followUser(userId);
|
|
80
|
-
newFollowState = true;
|
|
81
|
-
}
|
|
14
|
+
// Export setup helper for easy integration
|
|
15
|
+
export { setupOxyStore, oxyReducers } from './setupOxyStore';
|
|
82
16
|
|
|
83
|
-
|
|
84
|
-
const isSuccess = response.success !== false && response.action !== 'error';
|
|
85
|
-
if (isSuccess) {
|
|
86
|
-
return {
|
|
87
|
-
userId,
|
|
88
|
-
isFollowing: newFollowState,
|
|
89
|
-
message: response.message || `Successfully ${newFollowState ? 'followed' : 'unfollowed'} user`
|
|
90
|
-
};
|
|
91
|
-
} else {
|
|
92
|
-
return rejectWithValue(response.message || `Failed to ${newFollowState ? 'follow' : 'unfollow'} user`);
|
|
93
|
-
}
|
|
94
|
-
} catch (error) {
|
|
95
|
-
// Enhanced error handling with state mismatch detection
|
|
96
|
-
let errorMessage = 'Network error occurred';
|
|
97
|
-
if (error?.message) {
|
|
98
|
-
errorMessage = error.message;
|
|
99
|
-
} else if (error?.response?.data?.message) {
|
|
100
|
-
errorMessage = error.response.data.message;
|
|
101
|
-
} else if (error?.data?.message) {
|
|
102
|
-
errorMessage = error.data.message;
|
|
103
|
-
}
|
|
17
|
+
// Export types for external store integration
|
|
104
18
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
const actualStatus = await oxyServices.getFollowStatus(userId);
|
|
111
|
-
dispatch({
|
|
112
|
-
type: 'follow/setFollowingStatus',
|
|
113
|
-
payload: {
|
|
114
|
-
userId,
|
|
115
|
-
isFollowing: actualStatus.isFollowing
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
return rejectWithValue('State synced with backend. Please try again.');
|
|
119
|
-
} catch (syncError) {
|
|
120
|
-
console.error('Failed to sync state with backend:', syncError);
|
|
121
|
-
}
|
|
122
|
-
} else if (errorMessage.includes('Already following this user') && !isCurrentlyFollowing) {
|
|
123
|
-
console.warn(`State mismatch detected for user ${userId}: Frontend thinks not following, backend says following. Syncing state...`);
|
|
124
|
-
// Auto-sync with backend state
|
|
125
|
-
try {
|
|
126
|
-
const actualStatus = await oxyServices.getFollowStatus(userId);
|
|
127
|
-
dispatch({
|
|
128
|
-
type: 'follow/setFollowingStatus',
|
|
129
|
-
payload: {
|
|
130
|
-
userId,
|
|
131
|
-
isFollowing: actualStatus.isFollowing
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
return rejectWithValue('State synced with backend. Please try again.');
|
|
135
|
-
} catch (syncError) {
|
|
136
|
-
console.error('Failed to sync state with backend:', syncError);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return rejectWithValue(errorMessage);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
const authSlice = createSlice({
|
|
143
|
-
name: 'auth',
|
|
144
|
-
initialState: initialAuthState,
|
|
145
|
-
reducers: {
|
|
146
|
-
loginStart(state) {
|
|
147
|
-
state.isLoading = true;
|
|
148
|
-
state.error = null;
|
|
149
|
-
},
|
|
150
|
-
loginSuccess(state, action) {
|
|
151
|
-
state.isLoading = false;
|
|
152
|
-
state.isAuthenticated = true;
|
|
153
|
-
state.user = action.payload;
|
|
154
|
-
},
|
|
155
|
-
loginFailure(state, action) {
|
|
156
|
-
state.isLoading = false;
|
|
157
|
-
state.error = action.payload;
|
|
158
|
-
},
|
|
159
|
-
logout(state) {
|
|
160
|
-
state.user = null;
|
|
161
|
-
state.isAuthenticated = false;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
const followSlice = createSlice({
|
|
166
|
-
name: 'follow',
|
|
167
|
-
initialState: initialFollowState,
|
|
168
|
-
reducers: {
|
|
169
|
-
setFollowingStatus(state, action) {
|
|
170
|
-
const {
|
|
171
|
-
userId,
|
|
172
|
-
isFollowing
|
|
173
|
-
} = action.payload;
|
|
174
|
-
state.followingUsers[userId] = isFollowing;
|
|
175
|
-
state.errors[userId] = null;
|
|
176
|
-
},
|
|
177
|
-
clearFollowError(state, action) {
|
|
178
|
-
const userId = action.payload;
|
|
179
|
-
state.errors[userId] = null;
|
|
180
|
-
},
|
|
181
|
-
resetFollowState(state) {
|
|
182
|
-
state.followingUsers = {};
|
|
183
|
-
state.loadingUsers = {};
|
|
184
|
-
state.fetchingUsers = {};
|
|
185
|
-
state.errors = {};
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
extraReducers: builder => {
|
|
189
|
-
builder
|
|
190
|
-
// Handle fetchFollowStatus
|
|
191
|
-
.addCase(fetchFollowStatus.pending, (state, action) => {
|
|
192
|
-
const {
|
|
193
|
-
userId
|
|
194
|
-
} = action.meta.arg;
|
|
195
|
-
state.fetchingUsers[userId] = true;
|
|
196
|
-
state.errors[userId] = null;
|
|
197
|
-
}).addCase(fetchFollowStatus.fulfilled, (state, action) => {
|
|
198
|
-
const {
|
|
199
|
-
userId,
|
|
200
|
-
isFollowing
|
|
201
|
-
} = action.payload;
|
|
202
|
-
state.followingUsers[userId] = isFollowing;
|
|
203
|
-
state.fetchingUsers[userId] = false;
|
|
204
|
-
state.errors[userId] = null;
|
|
205
|
-
}).addCase(fetchFollowStatus.rejected, (state, action) => {
|
|
206
|
-
const {
|
|
207
|
-
userId
|
|
208
|
-
} = action.meta.arg;
|
|
209
|
-
state.fetchingUsers[userId] = false;
|
|
210
|
-
// Don't update follow state on fetch errors - preserve existing/initial state
|
|
211
|
-
if (action.payload !== 'Not authenticated') {
|
|
212
|
-
console.warn(`Failed to fetch follow status for user ${userId}:`, action.payload);
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
// Handle toggleFollowUser
|
|
216
|
-
.addCase(toggleFollowUser.pending, (state, action) => {
|
|
217
|
-
const {
|
|
218
|
-
userId
|
|
219
|
-
} = action.meta.arg;
|
|
220
|
-
state.loadingUsers[userId] = true;
|
|
221
|
-
state.errors[userId] = null;
|
|
222
|
-
}).addCase(toggleFollowUser.fulfilled, (state, action) => {
|
|
223
|
-
const {
|
|
224
|
-
userId,
|
|
225
|
-
isFollowing
|
|
226
|
-
} = action.payload;
|
|
227
|
-
state.followingUsers[userId] = isFollowing;
|
|
228
|
-
state.loadingUsers[userId] = false;
|
|
229
|
-
state.errors[userId] = null;
|
|
230
|
-
}).addCase(toggleFollowUser.rejected, (state, action) => {
|
|
231
|
-
const {
|
|
232
|
-
userId
|
|
233
|
-
} = action.meta.arg;
|
|
234
|
-
state.loadingUsers[userId] = false;
|
|
235
|
-
state.errors[userId] = action.error.message || 'Failed to update follow status';
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
export const {
|
|
240
|
-
loginStart,
|
|
241
|
-
loginSuccess,
|
|
242
|
-
loginFailure,
|
|
243
|
-
logout
|
|
244
|
-
} = authSlice.actions;
|
|
245
|
-
export const {
|
|
246
|
-
setFollowingStatus,
|
|
247
|
-
clearFollowError,
|
|
248
|
-
resetFollowState
|
|
249
|
-
} = followSlice.actions;
|
|
19
|
+
// For backward compatibility: create a legacy store instance
|
|
20
|
+
// This will be deprecated in favor of setupOxyStore()
|
|
21
|
+
import { configureStore } from '@reduxjs/toolkit';
|
|
22
|
+
import { setupOxyStore } from './setupOxyStore';
|
|
250
23
|
|
|
251
|
-
|
|
252
|
-
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated Use setupOxyStore() instead to integrate with your app's store
|
|
26
|
+
* This internal store will be removed in a future version
|
|
27
|
+
*/
|
|
253
28
|
export const store = configureStore({
|
|
254
|
-
reducer:
|
|
255
|
-
auth: authSlice.reducer,
|
|
256
|
-
follow: followSlice.reducer
|
|
257
|
-
}
|
|
29
|
+
reducer: setupOxyStore()
|
|
258
30
|
});
|
|
31
|
+
// Legacy selector (deprecated)
|
|
32
|
+
export const selectIsUserBeingFetched = (state, userId) => state.follow.fetchingUsers[userId] ?? false;
|
|
259
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["setupOxyStore","oxyReducers","configureStore","store","reducer","selectIsUserBeingFetched","state","userId","follow","fetchingUsers"],"sourceRoot":"../../../../src","sources":["ui/store/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,cAAc,UAAU;;AAExB;AACA,SAASA,aAAa,EAAEC,WAAW,QAAQ,iBAAiB;;AAE5D;;AAGA;AACA;AACA,SAASC,cAAc,QAAQ,kBAAkB;AACjD,SAASF,aAAa,QAAQ,iBAAiB;;AAE/C;AACA;AACA;AACA;AACA,OAAO,MAAMG,KAAK,GAAGD,cAAc,CAAC;EAClCE,OAAO,EAAEJ,aAAa,CAAC;AACzB,CAAC,CAAC;AAKF;AACA,OAAO,MAAMK,wBAAwB,GAAGA,CAACC,KAAgB,EAAEC,MAAc,KACvED,KAAK,CAACE,MAAM,CAACC,aAAa,CAACF,MAAM,CAAC,IAAI,KAAK","ignoreList":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { authReducer } from './slices/authSlice';
|
|
4
|
+
import { followReducer } from './slices/followSlice';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Setup helper for Oxy Store
|
|
8
|
+
* Returns all Oxy reducers ready to be spread into a host app's Redux store
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```ts
|
|
12
|
+
* const store = configureStore({
|
|
13
|
+
* reducer: {
|
|
14
|
+
* ...setupOxyStore(),
|
|
15
|
+
* appSpecificReducer,
|
|
16
|
+
* },
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export function setupOxyStore() {
|
|
21
|
+
return {
|
|
22
|
+
auth: authReducer,
|
|
23
|
+
follow: followReducer
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Tree-shakable version where you can pick specific reducers
|
|
29
|
+
*
|
|
30
|
+
* Usage:
|
|
31
|
+
* ```ts
|
|
32
|
+
* const store = configureStore({
|
|
33
|
+
* reducer: {
|
|
34
|
+
* ...setupOxyStore.pick('auth'), // Only include auth
|
|
35
|
+
* // or
|
|
36
|
+
* ...setupOxyStore.pick('auth', 'follow'), // Include both
|
|
37
|
+
* appSpecificReducer,
|
|
38
|
+
* },
|
|
39
|
+
* });
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
setupOxyStore.pick = function (...keys) {
|
|
43
|
+
const allReducers = setupOxyStore();
|
|
44
|
+
const pickedReducers = {};
|
|
45
|
+
for (const key of keys) {
|
|
46
|
+
if (key in allReducers) {
|
|
47
|
+
// Use bracket notation with explicit typing
|
|
48
|
+
pickedReducers[key] = allReducers[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return pickedReducers;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Export individual reducers for maximum flexibility
|
|
55
|
+
export const oxyReducers = {
|
|
56
|
+
auth: authReducer,
|
|
57
|
+
follow: followReducer
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=setupOxyStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["authReducer","followReducer","setupOxyStore","auth","follow","pick","keys","allReducers","pickedReducers","key","oxyReducers"],"sourceRoot":"../../../../src","sources":["ui/store/setupOxyStore.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,oBAAoB;AAChD,SAASC,aAAa,QAAQ,sBAAsB;;AAEpD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,aAAaA,CAAA,EAAG;EAC9B,OAAO;IACLC,IAAI,EAAEH,WAAW;IACjBI,MAAM,EAAEH;EACV,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACAC,aAAa,CAACG,IAAI,GAAG,UAAS,GAAGC,IAA8B,EAAE;EAC/D,MAAMC,WAAW,GAAGL,aAAa,CAAC,CAAC;EACnC,MAAMM,cAAc,GAAG,CAAC,CAA8C;EAEtE,KAAK,MAAMC,GAAG,IAAIH,IAAI,EAAE;IACtB,IAAIG,GAAG,IAAIF,WAAW,EAAE;MACtB;MACCC,cAAc,CAAyBC,GAAG,CAAC,GAAGF,WAAW,CAACE,GAAG,CAAC;IACjE;EACF;EAEA,OAAOD,cAAc;AACvB,CAAC;;AAED;AACA,OAAO,MAAME,WAAW,GAAG;EACzBP,IAAI,EAAEH,WAAW;EACjBI,MAAM,EAAEH;AACV,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { createSlice } from '@reduxjs/toolkit';
|
|
4
|
+
import { initialAuthState } from './types';
|
|
5
|
+
export const authSlice = createSlice({
|
|
6
|
+
name: 'auth',
|
|
7
|
+
initialState: initialAuthState,
|
|
8
|
+
reducers: {
|
|
9
|
+
loginStart(state) {
|
|
10
|
+
state.isLoading = true;
|
|
11
|
+
state.error = null;
|
|
12
|
+
},
|
|
13
|
+
loginSuccess(state, action) {
|
|
14
|
+
state.isLoading = false;
|
|
15
|
+
state.isAuthenticated = true;
|
|
16
|
+
state.user = action.payload;
|
|
17
|
+
},
|
|
18
|
+
loginFailure(state, action) {
|
|
19
|
+
state.isLoading = false;
|
|
20
|
+
state.error = action.payload;
|
|
21
|
+
},
|
|
22
|
+
logout(state) {
|
|
23
|
+
state.user = null;
|
|
24
|
+
state.isAuthenticated = false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Export actions
|
|
30
|
+
export const authActions = authSlice.actions;
|
|
31
|
+
export const {
|
|
32
|
+
loginStart,
|
|
33
|
+
loginSuccess,
|
|
34
|
+
loginFailure,
|
|
35
|
+
logout
|
|
36
|
+
} = authSlice.actions;
|
|
37
|
+
|
|
38
|
+
// Export selectors
|
|
39
|
+
export const authSelectors = {
|
|
40
|
+
selectUser: state => state.auth.user,
|
|
41
|
+
selectIsAuthenticated: state => state.auth.isAuthenticated,
|
|
42
|
+
selectIsLoading: state => state.auth.isLoading,
|
|
43
|
+
selectError: state => state.auth.error
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Export reducer
|
|
47
|
+
export const authReducer = authSlice.reducer;
|
|
48
|
+
//# sourceMappingURL=authSlice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createSlice","initialAuthState","authSlice","name","initialState","reducers","loginStart","state","isLoading","error","loginSuccess","action","isAuthenticated","user","payload","loginFailure","logout","authActions","actions","authSelectors","selectUser","auth","selectIsAuthenticated","selectIsLoading","selectError","authReducer","reducer"],"sourceRoot":"../../../../../src","sources":["ui/store/slices/authSlice.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAuB,kBAAkB;AAG7D,SAASC,gBAAgB,QAAQ,SAAS;AAE1C,OAAO,MAAMC,SAAS,GAAGF,WAAW,CAAC;EACnCG,IAAI,EAAE,MAAM;EACZC,YAAY,EAAEH,gBAAgB;EAC9BI,QAAQ,EAAE;IACRC,UAAUA,CAACC,KAAgB,EAAE;MAC3BA,KAAK,CAACC,SAAS,GAAG,IAAI;MACtBD,KAAK,CAACE,KAAK,GAAG,IAAI;IACpB,CAAC;IACDC,YAAYA,CAACH,KAAgB,EAAEI,MAA2B,EAAE;MAC1DJ,KAAK,CAACC,SAAS,GAAG,KAAK;MACvBD,KAAK,CAACK,eAAe,GAAG,IAAI;MAC5BL,KAAK,CAACM,IAAI,GAAGF,MAAM,CAACG,OAAO;IAC7B,CAAC;IACDC,YAAYA,CAACR,KAAgB,EAAEI,MAA6B,EAAE;MAC5DJ,KAAK,CAACC,SAAS,GAAG,KAAK;MACvBD,KAAK,CAACE,KAAK,GAAGE,MAAM,CAACG,OAAO;IAC9B,CAAC;IACDE,MAAMA,CAACT,KAAgB,EAAE;MACvBA,KAAK,CAACM,IAAI,GAAG,IAAI;MACjBN,KAAK,CAACK,eAAe,GAAG,KAAK;IAC/B;EACF;AACF,CAAC,CAAC;;AAEF;AACA,OAAO,MAAMK,WAAW,GAAGf,SAAS,CAACgB,OAAO;AAC5C,OAAO,MAAM;EAAEZ,UAAU;EAAEI,YAAY;EAAEK,YAAY;EAAEC;AAAO,CAAC,GAAGd,SAAS,CAACgB,OAAO;;AAEnF;AACA,OAAO,MAAMC,aAAa,GAAG;EAC3BC,UAAU,EAAGb,KAA0B,IAAKA,KAAK,CAACc,IAAI,CAACR,IAAI;EAC3DS,qBAAqB,EAAGf,KAA0B,IAAKA,KAAK,CAACc,IAAI,CAACT,eAAe;EACjFW,eAAe,EAAGhB,KAA0B,IAAKA,KAAK,CAACc,IAAI,CAACb,SAAS;EACrEgB,WAAW,EAAGjB,KAA0B,IAAKA,KAAK,CAACc,IAAI,CAACZ;AAC1D,CAAC;;AAED;AACA,OAAO,MAAMgB,WAAW,GAAGvB,SAAS,CAACwB,OAAO","ignoreList":[]}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
|
4
|
+
import { initialFollowState } from './types';
|
|
5
|
+
|
|
6
|
+
// Define thunk state interface for dependency injection
|
|
7
|
+
|
|
8
|
+
// Async thunk for fetching follow status from backend with deduplication
|
|
9
|
+
export const fetchFollowStatus = createAsyncThunk('follow/fetchFollowStatus', async ({
|
|
10
|
+
userId,
|
|
11
|
+
oxyServices
|
|
12
|
+
}, {
|
|
13
|
+
rejectWithValue
|
|
14
|
+
}) => {
|
|
15
|
+
try {
|
|
16
|
+
// Use the proper core service method
|
|
17
|
+
const response = await oxyServices.getFollowStatus(userId);
|
|
18
|
+
return {
|
|
19
|
+
userId,
|
|
20
|
+
isFollowing: response.isFollowing
|
|
21
|
+
};
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// Ignore authentication errors when user isn't signed in - don't update state
|
|
24
|
+
if (error?.status === 401 || error?.message?.includes('Authentication')) {
|
|
25
|
+
return rejectWithValue('Not authenticated');
|
|
26
|
+
}
|
|
27
|
+
// Log other failures and reject to not update state
|
|
28
|
+
console.warn(`Failed to fetch follow status for user ${userId}:`, error);
|
|
29
|
+
return rejectWithValue(error?.message || 'Failed to fetch follow status');
|
|
30
|
+
}
|
|
31
|
+
}, {
|
|
32
|
+
// Prevent duplicate requests for the same user ID
|
|
33
|
+
condition: ({
|
|
34
|
+
userId
|
|
35
|
+
}, {
|
|
36
|
+
getState
|
|
37
|
+
}) => {
|
|
38
|
+
const state = getState();
|
|
39
|
+
const isAlreadyFetching = state.follow.fetchingUsers[userId];
|
|
40
|
+
if (isAlreadyFetching) {
|
|
41
|
+
console.log(`⚡ Deduplicating fetch request for user ${userId} - already in progress`);
|
|
42
|
+
return false; // Cancel this request
|
|
43
|
+
}
|
|
44
|
+
return true; // Allow this request
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Async thunk for following/unfollowing users using core services
|
|
49
|
+
export const toggleFollowUser = createAsyncThunk('follow/toggleFollowUser', async ({
|
|
50
|
+
userId,
|
|
51
|
+
oxyServices,
|
|
52
|
+
isCurrentlyFollowing
|
|
53
|
+
}, {
|
|
54
|
+
rejectWithValue,
|
|
55
|
+
dispatch
|
|
56
|
+
}) => {
|
|
57
|
+
try {
|
|
58
|
+
let response;
|
|
59
|
+
let newFollowState;
|
|
60
|
+
if (isCurrentlyFollowing) {
|
|
61
|
+
// Use the core service to unfollow user
|
|
62
|
+
response = await oxyServices.unfollowUser(userId);
|
|
63
|
+
newFollowState = false;
|
|
64
|
+
} else {
|
|
65
|
+
// Use the core service to follow user
|
|
66
|
+
response = await oxyServices.followUser(userId);
|
|
67
|
+
newFollowState = true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Check if the response indicates success (different APIs might return different formats)
|
|
71
|
+
const isSuccess = response.success !== false && response.action !== 'error';
|
|
72
|
+
if (isSuccess) {
|
|
73
|
+
return {
|
|
74
|
+
userId,
|
|
75
|
+
isFollowing: newFollowState,
|
|
76
|
+
message: response.message || `Successfully ${newFollowState ? 'followed' : 'unfollowed'} user`
|
|
77
|
+
};
|
|
78
|
+
} else {
|
|
79
|
+
return rejectWithValue(response.message || `Failed to ${newFollowState ? 'follow' : 'unfollow'} user`);
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
// Enhanced error handling with state mismatch detection
|
|
83
|
+
let errorMessage = 'Network error occurred';
|
|
84
|
+
if (error?.message) {
|
|
85
|
+
errorMessage = error.message;
|
|
86
|
+
} else if (error?.response?.data?.message) {
|
|
87
|
+
errorMessage = error.response.data.message;
|
|
88
|
+
} else if (error?.data?.message) {
|
|
89
|
+
errorMessage = error.data.message;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Handle state mismatch errors by syncing with backend
|
|
93
|
+
if (errorMessage.includes('Not following this user') && isCurrentlyFollowing) {
|
|
94
|
+
console.warn(`State mismatch detected for user ${userId}: Frontend thinks following, backend says not following. Syncing state...`);
|
|
95
|
+
// Auto-sync with backend state
|
|
96
|
+
try {
|
|
97
|
+
const actualStatus = await oxyServices.getFollowStatus(userId);
|
|
98
|
+
dispatch({
|
|
99
|
+
type: 'follow/setFollowingStatus',
|
|
100
|
+
payload: {
|
|
101
|
+
userId,
|
|
102
|
+
isFollowing: actualStatus.isFollowing
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return rejectWithValue('State synced with backend. Please try again.');
|
|
106
|
+
} catch (syncError) {
|
|
107
|
+
console.error('Failed to sync state with backend:', syncError);
|
|
108
|
+
}
|
|
109
|
+
} else if (errorMessage.includes('Already following this user') && !isCurrentlyFollowing) {
|
|
110
|
+
console.warn(`State mismatch detected for user ${userId}: Frontend thinks not following, backend says following. Syncing state...`);
|
|
111
|
+
// Auto-sync with backend state
|
|
112
|
+
try {
|
|
113
|
+
const actualStatus = await oxyServices.getFollowStatus(userId);
|
|
114
|
+
dispatch({
|
|
115
|
+
type: 'follow/setFollowingStatus',
|
|
116
|
+
payload: {
|
|
117
|
+
userId,
|
|
118
|
+
isFollowing: actualStatus.isFollowing
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return rejectWithValue('State synced with backend. Please try again.');
|
|
122
|
+
} catch (syncError) {
|
|
123
|
+
console.error('Failed to sync state with backend:', syncError);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return rejectWithValue(errorMessage);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
export const followSlice = createSlice({
|
|
130
|
+
name: 'follow',
|
|
131
|
+
initialState: initialFollowState,
|
|
132
|
+
reducers: {
|
|
133
|
+
setFollowingStatus(state, action) {
|
|
134
|
+
const {
|
|
135
|
+
userId,
|
|
136
|
+
isFollowing
|
|
137
|
+
} = action.payload;
|
|
138
|
+
state.followingUsers[userId] = isFollowing;
|
|
139
|
+
state.errors[userId] = null;
|
|
140
|
+
},
|
|
141
|
+
clearFollowError(state, action) {
|
|
142
|
+
const userId = action.payload;
|
|
143
|
+
state.errors[userId] = null;
|
|
144
|
+
},
|
|
145
|
+
resetFollowState(state) {
|
|
146
|
+
state.followingUsers = {};
|
|
147
|
+
state.loadingUsers = {};
|
|
148
|
+
state.fetchingUsers = {};
|
|
149
|
+
state.errors = {};
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
extraReducers: builder => {
|
|
153
|
+
builder
|
|
154
|
+
// Handle fetchFollowStatus
|
|
155
|
+
.addCase(fetchFollowStatus.pending, (state, action) => {
|
|
156
|
+
const {
|
|
157
|
+
userId
|
|
158
|
+
} = action.meta.arg;
|
|
159
|
+
state.fetchingUsers[userId] = true;
|
|
160
|
+
state.errors[userId] = null;
|
|
161
|
+
}).addCase(fetchFollowStatus.fulfilled, (state, action) => {
|
|
162
|
+
const {
|
|
163
|
+
userId,
|
|
164
|
+
isFollowing
|
|
165
|
+
} = action.payload;
|
|
166
|
+
state.followingUsers[userId] = isFollowing;
|
|
167
|
+
state.fetchingUsers[userId] = false;
|
|
168
|
+
state.errors[userId] = null;
|
|
169
|
+
}).addCase(fetchFollowStatus.rejected, (state, action) => {
|
|
170
|
+
const {
|
|
171
|
+
userId
|
|
172
|
+
} = action.meta.arg;
|
|
173
|
+
state.fetchingUsers[userId] = false;
|
|
174
|
+
// Don't update follow state on fetch errors - preserve existing/initial state
|
|
175
|
+
if (action.payload !== 'Not authenticated') {
|
|
176
|
+
console.warn(`Failed to fetch follow status for user ${userId}:`, action.payload);
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
// Handle toggleFollowUser
|
|
180
|
+
.addCase(toggleFollowUser.pending, (state, action) => {
|
|
181
|
+
const {
|
|
182
|
+
userId
|
|
183
|
+
} = action.meta.arg;
|
|
184
|
+
state.loadingUsers[userId] = true;
|
|
185
|
+
state.errors[userId] = null;
|
|
186
|
+
}).addCase(toggleFollowUser.fulfilled, (state, action) => {
|
|
187
|
+
const {
|
|
188
|
+
userId,
|
|
189
|
+
isFollowing
|
|
190
|
+
} = action.payload;
|
|
191
|
+
state.followingUsers[userId] = isFollowing;
|
|
192
|
+
state.loadingUsers[userId] = false;
|
|
193
|
+
state.errors[userId] = null;
|
|
194
|
+
}).addCase(toggleFollowUser.rejected, (state, action) => {
|
|
195
|
+
const {
|
|
196
|
+
userId
|
|
197
|
+
} = action.meta.arg;
|
|
198
|
+
state.loadingUsers[userId] = false;
|
|
199
|
+
state.errors[userId] = action.error.message || 'Failed to update follow status';
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// Export actions
|
|
205
|
+
export const followActions = followSlice.actions;
|
|
206
|
+
export const {
|
|
207
|
+
setFollowingStatus,
|
|
208
|
+
clearFollowError,
|
|
209
|
+
resetFollowState
|
|
210
|
+
} = followSlice.actions;
|
|
211
|
+
|
|
212
|
+
// Export thunks
|
|
213
|
+
export const followThunks = {
|
|
214
|
+
fetchFollowStatus,
|
|
215
|
+
toggleFollowUser
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Export selectors
|
|
219
|
+
export const followSelectors = {
|
|
220
|
+
selectFollowingUsers: state => state.follow.followingUsers,
|
|
221
|
+
selectLoadingUsers: state => state.follow.loadingUsers,
|
|
222
|
+
selectFetchingUsers: state => state.follow.fetchingUsers,
|
|
223
|
+
selectFollowErrors: state => state.follow.errors,
|
|
224
|
+
selectIsUserFollowed: (state, userId) => state.follow.followingUsers[userId] ?? false,
|
|
225
|
+
selectIsUserLoading: (state, userId) => state.follow.loadingUsers[userId] ?? false,
|
|
226
|
+
selectIsUserBeingFetched: (state, userId) => state.follow.fetchingUsers[userId] ?? false,
|
|
227
|
+
selectUserError: (state, userId) => state.follow.errors[userId] ?? null
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Export reducer
|
|
231
|
+
export const followReducer = followSlice.reducer;
|
|
232
|
+
//# sourceMappingURL=followSlice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createSlice","createAsyncThunk","initialFollowState","fetchFollowStatus","userId","oxyServices","rejectWithValue","response","getFollowStatus","isFollowing","error","status","message","includes","console","warn","condition","getState","state","isAlreadyFetching","follow","fetchingUsers","log","toggleFollowUser","isCurrentlyFollowing","dispatch","newFollowState","unfollowUser","followUser","isSuccess","success","action","errorMessage","data","actualStatus","type","payload","syncError","followSlice","name","initialState","reducers","setFollowingStatus","followingUsers","errors","clearFollowError","resetFollowState","loadingUsers","extraReducers","builder","addCase","pending","meta","arg","fulfilled","rejected","followActions","actions","followThunks","followSelectors","selectFollowingUsers","selectLoadingUsers","selectFetchingUsers","selectFollowErrors","selectIsUserFollowed","selectIsUserLoading","selectIsUserBeingFetched","selectUserError","followReducer","reducer"],"sourceRoot":"../../../../../src","sources":["ui/store/slices/followSlice.ts"],"mappings":"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","ignoreList":[]}
|