@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.
- package/README.md +269 -79
- package/dist/components/AuthBottomSheet/types.d.ts +24 -0
- package/dist/components/AuthBottomSheet/types.js +2 -0
- package/dist/components/FileSelectorModal/types.d.ts +35 -0
- package/dist/components/FileSelectorModal/types.js +2 -0
- package/dist/components/SessionProvider.d.ts +26 -0
- package/dist/components/SessionProvider.js +367 -0
- package/dist/config.d.ts +169 -0
- package/dist/config.js +115 -0
- package/dist/constants.d.ts +54 -0
- package/dist/constants.js +61 -0
- package/dist/hooks/index.d.ts +11 -0
- package/dist/hooks/index.js +23 -0
- package/dist/hooks/useAuth.d.ts +6 -0
- package/dist/hooks/useAuth.js +17 -0
- package/dist/hooks/useFiles.d.ts +10 -0
- package/dist/hooks/useFiles.js +329 -0
- package/dist/hooks/useProfile.d.ts +13 -0
- package/dist/hooks/useProfile.js +154 -0
- package/dist/hooks/useSession.d.ts +2 -0
- package/dist/hooks/useSession.js +12 -0
- package/dist/hooks/useSubscription.d.ts +15 -0
- package/dist/hooks/useSubscription.js +85 -0
- package/dist/index.d.ts +28 -7
- package/dist/index.js +82 -6
- package/dist/package.json +71 -0
- package/dist/reducers/index.d.ts +8 -0
- package/dist/reducers/index.js +29 -0
- package/dist/reducers/profileReducer.d.ts +55 -0
- package/dist/reducers/profileReducer.js +136 -0
- package/dist/services/OxyClient.d.ts +84 -0
- package/dist/services/OxyClient.js +309 -0
- package/dist/services/api.service.d.ts +61 -0
- package/dist/services/api.service.js +289 -0
- package/dist/services/auth.service.d.ts +87 -0
- package/dist/services/auth.service.js +266 -0
- package/dist/services/index.d.ts +30 -0
- package/dist/services/index.js +88 -0
- package/dist/services/payment.service.d.ts +20 -0
- package/dist/services/payment.service.js +56 -0
- package/dist/services/privacy.service.d.ts +16 -0
- package/dist/services/privacy.service.js +69 -0
- package/dist/services/profile.service.d.ts +20 -0
- package/dist/services/profile.service.js +158 -0
- package/dist/services/subscription.service.d.ts +7 -0
- package/dist/services/subscription.service.js +46 -0
- package/dist/services/user.service.d.ts +25 -0
- package/dist/services/user.service.js +109 -0
- package/dist/styles/colors.d.ts +24 -0
- package/dist/styles/colors.js +31 -0
- package/dist/styles/shared.d.ts +168 -0
- package/dist/styles/shared.js +177 -0
- package/dist/types/index.d.ts +136 -2
- package/dist/types/index.js +7 -1
- package/dist/utils/api.d.ts +20 -0
- package/dist/utils/api.js +546 -0
- package/dist/utils/authEvents.d.ts +44 -0
- package/dist/utils/authEvents.js +73 -0
- package/dist/utils/errorHandler.d.ts +68 -0
- package/dist/utils/errorHandler.js +166 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.js +41 -0
- package/dist/utils/logger.d.ts +100 -0
- package/dist/utils/logger.js +298 -0
- package/dist/utils/socket.d.ts +6 -0
- package/dist/utils/socket.js +179 -0
- package/dist/utils/socketConfig.d.ts +32 -0
- package/dist/utils/socketConfig.js +67 -0
- package/dist/utils/storage.d.ts +54 -0
- package/dist/utils/storage.js +253 -0
- package/package.json +71 -59
- package/dist/assets/dot-icon.d.ts +0 -3
- package/dist/assets/dot-icon.d.ts.map +0 -1
- package/dist/assets/dot-icon.js +0 -6
- package/dist/assets/verified-icon.d.ts +0 -3
- package/dist/assets/verified-icon.d.ts.map +0 -1
- package/dist/assets/verified-icon.js +0 -10
- package/dist/components/assets/oxy-logo.d.ts +0 -3
- package/dist/components/assets/oxy-logo.d.ts.map +0 -1
- package/dist/components/assets/oxy-logo.js +0 -30
- package/dist/components/auth/AccountSwitcherModal.d.ts +0 -7
- package/dist/components/auth/AccountSwitcherModal.d.ts.map +0 -1
- package/dist/components/auth/AccountSwitcherModal.js +0 -91
- package/dist/components/auth/SessionOwnerButton.d.ts +0 -3
- package/dist/components/auth/SessionOwnerButton.d.ts.map +0 -1
- package/dist/components/auth/SessionOwnerButton.js +0 -35
- package/dist/components/auth/SignInButton.d.ts +0 -8
- package/dist/components/auth/SignInButton.d.ts.map +0 -1
- package/dist/components/auth/SignInButton.js +0 -15
- package/dist/components/auth/styles/account-switcher-modal.module.css +0 -29
- package/dist/components/auth/styles/account-switcher-modal.module.css.map +0 -1
- package/dist/components/auth/styles/oavatar.module.css +0 -34
- package/dist/components/auth/styles/oavatar.module.css.map +0 -1
- package/dist/components/auth/styles/session-owner-modal.module.css +0 -35
- package/dist/components/auth/styles/session-owner-modal.module.css.map +0 -1
- package/dist/components/auth/styles/sign-in-button.module.css +0 -30
- package/dist/components/auth/styles/sign-in-button.module.css.map +0 -1
- package/dist/components/elements/button/components/button.d.ts +0 -7
- package/dist/components/elements/button/components/button.d.ts.map +0 -1
- package/dist/components/elements/button/components/button.js +0 -6
- package/dist/components/elements/button/components/styles/button.module.css +0 -25
- package/dist/components/elements/button/components/styles/button.module.css.map +0 -1
- package/dist/components/elements/button/index.d.ts +0 -2
- package/dist/components/elements/button/index.d.ts.map +0 -1
- package/dist/components/elements/button/index.js +0 -1
- package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.d.ts +0 -5
- package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.d.ts.map +0 -1
- package/dist/components/elements/ellipsis-wrapper/components/EllipsisWrapper.js +0 -4
- package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.d.ts +0 -5
- package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.d.ts.map +0 -1
- package/dist/components/elements/ellipsis-wrapper/components/ellipsis-wrapper.js +0 -4
- package/dist/components/elements/ellipsis-wrapper/components/styles/ellipses-wrapper.module.css +0 -11
- package/dist/components/elements/ellipsis-wrapper/components/styles/ellipses-wrapper.module.css.map +0 -1
- package/dist/components/elements/ellipsis-wrapper/index.d.ts +0 -2
- package/dist/components/elements/ellipsis-wrapper/index.d.ts.map +0 -1
- package/dist/components/elements/ellipsis-wrapper/index.js +0 -1
- package/dist/components/elements/modal/components/confirmation-modal.d.ts +0 -12
- package/dist/components/elements/modal/components/confirmation-modal.d.ts.map +0 -1
- package/dist/components/elements/modal/components/confirmation-modal.js +0 -21
- package/dist/components/elements/modal/components/modal.d.ts +0 -13
- package/dist/components/elements/modal/components/modal.d.ts.map +0 -1
- package/dist/components/elements/modal/components/modal.js +0 -111
- package/dist/components/elements/modal/components/styles/confirmation-modal.module.css +0 -105
- package/dist/components/elements/modal/components/styles/confirmation-modal.module.css.map +0 -1
- package/dist/components/elements/modal/components/styles/modal.module.css +0 -10
- package/dist/components/elements/modal/components/styles/modal.module.css.map +0 -1
- package/dist/components/elements/modal/hooks/use-track-position.d.ts +0 -5
- package/dist/components/elements/modal/hooks/use-track-position.d.ts.map +0 -1
- package/dist/components/elements/modal/hooks/use-track-position.js +0 -35
- package/dist/components/elements/modal/index.d.ts +0 -4
- package/dist/components/elements/modal/index.d.ts.map +0 -1
- package/dist/components/elements/modal/index.js +0 -3
- package/dist/config/index.d.ts +0 -21
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -7
- package/dist/features/profile/components/avatar.d.ts +0 -10
- package/dist/features/profile/components/avatar.d.ts.map +0 -1
- package/dist/features/profile/components/avatar.js +0 -7
- package/dist/features/profile/components/styles/avatar.module.css +0 -15
- package/dist/features/profile/components/styles/avatar.module.css.map +0 -1
- package/dist/features/profile/components/styles/user-name.module.css +0 -18
- package/dist/features/profile/components/styles/user-name.module.css.map +0 -1
- package/dist/features/profile/components/styles/user-username.module.css +0 -6
- package/dist/features/profile/components/styles/user-username.module.css.map +0 -1
- package/dist/features/profile/components/user-name.d.ts +0 -7
- package/dist/features/profile/components/user-name.d.ts.map +0 -1
- package/dist/features/profile/components/user-name.js +0 -8
- package/dist/features/profile/components/user-username.d.ts +0 -5
- package/dist/features/profile/components/user-username.d.ts.map +0 -1
- package/dist/features/profile/components/user-username.js +0 -7
- package/dist/features/profile/index.d.ts +0 -4
- package/dist/features/profile/index.d.ts.map +0 -1
- package/dist/features/profile/index.js +0 -3
- package/dist/hooks/get-user.d.ts +0 -2
- package/dist/hooks/get-user.d.ts.map +0 -1
- package/dist/hooks/get-user.js +0 -31
- package/dist/hooks/getClientKey.d.ts +0 -2
- package/dist/hooks/getClientKey.d.ts.map +0 -1
- package/dist/hooks/getClientKey.js +0 -19
- package/dist/hooks/getUserById.d.ts +0 -11
- package/dist/hooks/getUserById.d.ts.map +0 -1
- package/dist/hooks/getUserById.js +0 -31
- package/dist/hooks/use-user.d.ts +0 -14
- package/dist/hooks/use-user.d.ts.map +0 -1
- package/dist/hooks/use-user.js +0 -8
- package/dist/hooks/useCrossDomainStorage.d.ts +0 -6
- package/dist/hooks/useCrossDomainStorage.d.ts.map +0 -1
- package/dist/hooks/useCrossDomainStorage.js +0 -24
- package/dist/hooks/useOxySession.d.ts +0 -30
- package/dist/hooks/useOxySession.d.ts.map +0 -1
- package/dist/hooks/useOxySession.js +0 -64
- package/dist/index.css +0 -5
- package/dist/index.css.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/interfaces/index.d.ts +0 -10
- package/dist/interfaces/index.d.ts.map +0 -1
- package/dist/interfaces/index.js +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/utils/cn.d.ts +0 -3
- package/dist/utils/cn.d.ts.map +0 -1
- 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,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
|
+
};
|