diff --git a/components/ask/aiChat.tsx b/components/ask/aiChat.tsx
index de470a9..cd9db3e 100644
--- a/components/ask/aiChat.tsx
+++ b/components/ask/aiChat.tsx
@@ -5,7 +5,7 @@ import MoreSvg from "@/assets/icons/svg/more.svg";
import { Message, Video } from "@/types/ask";
import { MaterialItem } from "@/types/personal-info";
import { TFunction } from "i18next";
-import React from 'react';
+import React, { useState } from 'react';
import {
Image,
Pressable,
@@ -36,6 +36,7 @@ interface RenderMessageProps {
const MessageItem = ({ t, insets, item, sessionId, setModalVisible, modalVisible, setModalDetailsVisible, modalDetailsVisible, setSelectedImages, selectedImages }: RenderMessageProps) => {
const isUser = item.role === 'User';
+ const [cancel, setCancel] = useState(false);
return (
@@ -76,7 +77,7 @@ const MessageItem = ({ t, insets, item, sessionId, setModalVisible, modalVisible
items={[
{
svg: ,
- label: "保存",
+ label: t("ask:ask.save"),
onPress: () => {
const imageUrl = image?.preview_file_info?.url || image.video?.preview_file_info?.url;
if (imageUrl) {
@@ -87,11 +88,14 @@ const MessageItem = ({ t, insets, item, sessionId, setModalVisible, modalVisible
},
{
svg: ,
- label: "取消",
- onPress: () => console.log('取消'),
+ label: t("ask:ask.cancel"),
+ onPress: () => {
+ setCancel(true);
+ },
textStyle: { color: 'red' }
}
]}
+ cancel={cancel}
menuStyle={{
backgroundColor: 'white',
borderRadius: 8,
@@ -115,7 +119,6 @@ const MessageItem = ({ t, insets, item, sessionId, setModalVisible, modalVisible
loadingIndicatorSource={require('@/assets/images/png/placeholder.png')}
/>
-
))}
@@ -194,7 +197,7 @@ const styles = StyleSheet.create({
},
background: {
...StyleSheet.absoluteFillObject,
- backgroundColor: 'rgba(0, 0, 0, 0.5)', // 添加半透明黑色背景
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
},
centeredView: {
flex: 1,
diff --git a/components/ask/selectModel.tsx b/components/ask/selectModel.tsx
index d5c2dea..8d5d738 100644
--- a/components/ask/selectModel.tsx
+++ b/components/ask/selectModel.tsx
@@ -4,7 +4,7 @@ import FolderSvg from "@/assets/icons/svg/folder.svg";
import ReturnArrow from "@/assets/icons/svg/returnArrow.svg";
import YesSvg from "@/assets/icons/svg/yes.svg";
import { TFunction } from "i18next";
-import React from "react";
+import React, { useState } from "react";
import { FlatList, Image, Modal, StyleSheet, TouchableOpacity, View } from "react-native";
import ContextMenu from "../gusture/contextMenu";
import { ThemedText } from "../ThemedText";
@@ -19,6 +19,7 @@ interface SelectModelProps {
t: TFunction;
}
const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setSelectedImages, selectedImages, t }: SelectModelProps) => {
+ const [cancel, setCancel] = useState(false)
return (
,
- label: "保存",
+ label: t("ask:ask.save"),
onPress: () => {
const imageUrl = item?.file_info?.url || item.video?.file_info?.url;
if (imageUrl) {
@@ -86,11 +87,12 @@ const SelectModel = ({ modalDetailsVisible, setModalDetailsVisible, insets, setS
},
{
svg: ,
- label: "取消",
- onPress: () => console.log('取消'),
+ label: t("ask:ask.cancel"),
+ onPress: () => setCancel(true),
textStyle: { color: 'red' }
}
]}
+ cancel={cancel}
menuStyle={{
backgroundColor: 'white',
borderRadius: 8,
diff --git a/components/ask/send.tsx b/components/ask/send.tsx
index 5a6f3ba..08543cd 100644
--- a/components/ask/send.tsx
+++ b/components/ask/send.tsx
@@ -4,7 +4,6 @@ import SunSvg from '@/assets/icons/svg/sun.svg';
import VideoSvg from '@/assets/icons/svg/video.svg';
import React, { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react';
import {
- EventSubscription,
Keyboard,
ScrollView,
StyleSheet,
@@ -14,6 +13,7 @@ import {
} from 'react-native';
import { Message } from '@/types/ask';
+import { useTranslation } from 'react-i18next';
import { ThemedText } from '../ThemedText';
import { createNewConversation, getConversation } from './utils';
@@ -28,14 +28,12 @@ interface Props {
export default function SendMessage(props: Props) {
const { setIsHello, conversationId, setUserMessages, setConversationId, selectedImages, setSelectedImages } = props;
+ const { t } = useTranslation()
+
// 用户询问
const [inputValue, setInputValue] = useState('');
-
-
// 添加一个ref来跟踪键盘状态
- const keyboardDidShowListener = useRef(null);
- const keyboardDidHideListener = useRef(null);
const isKeyboardVisible = useRef(false);
useEffect(() => {
@@ -49,8 +47,7 @@ export default function SendMessage(props: Props) {
setUserMessages([
{
content: {
- text: '想打开记忆盲盒吗?描述你的回忆,我来帮你找回照片、生成影片或解锁隐藏彩蛋✨'
-
+ text: t("ask:ask.introduction1")
},
role: 'Assistant',
timestamp: new Date().toISOString()
@@ -139,8 +136,8 @@ export default function SendMessage(props: Props) {
{
content: {
text: type === "search"
- ? '想找合适的图片?试试这样搜更精准:\n\n• 明确主题:比如"秋日森林""极简风书桌""复古海报设计"\n\n• 加上细节:想找特定风格?试试"水彩风猫咪""赛博朋克城市夜景";需要特定用途?比如"无版权风景图""可商用图标"\n\n• 描述场景:比如"阳光透过树叶的光斑""雨天咖啡馆窗外"\n\n输入这些关键词,说不定就能找到你想要的画面啦~'
- : '想让你的视频内容更吸睛、更有故事感吗?不妨试试从搜索图片入手吧!\n\n你可以先确定视频的主题——是治愈系的自然风景,还是复古风的城市街景,或是充满活力的生活瞬间?然后根据主题去搜索相关的图片,比如想做"春日限定"主题,就搜"樱花飘落""草地野餐""嫩芽初绽"之类的画面。\n\n这些图片能帮你快速理清视频的画面脉络,甚至能激发新的创意——比如一张老照片里的复古物件,或许能延伸出一段关于时光的故事;一组星空图片,说不定能串联成关于梦想与远方的叙事。把这些图片按你的想法串联起来,配上合适的音乐和文案,一段有温度的视频就诞生啦,试试看吧~'
+ ? t("ask:ask.introduction2")
+ : t("ask:ask.introduction3")
},
role: 'Assistant',
timestamp: new Date().toISOString()
@@ -154,10 +151,10 @@ export default function SendMessage(props: Props) {
handleQuitly('search')}>
- 检索素材
+ {t("ask:ask.search")}
handleQuitly('video')}>
- 创作视频
+ {t("ask:ask.video")}
= ({
text,
- speed = 150,
+ speed = 100,
loop = false,
delay = 2000,
}) => {
diff --git a/components/ask/utils.ts b/components/ask/utils.ts
index 945e3a4..a000c31 100644
--- a/components/ask/utils.ts
+++ b/components/ask/utils.ts
@@ -3,7 +3,9 @@ import { Message } from "@/types/ask";
import * as FileSystem from 'expo-file-system';
import * as MediaLibrary from 'expo-media-library';
import { useCallback } from "react";
+import { useTranslation } from "react-i18next";
import { Alert } from 'react-native';
+const { t } = useTranslation()
// 实现一个函数,从两个数组中轮流插入新数组
export const mergeArrays = (arr1: any[], arr2: any[]) => {
@@ -64,7 +66,7 @@ export const saveMediaToGallery = async (mediaUrl: string) => {
const { status } = await MediaLibrary.requestPermissionsAsync();
if (status !== 'granted') {
- Alert.alert('需要相册权限', '请允许应用访问相册以保存媒体文件');
+ Alert.alert(t("ask:ask.mediaAuth"), t("ask:ask.mediaAuthDesc"));
return false;
}
@@ -104,15 +106,15 @@ export const saveMediaToGallery = async (mediaUrl: string) => {
);
Alert.alert(
- '保存成功',
- isVideo ? '视频已保存到相册' : '图片已保存到相册'
+ t("ask:ask.saveSuccess"),
+ isVideo ? t("ask:ask.videoSave") : t("ask:ask.imgSave")
);
return true;
} catch (error) {
- console.error('保存失败:', error);
+ console.log('保存失败:', error);
Alert.alert(
- '保存失败',
- error instanceof Error ? error.message : '保存媒体文件时出错,请重试'
+ t("ask:ask.saveError"),
+ error instanceof Error ? error.message : t("ask:ask.saveError")
);
return false;
} finally {
@@ -122,7 +124,7 @@ export const saveMediaToGallery = async (mediaUrl: string) => {
await FileSystem.deleteAsync(fileUri, { idempotent: true }).catch(console.warn);
}
} catch (cleanupError) {
- console.warn('清理临时文件时出错:', cleanupError);
+ console.log('清理临时文件时出错:', cleanupError);
}
}
};
\ No newline at end of file
diff --git a/components/gusture/contextMenu.tsx b/components/gusture/contextMenu.tsx
index 5fcaa2f..17ff7e6 100644
--- a/components/gusture/contextMenu.tsx
+++ b/components/gusture/contextMenu.tsx
@@ -1,4 +1,4 @@
-import React, { useRef, useState } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import {
Dimensions,
Modal,
@@ -32,6 +32,7 @@ interface ContextMenuProps {
onClose?: () => void;
longPressDuration?: number;
activeOpacity?: number;
+ cancel?: boolean;
}
const ContextMenu: React.FC = ({
@@ -41,6 +42,7 @@ const ContextMenu: React.FC = ({
menuItemStyle,
menuTextStyle,
dividerStyle,
+ calcel,
onOpen,
onClose,
longPressDuration = 500,
@@ -75,6 +77,10 @@ const ContextMenu: React.FC = ({
runOnJS(showMenu)(absoluteX, absoluteY);
});
+ useEffect(() => {
+ setMenuVisible(!calcel);
+ }, [calcel])
+
return (
<>
diff --git a/i18n/locales/en/ask.json b/i18n/locales/en/ask.json
index f0009c0..2fac375 100644
--- a/i18n/locales/en/ask.json
+++ b/i18n/locales/en/ask.json
@@ -16,6 +16,13 @@
"issue": "have some issue",
"case1": "Find last year's baby/pet material",
"case2": "Find last year's food",
- "case3": "Find recent travel material"
+ "case3": "Find recent travel material",
+ "mediaAuth": "need album permission",
+ "mediaAuthDesc": "allow app to access album to save media files",
+ "saveSuccess": "save success",
+ "imgSave": "image saved to album",
+ "videoSave": "video saved to album",
+ "saveError": "save failed",
+ "saveErrorDesc": "save media files error, please try again"
}
}
\ No newline at end of file
diff --git a/i18n/locales/zh/ask.json b/i18n/locales/zh/ask.json
index 4ff442d..5f46082 100644
--- a/i18n/locales/zh/ask.json
+++ b/i18n/locales/zh/ask.json
@@ -16,6 +16,20 @@
"issue": "发生了一些问题",
"case1": "找去年我家宝宝/宠物的素材片段",
"case2": "找去年吃过的美食",
- "case3": "找近期旅游的素材"
+ "case3": "找近期旅游的素材",
+ "mediaAuth": "需要相册权限",
+ "mediaAuthDesc": "请允许应用访问相册以保存媒体文件",
+ "saveSuccess": "保存成功",
+ "imgSave": "图片已保存到相册",
+ "videoSave": "视频已保存到相册",
+ "saveError": "保存失败",
+ "saveErrorDesc": "保存媒体文件时出错,请重试",
+ "save": "保存",
+ "cancel": "取消",
+ "introduction1": "想打开记忆盲盒吗?描述你的回忆,我来帮你找回照片、生成影片或解锁隐藏彩蛋✨",
+ "introduction2": "想找合适的图片?试试这样搜更精准:\n\n• 明确主题:比如'秋日森林'、'极简风书桌'、'复古海报设计'\n\n• 加上细节:想找特定风格?试试'水彩风猫咪'、'赛博朋克城市夜景';需要特定用途?比如'无版权风景图'、'可商用图标'\n\n• 描述场景:比如'阳光透过树叶的光斑'、'雨天咖啡馆窗外'\n\n输入这些关键词,说不定就能找到你想要的画面啦~",
+ "introduction3": "想让你的视频内容更吸睛、更有故事感吗?不妨试试从搜索图片入手吧!\n\n你可以先确定视频的主题——是治愈系的自然风景,还是复古风的城市街景,或是充满活力的生活瞬间?然后根据主题去搜索相关的图片,比如想做'春日限定'主题,就搜'樱花飘落''草地野餐''嫩芽初绽'之类的画面。\n\n这些图片能帮你快速理清视频的画面脉络,甚至能激发新的创意——比如一张老照片里的复古物件,或许能延伸出一段关于时光的故事;一组星空图片,说不定能串联成关于梦想与远方的叙事。把这些图片按你的想法串联起来,配上合适的音乐和文案,一段有温度的视频就诞生啦,试试看吧~",
+ "search": "检索素材",
+ "video": "创作视频"
}
}
\ No newline at end of file