129 lines
4.0 KiB
TypeScript
129 lines
4.0 KiB
TypeScript
import { fetchApi } from "@/lib/server-api-util";
|
|
import { Message } from "@/types/ask";
|
|
import * as FileSystem from 'expo-file-system';
|
|
import * as MediaLibrary from 'expo-media-library';
|
|
import { TFunction } from "i18next";
|
|
import { useCallback } from "react";
|
|
import { Alert } from 'react-native';
|
|
|
|
// 实现一个函数,从两个数组中轮流插入新数组
|
|
export const mergeArrays = (arr1: any[], arr2: any[]) => {
|
|
const result: any[] = [];
|
|
const maxLength = Math.max(arr1.length, arr2.length);
|
|
for (let i = 0; i < maxLength; i++) {
|
|
if (i < arr1.length) result.push(arr1[i]);
|
|
if (i < arr2.length) result.push(arr2[i]);
|
|
}
|
|
return result;
|
|
};
|
|
|
|
|
|
// 创建新对话并获取消息
|
|
export const createNewConversation = useCallback(async (user_text: string) => {
|
|
const data = await fetchApi<string>("/chat/new", {
|
|
method: "POST",
|
|
});
|
|
return data
|
|
}, []);
|
|
|
|
// 获取对话信息
|
|
export const getConversation = async ({
|
|
session_id,
|
|
user_text,
|
|
material_ids
|
|
}: {
|
|
session_id: string,
|
|
user_text: string,
|
|
material_ids: string[]
|
|
}): Promise<Message | undefined> => {
|
|
// 获取对话信息必须要有对话id
|
|
if (!session_id) return undefined;
|
|
|
|
try {
|
|
const response = await fetchApi<Message>(`/chat`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
session_id,
|
|
user_text,
|
|
material_ids
|
|
})
|
|
});
|
|
return response;
|
|
} catch (error) {
|
|
// console.error('Error in getConversation:', error);
|
|
return undefined;
|
|
}
|
|
};
|
|
|
|
// 图片 视频 保存到本地
|
|
export const saveMediaToGallery = async (mediaUrl: string, t: TFunction) => {
|
|
// 声明 fileUri 变量以便在 finally 块中使用
|
|
let fileUri: string | null = null;
|
|
|
|
try {
|
|
// 首先请求权限
|
|
const { status } = await MediaLibrary.requestPermissionsAsync();
|
|
|
|
if (status !== 'granted') {
|
|
Alert.alert(t("ask:ask.mediaAuth"), t("ask:ask.mediaAuthDesc"));
|
|
return false;
|
|
}
|
|
|
|
// 获取文件扩展名
|
|
const fileExtension = mediaUrl.split('.').pop()?.toLowerCase() || 'mp4';
|
|
const isVideo = ['mp4', 'mov', 'avi', 'mkv'].includes(fileExtension);
|
|
const fileName = `temp_${Date.now()}.${fileExtension}`;
|
|
fileUri = `${FileSystem.documentDirectory}${fileName}`;
|
|
|
|
// 下载文件
|
|
console.log('开始下载文件:', mediaUrl);
|
|
const downloadResumable = FileSystem.createDownloadResumable(
|
|
mediaUrl,
|
|
fileUri,
|
|
{},
|
|
(downloadProgress) => {
|
|
const progress = downloadProgress.totalBytesWritten / (downloadProgress.totalBytesExpectedToWrite || 1);
|
|
console.log(`下载进度: ${Math.round(progress * 100)}%`);
|
|
}
|
|
);
|
|
|
|
const downloadResult = await downloadResumable.downloadAsync();
|
|
|
|
if (!downloadResult) {
|
|
throw new Error('下载失败: 下载被取消或发生错误');
|
|
}
|
|
|
|
const { uri } = downloadResult;
|
|
console.log('文件下载完成,准备保存到相册:', uri);
|
|
|
|
// 保存到相册
|
|
const asset = await MediaLibrary.createAssetAsync(uri);
|
|
await MediaLibrary.createAlbumAsync(
|
|
'Memowake',
|
|
asset,
|
|
false
|
|
);
|
|
|
|
Alert.alert(
|
|
t("ask:ask.saveSuccess"),
|
|
isVideo ? t("ask:ask.videoSave") : t("ask:ask.imgSave")
|
|
);
|
|
return true;
|
|
} catch (error) {
|
|
console.log('保存失败:', error);
|
|
Alert.alert(
|
|
t("ask:ask.saveError"),
|
|
error instanceof Error ? error.message : t("ask:ask.saveError")
|
|
);
|
|
return false;
|
|
} finally {
|
|
// 清理临时文件
|
|
try {
|
|
if (fileUri) {
|
|
await FileSystem.deleteAsync(fileUri, { idempotent: true }).catch(console.warn);
|
|
}
|
|
} catch (cleanupError) {
|
|
console.log('清理临时文件时出错:', cleanupError);
|
|
}
|
|
}
|
|
}; |