Files
digital-pilates/hooks/useCosUpload.ts
richarjiang 4627cb650e feat(ui): 更新应用图标和启动屏幕为新品牌标识并调整相关配置
更新应用图标、启动屏幕和相关配置以匹配新品牌标识,移除旧的 Sealife 图标文件并替换为新的 icon.icon 资源。同时更新 iOS 配置中的背景任务标识符以符合命名规范。调整统计页面头部 logo 尺寸和字体粗细以优化视觉效果。

- 替换所有平台的应用图标和启动图资源
- 更新 app.json、Info.plist 和各 imageset 配置文件
- 调整 statistics.tsx 中的 logo 样式
- 移除已废弃的腾讯云 COS 文档
2025-09-12 17:07:40 +08:00

85 lines
3.2 KiB
TypeScript

import { buildCosKey, buildPublicUrl } from '@/constants/Cos';
import { uploadWithRetry } from '@/services/cos';
import { useCallback, useMemo, useRef, useState } from 'react';
import { Platform } from 'react-native';
export type UseCosUploadOptions = {
prefix?: string;
userId?: string;
contentType?: string;
};
export function useCosUpload(defaultOptions?: UseCosUploadOptions) {
const abortRef = useRef<AbortController | null>(null);
const [progress, setProgress] = useState(0);
const [uploading, setUploading] = useState(false);
const cancel = useCallback(() => {
abortRef.current?.abort();
}, []);
const upload = useCallback(
async (file: { uri?: string; name?: string; type?: string; buffer?: any; blob?: Blob } | Blob | string | any, options?: UseCosUploadOptions) => {
const finalOptions = { ...(defaultOptions || {}), ...(options || {}) };
const extGuess = (() => {
const name = (file && (file.name || (file as any).filename)) || '';
const match = name.match(/\.([a-zA-Z0-9]+)$/);
return match ? match[1] : undefined;
})();
const key = buildCosKey({ prefix: finalOptions.prefix, userId: finalOptions.userId, ext: extGuess });
const controller = new AbortController();
abortRef.current = controller;
setProgress(0);
setUploading(true);
try {
let res: any;
if (Platform.OS === 'web') {
let body: any = null;
if (typeof file === 'string') {
// 允许直接传 Base64/DataURL 字符串
body = file;
} else if ((file as any)?.blob) {
body = (file as any).blob;
} else if ((file as any)?.uri) {
const resp = await fetch((file as any).uri);
body = await resp.blob();
} else if (typeof Blob !== 'undefined' && file instanceof Blob) {
body = file;
} else {
throw new Error('无效的文件:请提供 uri 或 Blob');
}
res = await uploadWithRetry({
key,
body,
contentType: finalOptions.contentType || (file as any)?.type,
signal: controller.signal,
onProgress: ({ percent }: { percent: number }) => setProgress(percent),
} as any);
} else {
// 原生:直接传本地路径
const srcUri = (file as any)?.uri || (typeof file === 'string' ? file : undefined);
if (!srcUri || typeof srcUri !== 'string') {
throw new Error('请提供包含 uri 的对象,或传入本地文件路径字符串');
}
res = await uploadWithRetry({
key,
srcUri,
contentType: finalOptions.contentType || (file as any)?.type,
signal: controller.signal,
onProgress: ({ percent }: { percent: number }) => setProgress(percent),
} as any);
}
const url = (res as any).publicUrl || buildPublicUrl(res.key);
return { key: res.key, url };
} finally {
setUploading(false);
}
},
[defaultOptions]
);
return useMemo(() => ({ upload, cancel, progress, uploading }), [upload, cancel, progress, uploading]);
}