@oxyhq/services 5.13.26 → 5.13.27
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 +5 -6
- package/lib/commonjs/core/OxyServices.js +2 -2
- package/lib/commonjs/core/mixins/OxyServices.assets.js +0 -7
- package/lib/commonjs/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/commonjs/index.js +15 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileCard.js +5 -1
- package/lib/commonjs/ui/components/ProfileCard.js.map +1 -1
- package/lib/commonjs/ui/hooks/index.js +13 -0
- package/lib/commonjs/ui/hooks/index.js.map +1 -1
- package/lib/commonjs/ui/hooks/useFileDownloadUrl.js +103 -0
- package/lib/commonjs/ui/hooks/useFileDownloadUrl.js.map +1 -0
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js +0 -3
- package/lib/commonjs/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/module/core/OxyServices.js +2 -2
- package/lib/module/core/mixins/OxyServices.assets.js +0 -7
- package/lib/module/core/mixins/OxyServices.assets.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/components/ProfileCard.js +5 -1
- package/lib/module/ui/components/ProfileCard.js.map +1 -1
- package/lib/module/ui/hooks/index.js +1 -0
- package/lib/module/ui/hooks/index.js.map +1 -1
- package/lib/module/ui/hooks/useFileDownloadUrl.js +97 -0
- package/lib/module/ui/hooks/useFileDownloadUrl.js.map +1 -0
- package/lib/module/ui/screens/AccountOverviewScreen.js +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js +1 -4
- package/lib/module/ui/screens/karma/KarmaFAQScreen.js.map +1 -1
- package/lib/typescript/core/OxyServices.d.ts +2 -2
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts +0 -4
- package/lib/typescript/core/mixins/OxyServices.assets.d.ts.map +1 -1
- package/lib/typescript/core/mixins/index.d.ts +0 -1
- package/lib/typescript/core/mixins/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/ProfileCard.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/index.d.ts +1 -0
- package/lib/typescript/ui/hooks/index.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useFileDownloadUrl.d.ts +19 -0
- package/lib/typescript/ui/hooks/useFileDownloadUrl.d.ts.map +1 -0
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/karma/KarmaFAQScreen.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/OxyServices.ts +2 -2
- package/src/core/mixins/OxyServices.assets.ts +0 -7
- package/src/index.ts +1 -0
- package/src/ui/components/ProfileCard.tsx +4 -1
- package/src/ui/hooks/index.ts +2 -1
- package/src/ui/hooks/useFileDownloadUrl.ts +118 -0
- package/src/ui/screens/AccountOverviewScreen.tsx +4 -1
- package/src/ui/screens/karma/KarmaFAQScreen.tsx +1 -5
package/src/core/OxyServices.ts
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
* const file = fileInput.files[0];
|
|
23
23
|
* await oxy.uploadRawFile(file);
|
|
24
24
|
*
|
|
25
|
-
* // Get a file
|
|
26
|
-
* const url = oxy.
|
|
25
|
+
* // Get a file download URL for <img src>
|
|
26
|
+
* const url = oxy.getFileDownloadUrl('fileId', 'thumb');
|
|
27
27
|
* ```
|
|
28
28
|
*
|
|
29
29
|
* ## Node.js (CommonJS/TypeScript)
|
|
@@ -66,13 +66,6 @@ export function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>(Base: T
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/**
|
|
70
|
-
* Get file stream URL (direct Oxy Cloud/CDN URL, no token)
|
|
71
|
-
*/
|
|
72
|
-
getFileStreamUrl(fileId: string): string {
|
|
73
|
-
return `${this.getCloudURL()}/files/${fileId}/stream`;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
69
|
/**
|
|
77
70
|
* List user files
|
|
78
71
|
*/
|
package/src/index.ts
CHANGED
|
@@ -97,6 +97,7 @@ export { useAuthStore } from './ui/stores/authStore';
|
|
|
97
97
|
export { useAssetStore, useAssets as useAssetsStore, useAsset, useUploadProgress, useAssetLoading, useAssetErrors, useAssetsByApp, useAssetsByEntity, useAssetUsageCount, useIsAssetLinked } from './ui/stores/assetStore';
|
|
98
98
|
export { useSessionSocket } from './ui/hooks/useSessionSocket';
|
|
99
99
|
export { useAssets, setOxyAssetInstance } from './ui/hooks/useAssets';
|
|
100
|
+
export { useFileDownloadUrl, setOxyFileUrlInstance } from './ui/hooks/useFileDownloadUrl';
|
|
100
101
|
|
|
101
102
|
// UI components
|
|
102
103
|
export { OxySignInButton } from './ui/components/OxySignInButton';
|
|
@@ -4,6 +4,7 @@ import { Ionicons } from '@expo/vector-icons';
|
|
|
4
4
|
import { useI18n } from '../hooks/useI18n';
|
|
5
5
|
import Avatar from './Avatar';
|
|
6
6
|
import { useOxy } from '../context/OxyContext';
|
|
7
|
+
import { useFileDownloadUrl } from '../hooks';
|
|
7
8
|
import { fontFamilies } from '../styles/fonts';
|
|
8
9
|
|
|
9
10
|
interface ProfileCardProps {
|
|
@@ -33,6 +34,8 @@ const ProfileCard: React.FC<ProfileCardProps> = ({
|
|
|
33
34
|
const secondaryBackgroundColor = isDarkTheme ? '#222222' : '#FFFFFF';
|
|
34
35
|
const primaryColor = '#0066CC';
|
|
35
36
|
|
|
37
|
+
const avatarUrl = useFileDownloadUrl(user?.avatar, { variant: 'thumb' }).url || undefined;
|
|
38
|
+
|
|
36
39
|
return (
|
|
37
40
|
<View style={styles.headerSection}>
|
|
38
41
|
<View style={[
|
|
@@ -43,7 +46,7 @@ const ProfileCard: React.FC<ProfileCardProps> = ({
|
|
|
43
46
|
]}>
|
|
44
47
|
<View style={styles.userProfile}>
|
|
45
48
|
<Avatar
|
|
46
|
-
uri={user?.avatar ?
|
|
49
|
+
uri={user?.avatar ? avatarUrl : undefined}
|
|
47
50
|
name={user?.name?.full || user?.username}
|
|
48
51
|
size={60}
|
|
49
52
|
theme={theme}
|
package/src/ui/hooks/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { useFollow, useFollowerCounts } from './useFollow';
|
|
1
|
+
export { useFollow, useFollowerCounts } from './useFollow';
|
|
2
|
+
export { useFileDownloadUrl, setOxyFileUrlInstance } from './useFileDownloadUrl';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { OxyServices } from '../../core/OxyServices';
|
|
3
|
+
|
|
4
|
+
let oxyInstance: OxyServices | null = null;
|
|
5
|
+
|
|
6
|
+
export const setOxyFileUrlInstance = (instance: OxyServices) => {
|
|
7
|
+
oxyInstance = instance;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface UseFileDownloadUrlOptions {
|
|
11
|
+
variant?: string;
|
|
12
|
+
expiresIn?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface UseFileDownloadUrlResult {
|
|
16
|
+
url: string | null;
|
|
17
|
+
loading: boolean;
|
|
18
|
+
error: Error | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook to resolve a file's download URL asynchronously.
|
|
23
|
+
*
|
|
24
|
+
* Prefers `getFileDownloadUrlAsync` and falls back to the synchronous
|
|
25
|
+
* `getFileDownloadUrl` helper if the async call fails.
|
|
26
|
+
*/
|
|
27
|
+
export const useFileDownloadUrl = (
|
|
28
|
+
fileId?: string | null,
|
|
29
|
+
options?: UseFileDownloadUrlOptions
|
|
30
|
+
): UseFileDownloadUrlResult => {
|
|
31
|
+
const [url, setUrl] = useState<string | null>(null);
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
33
|
+
const [error, setError] = useState<Error | null>(null);
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (!fileId) {
|
|
37
|
+
setUrl(null);
|
|
38
|
+
setLoading(false);
|
|
39
|
+
setError(null);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!oxyInstance) {
|
|
44
|
+
// Fail silently but don't crash the UI – caller can decide what to do with null URL.
|
|
45
|
+
setUrl(null);
|
|
46
|
+
setLoading(false);
|
|
47
|
+
setError(new Error('OxyServices instance not configured for useFileDownloadUrl'));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let cancelled = false;
|
|
52
|
+
|
|
53
|
+
const load = async () => {
|
|
54
|
+
setLoading(true);
|
|
55
|
+
setError(null);
|
|
56
|
+
|
|
57
|
+
// Store instance in local variable for TypeScript null checking
|
|
58
|
+
const instance = oxyInstance;
|
|
59
|
+
if (!instance) {
|
|
60
|
+
setLoading(false);
|
|
61
|
+
setError(new Error('OxyServices instance not configured for useFileDownloadUrl'));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const { variant, expiresIn } = options || {};
|
|
67
|
+
let resolvedUrl: string | null = null;
|
|
68
|
+
|
|
69
|
+
if (typeof instance.getFileDownloadUrlAsync === 'function') {
|
|
70
|
+
resolvedUrl = await instance.getFileDownloadUrlAsync(fileId, variant, expiresIn);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!resolvedUrl && typeof instance.getFileDownloadUrl === 'function') {
|
|
74
|
+
resolvedUrl = instance.getFileDownloadUrl(fileId, variant, expiresIn);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!cancelled) {
|
|
78
|
+
setUrl(resolvedUrl || null);
|
|
79
|
+
}
|
|
80
|
+
} catch (err: any) {
|
|
81
|
+
// Fallback to sync URL on error where possible
|
|
82
|
+
try {
|
|
83
|
+
if (typeof instance.getFileDownloadUrl === 'function') {
|
|
84
|
+
const { variant, expiresIn } = options || {};
|
|
85
|
+
const fallbackUrl = instance.getFileDownloadUrl(fileId, variant, expiresIn);
|
|
86
|
+
if (!cancelled) {
|
|
87
|
+
setUrl(fallbackUrl || null);
|
|
88
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
} catch {
|
|
93
|
+
// ignore secondary failure, we'll surface the original error below
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!cancelled) {
|
|
97
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
if (!cancelled) {
|
|
101
|
+
setLoading(false);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
load();
|
|
107
|
+
|
|
108
|
+
return () => {
|
|
109
|
+
cancelled = true;
|
|
110
|
+
};
|
|
111
|
+
}, [fileId, options?.variant, options?.expiresIn]);
|
|
112
|
+
|
|
113
|
+
return { url, loading, error };
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
@@ -420,7 +420,10 @@ const AccountOverviewScreen: React.FC<BaseScreenProps> = ({
|
|
|
420
420
|
<>
|
|
421
421
|
<View style={styles.userIcon}>
|
|
422
422
|
{account.avatar ? (
|
|
423
|
-
<Image
|
|
423
|
+
<Image
|
|
424
|
+
source={{ uri: oxyServices.getFileDownloadUrl(account.avatar as string, 'thumb') }}
|
|
425
|
+
style={styles.accountAvatarImage}
|
|
426
|
+
/>
|
|
424
427
|
) : (
|
|
425
428
|
<View style={styles.accountAvatarFallback}>
|
|
426
429
|
<Text style={styles.accountAvatarText}>
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import React, { useState, useMemo, useCallback } from 'react';
|
|
2
|
-
import { View, Text, StyleSheet, ScrollView, Platform, TouchableOpacity, TextInput, LayoutAnimation
|
|
2
|
+
import { View, Text, StyleSheet, ScrollView, Platform, TouchableOpacity, TextInput, LayoutAnimation } from 'react-native';
|
|
3
3
|
import type { BaseScreenProps } from '../../navigation/types';
|
|
4
4
|
import { Ionicons } from '@expo/vector-icons';
|
|
5
5
|
import { Header } from '../../components';
|
|
6
6
|
import { useI18n } from '../../hooks/useI18n';
|
|
7
7
|
|
|
8
|
-
if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
|
|
9
|
-
UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
8
|
const FAQ_KEYS = ['what', 'earn', 'lose', 'use', 'transfer', 'support'] as const;
|
|
13
9
|
|
|
14
10
|
/**
|