@oxyhq/services 5.4.5 → 5.4.6

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.
Files changed (37) hide show
  1. package/lib/commonjs/core/index.js +59 -0
  2. package/lib/commonjs/core/index.js.map +1 -1
  3. package/lib/commonjs/ui/components/FollowButton.js +23 -8
  4. package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
  5. package/lib/commonjs/ui/hooks/useFollow.js +29 -10
  6. package/lib/commonjs/ui/hooks/useFollow.js.map +1 -1
  7. package/lib/commonjs/ui/screens/AppInfoScreen.js +19 -37
  8. package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
  9. package/lib/commonjs/ui/screens/FileManagementScreen.js +9 -27
  10. package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
  11. package/lib/commonjs/ui/store/index.js +5 -1
  12. package/lib/commonjs/ui/store/index.js.map +1 -1
  13. package/lib/module/core/index.js +59 -0
  14. package/lib/module/core/index.js.map +1 -1
  15. package/lib/module/ui/components/FollowButton.js +23 -8
  16. package/lib/module/ui/components/FollowButton.js.map +1 -1
  17. package/lib/module/ui/hooks/useFollow.js +29 -10
  18. package/lib/module/ui/hooks/useFollow.js.map +1 -1
  19. package/lib/module/ui/screens/AppInfoScreen.js +19 -37
  20. package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
  21. package/lib/module/ui/screens/FileManagementScreen.js +9 -27
  22. package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
  23. package/lib/module/ui/store/index.js +5 -1
  24. package/lib/module/ui/store/index.js.map +1 -1
  25. package/lib/typescript/core/index.d.ts +28 -0
  26. package/lib/typescript/core/index.d.ts.map +1 -1
  27. package/lib/typescript/ui/components/FollowButton.d.ts.map +1 -1
  28. package/lib/typescript/ui/hooks/useFollow.d.ts.map +1 -1
  29. package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
  30. package/lib/typescript/ui/screens/FileManagementScreen.d.ts.map +1 -1
  31. package/lib/typescript/ui/store/index.d.ts.map +1 -1
  32. package/package.json +1 -1
  33. package/src/ui/components/FollowButton.tsx +25 -11
  34. package/src/ui/hooks/useFollow.ts +30 -10
  35. package/src/ui/screens/AppInfoScreen.tsx +23 -40
  36. package/src/ui/screens/FileManagementScreen.tsx +248 -268
  37. package/src/ui/store/index.ts +6 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useFollow.d.ts","sourceRoot":"","sources":["../../../../src/ui/hooks/useFollow.ts"],"names":[],"mappings":"AAmCA;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,GAAG,MAAM,EAAE;;;;;iCA8CF,OAAO;;;;;;;;;;;;;;;wCAqBM,MAAM;2CAcT,MAAM,aAAa,OAAO;uCAIxB,MAAM;;sCAiBb,MAAM;;;;;;;;;;;;CA8B5D,CAAC"}
