@oxyhq/services 0.0.84 → 0.1.0

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 (181) hide show
  1. package/README.md +269 -79
  2. package/dist/components/AuthBottomSheet/types.d.ts +24 -0
  3. package/dist/components/AuthBottomSheet/types.js +2 -0
  4. package/dist/components/FileSelectorModal/types.d.ts +35 -0
  5. package/dist/components/FileSelectorModal/types.js +2 -0
  6. package/dist/components/SessionProvider.d.ts +26 -0
  7. package/dist/components/SessionProvider.js +367 -0
  8. package/dist/config.d.ts +169 -0
  9. package/dist/config.js +115 -0
  10. package/dist/constants.d.ts +54 -0
  11. package/dist/constants.js +61 -0
  12. package/dist/hooks/index.d.ts +11 -0
  13. package/dist/hooks/index.js +23 -0
  14. package/dist/hooks/useAuth.d.ts +6 -0
  15. package/dist/hooks/useAuth.js +17 -0
  16. package/dist/hooks/useFiles.d.ts +10 -0
  17. package/dist/hooks/useFiles.js +329 -0
  18. package/dist/hooks/useProfile.d.ts +13 -0
  19. package/dist/hooks/useProfile.js +154 -0
  20. package/dist/hooks/useSession.d.ts +2 -0
  21. package/dist/hooks/useSession.js +12 -0
  22. package/dist/hooks/useSubscription.d.ts +15 -0
  23. package/dist/hooks/useSubscription.js +85 -0
  24. package/dist/index.d.ts +28 -7
  25. package/dist/index.js +82 -6
  26. package/dist/package.json +71 -0
  27. package/dist/reducers/index.d.ts +8 -0
  28. package/dist/reducers/index.js +29 -0
  29. package/dist/reducers/profileReducer.d.ts +55 -0
  30. package/dist/reducers/profileReducer.js +136 -0
  31. package/dist/services/OxyClient.d.ts +84 -0
  32. package/dist/services/OxyClient.js +309 -0
  33. package/dist/services/api.service.d.ts +61 -0
  34. package/dist/services/api.service.js +289 -0
  35. package/dist/services/auth.service.d.ts +87 -0
  36. package/dist/services/auth.service.js +266 -0
  37. package/dist/services/index.d.ts +30 -0
  38. package/dist/services/index.js +88 -0
  39. package/dist/services/payment.service.d.ts +20 -0
  40. package/dist/services/payment.service.js +56 -0
  41. package/dist/services/privacy.service.d.ts +16 -0
  42. package/dist/services/privacy.service.js +69 -0
  43. package/dist/services/profile.service.d.ts +20 -0
  44. package/dist/services/profile.service.js +158 -0
  45. package/dist/services/subscription.service.d.ts +7 -0
  46. package/dist/services/subscription.service.js +46 -0
  47. package/dist/services/user.service.d.ts +25 -0
  48. package/dist/services/user.service.js +109 -0
  49. package/dist/styles/colors.d.ts +24 -0
  50. package/dist/styles/colors.js +31 -0
  51. package/dist/styles/shared.d.ts +168 -0
  52. package/dist/styles/shared.js +177 -0
  53. package/dist/types/index.d.ts +136 -2
  54. package/dist/types/index.js +7 -1
  55. package/dist/utils/api.d.ts +20 -0
  56. package/dist/utils/api.js +546 -0
  57. package/dist/utils/authEvents.d.ts +44 -0
  58. package/dist/utils/authEvents.js +73 -0
  59. package/dist/utils/errorHandler.d.ts +68 -0
  60. package/dist/utils/errorHandler.js +166 -0
  61. package/dist/utils/index.d.ts +12 -0
  62. package/dist/utils/index.js +41 -0
  63. package/dist/utils/logger.d.ts +100 -0
  64. package/dist/utils/logger.js +298 -0
  65. package/dist/utils/socket.d.ts +6 -0
  66. package/dist/utils/socket.js +179 -0
  67. package/dist/utils/socketConfig.d.ts +32 -0
  68. package/dist/utils/socketConfig.js +67 -0
  69. package/dist/utils/storage.d.ts +54 -0
  70. package/dist/utils/storage.js +253 -0
  71. package/package.json +71 -59
  72. package/dist/assets/dot-icon.d.ts +0 -3
  73. package/dist/assets/dot-icon.d.ts.map +0 -1
  74. package/dist/assets/dot-icon.js +0 -6
  75. package/dist/assets/verified-icon.d.ts +0 -3
  76. package/dist/assets/verified-icon.d.ts.map +0 -1
  77. package/dist/assets/verified-icon.js +0 -10
  78. package/dist/components/assets/oxy-logo.d.ts +0 -3
  79. package/dist/components/assets/oxy-logo.d.ts.map +0 -1
  80. package/dist/components/assets/oxy-logo.js +0 -30
  81. package/dist/components/auth/AccountSwitcherModal.d.ts +0 -7
  82. package/dist/components/auth/AccountSwitcherModal.d.ts.map +0 -1
  83. package/dist/components/auth/AccountSwitcherModal.js +0 -91
  84. package/dist/components/auth/SessionOwnerButton.d.ts +0 -3
  85. package/dist/components/auth/SessionOwnerButton.d.ts.map +0 -1
  86. package/dist/components/auth/SessionOwnerButton.js +0 -35
  87. package/dist/components/auth/SignInButton.d.ts +0 -8
  88. package/dist/components/auth/SignInButton.d.ts.map +0 -1
  89. package/dist/components/auth/SignInButton.js +0 -15
  90. package/dist/components/auth/styles/account-switcher-modal.module.css +0 -29
  91. package/dist/components/auth/styles/account-switcher-modal.module.css.map +0 -1
  92. package/dist/components/auth/styles/oavatar.module.css +0 -34
  93. package/dist/components/auth/styles/oavatar.module.css.map +0 -1
  94. package/dist/components/auth/styles/session-owner-modal.module.css +0 -35
  95. package/dist/components/auth/styles/session-owner-modal.module.css.map +0 -1
  96. package/dist/components/auth/styles/sign-in-button.module.css +0 -30
  97. package/dist/components/auth/styles/sign-in-button.module.css.map +0 -1
  98. package/dist/components/elements/button/components/button.d.ts +0 -7
  99. package/dist/components/elements/button/components/button.d.ts.map +0 -1
  100. package/dist/components/elements/button/components/button.js +0 -6
  101. package/dist/components/elements/button/components/styles/button.module.css +0 -25
  102. package/dist/components/elements/button/components/styles/button.module.css.map +0 -1
  103. package/dist/components/elements/button/index.d.ts +0 -2
  104. package/dist/components/elements/button/index.d.ts.map +0 -1
  105. package/dist/components/elements/button/index.js +0 -1
  106. package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.d.ts +0 -5
  107. package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.d.ts.map +0 -1
  108. package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.js +0 -4
  109. package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.d.ts +0 -5
  110. package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.d.ts.map +0 -1
  111. package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.js +0 -4
  112. package/dist/components/elements/ellipsis-wrapper/components/styles/ellipses-wrapper.module.css +0 -11
  113. package/dist/components/elements/ellipsis-wrapper/components/styles/ellipses-wrapper.module.css.map +0 -1
  114. package/dist/components/elements/ellipsis-wrapper/index.d.ts +0 -2
  115. package/dist/components/elements/ellipsis-wrapper/index.d.ts.map +0 -1
  116. package/dist/components/elements/ellipsis-wrapper/index.js +0 -1
  117. package/dist/components/elements/modal/components/confirmation-modal.d.ts +0 -12
  118. package/dist/components/elements/modal/components/confirmation-modal.d.ts.map +0 -1
  119. package/dist/components/elements/modal/components/confirmation-modal.js +0 -21
  120. package/dist/components/elements/modal/components/modal.d.ts +0 -13
  121. package/dist/components/elements/modal/components/modal.d.ts.map +0 -1
  122. package/dist/components/elements/modal/components/modal.js +0 -111
  123. package/dist/components/elements/modal/components/styles/confirmation-modal.module.css +0 -105
  124. package/dist/components/elements/modal/components/styles/confirmation-modal.module.css.map +0 -1
  125. package/dist/components/elements/modal/components/styles/modal.module.css +0 -10
  126. package/dist/components/elements/modal/components/styles/modal.module.css.map +0 -1
  127. package/dist/components/elements/modal/hooks/use-track-position.d.ts +0 -5
  128. package/dist/components/elements/modal/hooks/use-track-position.d.ts.map +0 -1
  129. package/dist/components/elements/modal/hooks/use-track-position.js +0 -35
  130. package/dist/components/elements/modal/index.d.ts +0 -4
  131. package/dist/components/elements/modal/index.d.ts.map +0 -1
  132. package/dist/components/elements/modal/index.js +0 -3
  133. package/dist/config/index.d.ts +0 -21
  134. package/dist/config/index.d.ts.map +0 -1
  135. package/dist/config/index.js +0 -7
  136. package/dist/features/profile/components/avatar.d.ts +0 -10
  137. package/dist/features/profile/components/avatar.d.ts.map +0 -1
  138. package/dist/features/profile/components/avatar.js +0 -7
  139. package/dist/features/profile/components/styles/avatar.module.css +0 -15
  140. package/dist/features/profile/components/styles/avatar.module.css.map +0 -1
  141. package/dist/features/profile/components/styles/user-name.module.css +0 -18
  142. package/dist/features/profile/components/styles/user-name.module.css.map +0 -1
  143. package/dist/features/profile/components/styles/user-username.module.css +0 -6
  144. package/dist/features/profile/components/styles/user-username.module.css.map +0 -1
  145. package/dist/features/profile/components/user-name.d.ts +0 -7
  146. package/dist/features/profile/components/user-name.d.ts.map +0 -1
  147. package/dist/features/profile/components/user-name.js +0 -8
  148. package/dist/features/profile/components/user-username.d.ts +0 -5
  149. package/dist/features/profile/components/user-username.d.ts.map +0 -1
  150. package/dist/features/profile/components/user-username.js +0 -7
  151. package/dist/features/profile/index.d.ts +0 -4
  152. package/dist/features/profile/index.d.ts.map +0 -1
  153. package/dist/features/profile/index.js +0 -3
  154. package/dist/hooks/get-user.d.ts +0 -2
  155. package/dist/hooks/get-user.d.ts.map +0 -1
  156. package/dist/hooks/get-user.js +0 -31
  157. package/dist/hooks/getClientKey.d.ts +0 -2
  158. package/dist/hooks/getClientKey.d.ts.map +0 -1
  159. package/dist/hooks/getClientKey.js +0 -19
  160. package/dist/hooks/getUserById.d.ts +0 -11
  161. package/dist/hooks/getUserById.d.ts.map +0 -1
  162. package/dist/hooks/getUserById.js +0 -31
  163. package/dist/hooks/use-user.d.ts +0 -14
  164. package/dist/hooks/use-user.d.ts.map +0 -1
  165. package/dist/hooks/use-user.js +0 -8
  166. package/dist/hooks/useCrossDomainStorage.d.ts +0 -6
  167. package/dist/hooks/useCrossDomainStorage.d.ts.map +0 -1
  168. package/dist/hooks/useCrossDomainStorage.js +0 -24
  169. package/dist/hooks/useOxySession.d.ts +0 -30
  170. package/dist/hooks/useOxySession.d.ts.map +0 -1
  171. package/dist/hooks/useOxySession.js +0 -64
  172. package/dist/index.css +0 -5
  173. package/dist/index.css.map +0 -1
  174. package/dist/index.d.ts.map +0 -1
  175. package/dist/interfaces/index.d.ts +0 -10
  176. package/dist/interfaces/index.d.ts.map +0 -1
  177. package/dist/interfaces/index.js +0 -1
  178. package/dist/types/index.d.ts.map +0 -1
  179. package/dist/utils/cn.d.ts +0 -3
  180. package/dist/utils/cn.d.ts.map +0 -1
  181. package/dist/utils/cn.js +0 -5