1
+ {"version":3,"file":"useFollow.d.ts","sourceRoot":"","sources":["../../../../src/ui/hooks/useFollow.ts"],"names":[],"mappings":"AAuDA;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,MAAM,GAAG,MAAM,EAAE;;;;;iCA8CF,OAAO;;;;;;;;;;;;;;;wCAqBM,MAAM;2CAcT,MAAM,aAAa,OAAO;uCAIxB,MAAM;;sCAiBb,MAAM;;;;;;;;;;;;CA8B5D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"AppInfoScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/AppInfoScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAoBtD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA+kB5C,CAAC;AA2FF,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"AppInfoScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/AppInfoScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAanD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAoBtD,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8jB5C,CAAC;AA2FF,eAAe,aAAa,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileManagementScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/FileManagementScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAezE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAOtD,UAAU,yBAA0B,SAAQ,eAAe;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA6yD7D,CAAC;AA4qBF,eAAe,oBAAoB,CAAC"}
1
+ {"version":3,"file":"FileManagementScreen.d.ts","sourceRoot":"","sources":["../../../../src/ui/screens/FileManagementScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAezE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAOtD,UAAU,yBAA0B,SAAQ,eAAe;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,QAAA,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAyxD7D,CAAC;AA4qBF,eAAe,oBAAoB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/store/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,UAAU,SAAS;IACjB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,UAAU,WAAW;IAEnB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEtC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAiBD,eAAO,MAAM,iBAAiB;;;;YAEc,MAAM;iBAAe,GAAG;;;;;;;;;;EA6BnE,CAAC;AAGF,eAAO,MAAM,gBAAgB;;;;;YAGjB,MAAM;iBACD,GAAG;0BACM,OAAO;;;;;;;;;;EAkEhC,CAAC;AAwFF,eAAO,MAAQ,UAAU,6EAAE,YAAY,kFAAE,YAAY,oFAAE,MAAM,uEAAsB,CAAC;AACpF,eAAO,MAAQ,kBAAkB;YA3D0C,MAAM;iBAAe,OAAO;iCA2DpE,gBAAgB,0FAAE,gBAAgB,mFAAwB,CAAC;AAG9F,eAAO,MAAM,wBAAwB,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,YAC5B,CAAC;AAE9C,eAAO,MAAM,KAAK;;;;;;;;oCAKhB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/store/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAEpD,UAAU,SAAS;IACjB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,UAAU,WAAW;IAEnB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEtC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACvC;AAiBD,eAAO,MAAM,iBAAiB;;;;YAEc,MAAM;iBAAe,GAAG;;;;;;;;;;EAkCnE,CAAC;AAGF,eAAO,MAAM,gBAAgB;;;;;YAGjB,MAAM;iBACD,GAAG;0BACM,OAAO;;;;;;;;;;EAkEhC,CAAC;AAwFF,eAAO,MAAQ,UAAU,6EAAE,YAAY,kFAAE,YAAY,oFAAE,MAAM,uEAAsB,CAAC;AACpF,eAAO,MAAQ,kBAAkB;YA3D0C,MAAM;iBAAe,OAAO;iCA2DpE,gBAAgB,0FAAE,gBAAgB,mFAAwB,CAAC;AAG9F,eAAO,MAAM,wBAAwB,GAAI,OAAO,SAAS,EAAE,QAAQ,MAAM,YACzB,CAAC;AAEjD,eAAO,MAAM,KAAK;;;;;;;;oCAKhB,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAC,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "5.4.5",
3
+ "version": "5.4.6",
4
4
  "description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
5
5
  "main": "lib/commonjs/node/index.js",
6
6
  "module": "lib/module/node/index.js",
@@ -142,17 +142,31 @@ const FollowButton: React.FC<FollowButtonProps> = ({
142
142
  const dispatch = useDispatch();
143
143
  const { oxyServices, isAuthenticated } = useOxy();
144
144
 
145
- // Optimized single selector to prevent multiple re-renders
146
- const followState = useSelector((state: RootState) => ({
147
- isFollowing: state.follow.followingUsers[userId] ?? initiallyFollowing ?? false,
148
- isLoading: state.follow.loadingUsers[userId] ?? false,
149
- error: state.follow.errors[userId]
150
- }));
151
-
152
- // Whether the follow status has been loaded from the store
153
- const isStatusKnown = useSelector((state: RootState) =>
154
- Object.prototype.hasOwnProperty.call(state.follow.followingUsers, userId)
155
- );
145
+ // Optimized single selector to prevent multiple re-renders with defensive checks
146
+ const followState = useSelector((state: RootState) => {
147
+ // Defensive check to handle cases where follow state might not be initialized yet
148
+ if (!state.follow) {
149
+ return {
150
+ isFollowing: initiallyFollowing ?? false,
151
+ isLoading: false,
152
+ error: null
153
+ };
154
+ }
155
+
156
+ return {
157
+ isFollowing: state.follow.followingUsers?.[userId] ?? initiallyFollowing ?? false,
158
+ isLoading: state.follow.loadingUsers?.[userId] ?? false,
159
+ error: state.follow.errors?.[userId] ?? null
160
+ };
161
+ });
162
+
163
+ // Whether the follow status has been loaded from the store with defensive check
164
+ const isStatusKnown = useSelector((state: RootState) => {
165
+ if (!state.follow?.followingUsers) {
166
+ return false;
167
+ }
168
+ return Object.prototype.hasOwnProperty.call(state.follow.followingUsers, userId);
169
+ });
156
170
 
157
171
  const { isFollowing, isLoading, error } = followState;
158
172
 
@@ -6,9 +6,9 @@ import { useOxy } from '../context/OxyContext';
6
6
 
7
7
  // Memoized selector to prevent unnecessary re-renders
8
8
  const createFollowSelector = (userId: string) => (state: RootState) => ({
9
- isFollowing: state.follow.followingUsers[userId] ?? false,
10
- isLoading: state.follow.loadingUsers[userId] ?? false,
11
- error: state.follow.errors[userId] ?? null,
9
+ isFollowing: state.follow?.followingUsers?.[userId] ?? false,
10
+ isLoading: state.follow?.loadingUsers?.[userId] ?? false,
11
+ error: state.follow?.errors?.[userId] ?? null,
12
12
  });
13
13
 
14
14
  // Memoized selector for multiple users
@@ -16,20 +16,40 @@ const createMultipleFollowSelector = (userIds: string[]) => (state: RootState) =
16
16
  const followData: Record<string, { isFollowing: boolean; isLoading: boolean; error: string | null }> = {};
17
17
  const followState = state.follow;
18
18
 
19
+ // Defensive check for follow state
20
+ if (!followState) {
21
+ // Return default values if follow state is not initialized
22
+ for (const userId of userIds) {
23
+ followData[userId] = {
24
+ isFollowing: false,
25
+ isLoading: false,
26
+ error: null,
27
+ };
28
+ }
29
+
30
+ return {
31
+ followData,
32
+ isAnyLoading: false,
33
+ hasAnyError: false,
34
+ allFollowing: false,
35
+ allNotFollowing: true,
36
+ };
37
+ }
38
+
19
39
  for (const userId of userIds) {
20
40
  followData[userId] = {
21
- isFollowing: followState.followingUsers[userId] ?? false,
22
- isLoading: followState.loadingUsers[userId] ?? false,
23
- error: followState.errors[userId] ?? null,
41
+ isFollowing: followState.followingUsers?.[userId] ?? false,
42
+ isLoading: followState.loadingUsers?.[userId] ?? false,
43
+ error: followState.errors?.[userId] ?? null,
24
44
  };
25
45
  }
26
46
 
27
47
  return {
28
48
  followData,
29
- isAnyLoading: userIds.some(uid => followState.loadingUsers[uid]),
30
- hasAnyError: userIds.some(uid => followState.errors[uid]),
31
- allFollowing: userIds.every(uid => followState.followingUsers[uid]),
32
- allNotFollowing: userIds.every(uid => !followState.followingUsers[uid]),
49
+ isAnyLoading: userIds.some(uid => followState.loadingUsers?.[uid]),
50
+ hasAnyError: userIds.some(uid => followState.errors?.[uid]),
51
+ allFollowing: userIds.every(uid => followState.followingUsers?.[uid]),
52
+ allNotFollowing: userIds.every(uid => !followState.followingUsers?.[uid]),
33
53
  };
34
54
  };
35
55
 
@@ -69,18 +69,15 @@ const AppInfoScreen: React.FC<BaseScreenProps> = ({
69
69
  // Check API connection on mount
70
70
  const checkConnection = async () => {
71
71
  setConnectionStatus('checking');
72
- const apiBaseUrl = oxyServices?.getBaseURL() || 'https://api.oxy.so';
72
+
73
+ if (!oxyServices) {
74
+ setConnectionStatus('disconnected');
75
+ return;
76
+ }
77
+
73
78
  try {
74
- const response = await fetch(`${apiBaseUrl}/`, {
75
- method: 'GET',
76
- timeout: 3000,
77
- } as any);
78
-
79
- if (response.ok) {
80
- setConnectionStatus('connected');
81
- } else {
82
- setConnectionStatus('disconnected');
83
- }
79
+ await oxyServices.healthCheck();
80
+ setConnectionStatus('connected');
84
81
  } catch (error) {
85
82
  setConnectionStatus('disconnected');
86
83
  }
@@ -121,22 +118,11 @@ const AppInfoScreen: React.FC<BaseScreenProps> = ({
121
118
  toast.info('Running system checks...', { duration: 2000 });
122
119
 
123
120
  try {
124
- const response = await fetch(`${apiBaseUrl}/`, {
125
- method: 'GET',
126
- timeout: 5000,
127
- } as any);
128
-
129
- if (response.ok) {
130
- const data = await response.json();
131
- checks.push('✅ API server is responding');
132
- checks.push(`📊 Server stats: ${data.users || 0} users`);
133
- checks.push(`🌐 API URL: ${apiBaseUrl}`);
134
- setConnectionStatus('connected');
135
- } else {
136
- checks.push('❌ API server returned error status');
137
- checks.push(` Status: ${response.status} ${response.statusText}`);
138
- setConnectionStatus('disconnected');
139
- }
121
+ const data = await oxyServices.healthCheck();
122
+ checks.push('✅ API server is responding');
123
+ checks.push(`📊 Server stats: ${data.users || 0} users`);
124
+ checks.push(`🌐 API URL: ${apiBaseUrl}`);
125
+ setConnectionStatus('connected');
140
126
  } catch (error) {
141
127
  checks.push('❌ API server connection failed');
142
128
  checks.push(` Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
@@ -514,20 +500,17 @@ const AppInfoScreen: React.FC<BaseScreenProps> = ({
514
500
  }
515
501
  onPress={async () => {
516
502
  setConnectionStatus('checking');
517
- const apiBaseUrl = oxyServices?.getBaseURL() || 'https://api.oxy.so';
503
+
504
+ if (!oxyServices) {
505
+ setConnectionStatus('disconnected');
506
+ toast.error('OxyServices not initialized');
507
+ return;
508
+ }
509
+
518
510
  try {
519
- const response = await fetch(`${apiBaseUrl}/`, {
520
- method: 'GET',
521
- timeout: 3000,
522
- } as any);
523
-
524
- if (response.ok) {
525
- setConnectionStatus('connected');
526
- toast.success('API connection successful');
527
- } else {
528
- setConnectionStatus('disconnected');
529
- toast.error(`API server error: ${response.status}`);
530
- }
511
+ await oxyServices.healthCheck();
512
+ setConnectionStatus('connected');
513
+ toast.success('API connection successful');
531
514
  } catch (error) {
532
515
  setConnectionStatus('disconnected');
533
516
  toast.error('Failed to connect to API server');