@@ -0,0 +1,54 @@
1
+ /**
2
+ * OxyHQ Services Constants
3
+ *
4
+ * This file contains constants used throughout the OxyHQ services module.
5
+ * Centralizing these values helps maintain consistency across the application.
6
+ */
7
+ export declare const ENDPOINTS: {
8
+ AUTH: {
9
+ LOGIN: string;
10
+ REGISTER: string;
11
+ REFRESH: string;
12
+ LOGOUT: string;
13
+ VALIDATE: string;
14
+ };
15
+ USERS: {
16
+ PROFILE: (id: string) => string;
17
+ SESSIONS: string;
18
+ FOLLOWERS: (id: string) => string;
19
+ FOLLOWING: (id: string) => string;
20
+ };
21
+ FILES: {
22
+ LIST: (userId: string) => string;
23
+ UPLOAD: string;
24
+ DELETE: (fileId: string) => string;
25
+ };
26
+ SUBSCRIPTION: {
27
+ GET: (userId: string) => string;
28
+ UPDATE: (userId: string) => string;
29
+ CANCEL: (userId: string) => string;
30
+ };
31
+ };
32
+ export declare const STORAGE_KEYS: {
33
+ readonly ACCESS_TOKEN: "@oxy/access_token";
34
+ readonly REFRESH_TOKEN: "@oxy/refresh_token";
35
+ readonly USER: "@oxy/user";
36
+ readonly USER_ID: "@oxy/user_id";
37
+ readonly SESSIONS: "@oxy/sessions";
38
+ };
39
+ export declare const DEFAULTS: {
40
+ SESSION_EXPIRE_TIME: number;
41
+ CACHE_TIMEOUT: number;
42
+ MAX_FILES: number;
43
+ MAX_UPLOAD_SIZE: number;
44
+ ALLOWED_FILE_TYPES: string[];
45
+ };
46
+ export declare const ERROR_MESSAGES: {
47
+ DEFAULT: string;
48
+ NETWORK: string;
49
+ UNAUTHORIZED: string;
50
+ VALIDATION: string;
51
+ FILE_SIZE: string;
52
+ FILE_TYPE: string;
53
+ SESSION_EXPIRED: string;
54
+ };
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ /**
3
+ * OxyHQ Services Constants
4
+ *
5
+ * This file contains constants used throughout the OxyHQ services module.
6
+ * Centralizing these values helps maintain consistency across the application.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ERROR_MESSAGES = exports.DEFAULTS = exports.STORAGE_KEYS = exports.ENDPOINTS = void 0;
10
+ // API Endpoints
11
+ exports.ENDPOINTS = {
12
+ AUTH: {
13
+ LOGIN: '/auth/login',
14
+ REGISTER: '/auth/register',
15
+ REFRESH: '/auth/refresh',
16
+ LOGOUT: '/auth/logout',
17
+ VALIDATE: '/auth/validate',
18
+ },
19
+ USERS: {
20
+ PROFILE: (id) => `/users/${id}`,
21
+ SESSIONS: '/users/sessions',
22
+ FOLLOWERS: (id) => `/users/${id}/followers`,
23
+ FOLLOWING: (id) => `/users/${id}/following`,
24
+ },
25
+ FILES: {
26
+ LIST: (userId) => `/files/list/${userId}`,
27
+ UPLOAD: '/files/upload',
28
+ DELETE: (fileId) => `/files/${fileId}`,
29
+ },
30
+ SUBSCRIPTION: {
31
+ GET: (userId) => `/subscriptions/${userId}`,
32
+ UPDATE: (userId) => `/subscriptions/${userId}`,
33
+ CANCEL: (userId) => `/subscriptions/${userId}`,
34
+ }
35
+ };
36
+ // Storage Keys
37
+ exports.STORAGE_KEYS = {
38
+ ACCESS_TOKEN: '@oxy/access_token',
39
+ REFRESH_TOKEN: '@oxy/refresh_token',
40
+ USER: '@oxy/user',
41
+ USER_ID: '@oxy/user_id',
42
+ SESSIONS: '@oxy/sessions'
43
+ };
44
+ // Default values
45
+ exports.DEFAULTS = {
46
+ SESSION_EXPIRE_TIME: 7 * 24 * 60 * 60 * 1000, // 7 days
47
+ CACHE_TIMEOUT: 5 * 60 * 1000, // 5 minutes
48
+ MAX_FILES: 5,
49
+ MAX_UPLOAD_SIZE: 10 * 1024 * 1024, // 10MB
50
+ ALLOWED_FILE_TYPES: ['image/', 'video/', 'application/pdf'],
51
+ };
52
+ // Error messages
53
+ exports.ERROR_MESSAGES = {
54
+ DEFAULT: 'An error occurred. Please try again.',
55
+ NETWORK: 'Network error. Please check your connection.',
56
+ UNAUTHORIZED: 'Session expired. Please sign in again.',
57
+ VALIDATION: 'Please check the form for errors.',
58
+ FILE_SIZE: 'File too large. Maximum size is 10MB.',
59
+ FILE_TYPE: 'Invalid file type.',
60
+ SESSION_EXPIRED: 'Your session has expired. Please sign in again.'
61
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * OxyHQ Services Hooks
3
+ *
4
+ * This file exports all hooks for use with OxyHQ services module.
5
+ * These hooks provide React-friendly interfaces to the underlying services.
6
+ */
7
+ export { useAuth } from './useAuth';
8
+ export { useSession } from './useSession';
9
+ export { useProfile } from './useProfile';
10
+ export { useFiles } from './useFiles';
11
+ export { useSubscription } from './useSubscription';
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * OxyHQ Services Hooks
4
+ *
5
+ * This file exports all hooks for use with OxyHQ services module.
6
+ * These hooks provide React-friendly interfaces to the underlying services.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.useSubscription = exports.useFiles = exports.useProfile = exports.useSession = exports.useAuth = void 0;
10
+ // Authentication and Session Management
11
+ var useAuth_1 = require("./useAuth");
12
+ Object.defineProperty(exports, "useAuth", { enumerable: true, get: function () { return useAuth_1.useAuth; } });
13
+ var useSession_1 = require("./useSession");
14
+ Object.defineProperty(exports, "useSession", { enumerable: true, get: function () { return useSession_1.useSession; } });
15
+ // Profile Management
16
+ var useProfile_1 = require("./useProfile");
17
+ Object.defineProperty(exports, "useProfile", { enumerable: true, get: function () { return useProfile_1.useProfile; } });
18
+ // File Management
19
+ var useFiles_1 = require("./useFiles");
20
+ Object.defineProperty(exports, "useFiles", { enumerable: true, get: function () { return useFiles_1.useFiles; } });
21
+ // Subscription Management
22
+ var useSubscription_1 = require("./useSubscription");
23
+ Object.defineProperty(exports, "useSubscription", { enumerable: true, get: function () { return useSubscription_1.useSubscription; } });
@@ -0,0 +1,6 @@
1
+ import type { User } from '../services/auth.service';
2
+ export declare function useAuth(): {
3
+ token: string | null;
4
+ user: User | null;
5
+ isAuthenticated: boolean;
6
+ };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAuth = useAuth;
4
+ const react_1 = require("react");
5
+ const SessionProvider_1 = require("../components/SessionProvider");
6
+ function useAuth() {
7
+ var _a;
8
+ const context = (0, react_1.useContext)(SessionProvider_1.SessionContext);
9
+ if (!context) {
10
+ throw new Error('useAuth must be used within a SessionProvider');
11
+ }
12
+ return {
13
+ token: ((_a = context.state.user) === null || _a === void 0 ? void 0 : _a.id) ? 'secured' : null,
14
+ user: context.state.user,
15
+ isAuthenticated: !!context.state.user,
16
+ };
17
+ }
@@ -0,0 +1,10 @@
1
+ import { FileType, UseFilesOptions } from '../components/FileSelectorModal/types';
2
+ export declare function useFiles({ fileTypeFilter, maxFiles, userId }?: UseFilesOptions): {
3
+ files: FileType[];
4
+ loading: boolean;
5
+ uploading: boolean;
6
+ error: string | null;
7
+ fetchFiles: (forceRefresh?: boolean) => Promise<void>;
8
+ uploadFiles: () => Promise<void>;
9
+ deleteFile: (fileId: string) => Promise<void>;
10
+ };
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.useFiles = useFiles;
46
+ const react_1 = require("react");
47
+ const react_i18next_1 = require("react-i18next");
48
+ const sonner_1 = require("sonner");
49
+ const ImagePicker = __importStar(require("expo-image-picker"));
50
+ const DocumentPicker = __importStar(require("expo-document-picker"));
51
+ const react_native_1 = require("react-native");
52
+ const api_1 = __importStar(require("../utils/api"));
53
+ const storage_1 = require("../utils/storage");
54
+ const api_2 = require("../utils/api");
55
+ const SessionProvider_1 = require("../components/SessionProvider");
56
+ const constants_1 = require("../constants");
57
+ // Cache for files to improve performance across component instances
58
+ const globalFileCache = new Map();
59
+ // Cache expiration time (5 minutes)
60
+ const CACHE_EXPIRATION = 5 * 60 * 1000;
61
+ // Error handling utility
62
+ const handleFileError = (error, t, context) => {
63
+ var _a, _b;
64
+ console.error(`[Files][${context}] Error:`, error);
65
+ let errorMessage = t("An error occurred");
66
+ if ((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) {
67
+ errorMessage = error.response.data.message;
68
+ }
69
+ else if (error === null || error === void 0 ? void 0 : error.message) {
70
+ errorMessage = error.message;
71
+ }
72
+ sonner_1.toast.error(errorMessage);
73
+ };
74
+ function useFiles({ fileTypeFilter = [], maxFiles = 5, userId } = {}) {
75
+ const [files, setFiles] = (0, react_1.useState)([]);
76
+ const [loading, setLoading] = (0, react_1.useState)(true);
77
+ const [uploading, setUploading] = (0, react_1.useState)(false);
78
+ const [error, setError] = (0, react_1.useState)(null);
79
+ const { t } = (0, react_i18next_1.useTranslation)();
80
+ const sessionContext = (0, react_1.useContext)(SessionProvider_1.SessionContext);
81
+ // Use a ref to track the abort controller for fetch operations
82
+ const abortControllerRef = (0, react_1.useRef)(null);
83
+ // Use a ref to track the current user ID for cleanup
84
+ const currentUserIdRef = (0, react_1.useRef)(userId);
85
+ // Memoize the effective user ID
86
+ const effectiveUserId = (0, react_1.useMemo)(() => userId || (sessionContext === null || sessionContext === void 0 ? void 0 : sessionContext.getCurrentUserId()) || undefined, [userId, sessionContext]);
87
+ // Update the ref when userId changes
88
+ (0, react_1.useEffect)(() => {
89
+ currentUserIdRef.current = userId;
90
+ }, [userId]);
91
+ // Cleanup function for component unmount
92
+ (0, react_1.useEffect)(() => {
93
+ return () => {
94
+ if (abortControllerRef.current) {
95
+ abortControllerRef.current.abort();
96
+ }
97
+ };
98
+ }, []);
99
+ // Generate cache key based on user ID and file type filter
100
+ const getCacheKey = (0, react_1.useCallback)((uid) => `${uid}-${fileTypeFilter.join(',')}`, [fileTypeFilter]);
101
+ const fetchFiles = (0, react_1.useCallback)((...args_1) => __awaiter(this, [...args_1], void 0, function* (forceRefresh = false) {
102
+ var _a, _b;
103
+ if (!effectiveUserId) {
104
+ console.warn('[Files] No user ID available');
105
+ setFiles([]);
106
+ setLoading(false);
107
+ setError("User not authenticated");
108
+ return;
109
+ }
110
+ try {
111
+ setError(null);
112
+ const accessToken = yield (0, storage_1.getSecureData)(constants_1.STORAGE_KEYS.ACCESS_TOKEN);
113
+ const refreshToken = yield (0, storage_1.getSecureData)(constants_1.STORAGE_KEYS.REFRESH_TOKEN);
114
+ if (!accessToken || !refreshToken) {
115
+ console.warn('[Files] Missing auth tokens');
116
+ setFiles([]);
117
+ setLoading(false);
118
+ setError("Authentication required");
119
+ return;
120
+ }
121
+ // Check cache first
122
+ const cacheKey = getCacheKey(effectiveUserId);
123
+ const cachedData = globalFileCache.get(cacheKey);
124
+ const now = Date.now();
125
+ if (!forceRefresh && cachedData && (now - cachedData.timestamp < CACHE_EXPIRATION)) {
126
+ console.log('[Files] Using cached files data');
127
+ setFiles(cachedData.files);
128
+ setLoading(false);
129
+ return;
130
+ }
131
+ console.log('[Files] Fetching files for user:', effectiveUserId);
132
+ setLoading(true);
133
+ // Cancel any in-progress requests
134
+ if (abortControllerRef.current) {
135
+ abortControllerRef.current.abort();
136
+ }
137
+ abortControllerRef.current = new AbortController();
138
+ const signal = abortControllerRef.current.signal;
139
+ // Attempt token refresh only if needed
140
+ const isValid = yield (0, api_1.validateSession)().catch(() => false);
141
+ if (!isValid) {
142
+ console.log('[Files] Session invalid, refreshing token');
143
+ try {
144
+ yield (0, api_2.refreshAccessToken)();
145
+ }
146
+ catch (refreshError) {
147
+ console.error('[Files] Token refresh failed:', refreshError);
148
+ setFiles([]);
149
+ setLoading(false);
150
+ setError("Session expired");
151
+ return;
152
+ }
153
+ }
154
+ const response = yield api_1.default.get(`/files/list/${effectiveUserId}`, {
155
+ signal,
156
+ params: forceRefresh ? { _t: Date.now() } : undefined
157
+ });
158
+ let fetchedFiles = response.data;
159
+ if (fileTypeFilter.length > 0) {
160
+ fetchedFiles = fetchedFiles.filter((file) => fileTypeFilter.some(type => file.contentType.startsWith(type)));
161
+ }
162
+ // Sort files by upload date (newest first)
163
+ fetchedFiles.sort((a, b) => {
164
+ const dateA = a.uploadDate || '';
165
+ const dateB = b.uploadDate || '';
166
+ return new Date(dateB).getTime() - new Date(dateA).getTime();
167
+ });
168
+ globalFileCache.set(cacheKey, {
169
+ files: fetchedFiles,
170
+ timestamp: now,
171
+ userId: effectiveUserId
172
+ });
173
+ if (currentUserIdRef.current === userId) {
174
+ setFiles(fetchedFiles);
175
+ setError(null);
176
+ }
177
+ }
178
+ catch (error) {
179
+ if (error.name === 'AbortError') {
180
+ console.log('[Files] Fetch aborted');
181
+ return;
182
+ }
183
+ handleFileError(error, t, 'fetchFiles');
184
+ setFiles([]);
185
+ setError(((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || t("Error fetching files"));
186
+ }
187
+ finally {
188
+ if (currentUserIdRef.current === userId) {
189
+ setLoading(false);
190
+ }
191
+ }
192
+ }), [effectiveUserId, fileTypeFilter, t, getCacheKey, userId]);
193
+ const uploadFiles = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
194
+ var _a, _b, _c;
195
+ if (!effectiveUserId) {
196
+ sonner_1.toast.error(t("User not authenticated"));
197
+ setError("User not authenticated");
198
+ return;
199
+ }
200
+ try {
201
+ setError(null);
202
+ const accessToken = yield (0, storage_1.getSecureData)(constants_1.STORAGE_KEYS.ACCESS_TOKEN);
203
+ if (!accessToken) {
204
+ sonner_1.toast.error(t("Authentication required"));
205
+ setError("Authentication required");
206
+ return;
207
+ }
208
+ let result;
209
+ if (fileTypeFilter.includes("image/") || fileTypeFilter.includes("video/")) {
210
+ result = yield ImagePicker.launchImageLibraryAsync({
211
+ mediaTypes: fileTypeFilter.includes("video/") ?
212
+ ImagePicker.MediaTypeOptions.All :
213
+ ImagePicker.MediaTypeOptions.Images,
214
+ allowsMultipleSelection: true,
215
+ quality: 0.8,
216
+ exif: false
217
+ });
218
+ }
219
+ else {
220
+ result = yield DocumentPicker.getDocumentAsync({
221
+ type: fileTypeFilter.length > 0 ? fileTypeFilter.map(type => `${type}*`).join(",") : "*/*",
222
+ multiple: true,
223
+ copyToCacheDirectory: true
224
+ });
225
+ }
226
+ if (!result.canceled && result.assets && result.assets.length > 0) {
227
+ setUploading(true);
228
+ const formData = new FormData();
229
+ // Limit the number of files to upload
230
+ const assetsToUpload = result.assets.slice(0, maxFiles);
231
+ for (const asset of assetsToUpload) {
232
+ const fileUri = react_native_1.Platform.OS === 'ios' ? asset.uri.replace('file://', '') : asset.uri;
233
+ let fileName;
234
+ let fileType;
235
+ if ('mimeType' in asset) {
236
+ fileName = asset.name;
237
+ fileType = asset.mimeType || 'application/octet-stream';
238
+ }
239
+ else {
240
+ const extension = fileUri.split('.').pop() || 'jpg';
241
+ fileName = `image-${Date.now()}.${extension}`;
242
+ fileType = `image/${extension}`;
243
+ }
244
+ try {
245
+ const response = yield fetch(fileUri);
246
+ const blob = yield response.blob();
247
+ const file = new File([blob], fileName, { type: fileType });
248
+ formData.append('files', file);
249
+ }
250
+ catch (error) {
251
+ console.error('Error processing file:', error);
252
+ sonner_1.toast.error(t("Error processing file"));
253
+ setUploading(false);
254
+ setError("Error processing file");
255
+ return;
256
+ }
257
+ }
258
+ const response = yield api_1.default.post('/files/upload', formData, {
259
+ headers: {
260
+ 'Accept': 'application/json',
261
+ 'Content-Type': 'multipart/form-data',
262
+ 'Authorization': `Bearer ${accessToken}`
263
+ },
264
+ transformRequest: [(data) => data],
265
+ onUploadProgress: (progressEvent) => {
266
+ const percentCompleted = Math.round((progressEvent.loaded * 100) / (progressEvent.total || 1));
267
+ console.log(`Upload progress: ${percentCompleted}%`);
268
+ }
269
+ });
270
+ if ((_a = response.data) === null || _a === void 0 ? void 0 : _a.files) {
271
+ sonner_1.toast.success(t("Files uploaded successfully"));
272
+ // Invalidate cache for this user
273
+ const cacheKey = getCacheKey(effectiveUserId);
274
+ globalFileCache.delete(cacheKey);
275
+ // Refresh files list
276
+ yield fetchFiles(true);
277
+ setError(null);
278
+ }
279
+ }
280
+ }
281
+ catch (error) {
282
+ handleFileError(error, t, 'uploadFiles');
283
+ setError(((_c = (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || t("Error uploading files"));
284
+ }
285
+ finally {
286
+ setUploading(false);
287
+ }
288
+ }), [effectiveUserId, fileTypeFilter, maxFiles, t, fetchFiles, getCacheKey]);
289
+ const deleteFile = (0, react_1.useCallback)((fileId) => __awaiter(this, void 0, void 0, function* () {
290
+ var _a, _b, _c;
291
+ if (!fileId) {
292
+ sonner_1.toast.error(t("Invalid file ID"));
293
+ return;
294
+ }
295
+ try {
296
+ setError(null);
297
+ const response = yield api_1.default.delete(`/files/${fileId}`);
298
+ if ((_a = response.data) === null || _a === void 0 ? void 0 : _a.success) {
299
+ sonner_1.toast.success(t("File deleted successfully"));
300
+ // Update local state
301
+ setFiles(prevFiles => prevFiles.filter(file => file._id !== fileId));
302
+ // Invalidate cache for this user
303
+ if (effectiveUserId) {
304
+ const cacheKey = getCacheKey(effectiveUserId);
305
+ globalFileCache.delete(cacheKey);
306
+ }
307
+ }
308
+ }
309
+ catch (error) {
310
+ handleFileError(error, t, 'deleteFile');
311
+ setError(((_c = (_b = error === null || error === void 0 ? void 0 : error.response) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.message) || t("Error deleting file"));
312
+ }
313
+ }), [effectiveUserId, t, getCacheKey]);
314
+ // Load files on mount and when dependencies change
315
+ (0, react_1.useEffect)(() => {
316
+ if (effectiveUserId) {
317
+ fetchFiles();
318
+ }
319
+ }, [effectiveUserId, fetchFiles]);
320
+ return {
321
+ files,
322
+ loading,
323
+ uploading,
324
+ error,
325
+ fetchFiles,
326
+ uploadFiles,
327
+ deleteFile
328
+ };
329
+ }
@@ -0,0 +1,13 @@
1
+ import { OxyProfile } from '../types';
2
+ export declare const useProfile: () => {
3
+ loading: boolean;
4
+ error: string | null;
5
+ getProfile: (id: string) => Promise<OxyProfile | null>;
6
+ updateProfile: (data: Partial<OxyProfile>) => Promise<OxyProfile | null>;
7
+ getFollowers: (userId: string) => Promise<OxyProfile[] | null>;
8
+ getFollowing: (userId: string) => Promise<OxyProfile[] | null>;
9
+ followUser: (userId: string) => Promise<boolean>;
10
+ unfollowUser: (userId: string) => Promise<boolean>;
11
+ getFollowingStatus: (userId: string) => Promise<boolean>;
12
+ getIdByUsername: (username: string) => Promise<string | null>;
13
+ };