diff --git a/app/locales/en/translation.json b/app/locales/en/translation.json index 715a0b8..9e5446d 100644 --- a/app/locales/en/translation.json +++ b/app/locales/en/translation.json @@ -362,6 +362,9 @@ "submit": "Submit" } }, + "homePage":{ + "searchPlaceholder": "Search products" + }, "searchCountry": "Search country", "noCountriesFound": "No countries found" } \ No newline at end of file diff --git a/app/locales/fr/translation.json b/app/locales/fr/translation.json index 017dd57..665ac2a 100644 --- a/app/locales/fr/translation.json +++ b/app/locales/fr/translation.json @@ -356,6 +356,10 @@ "error": "Une erreur s'est produite. Veuillez réessayer.", "submit": "Soumettre" } + + }, + "homePage":{ + "searchPlaceholder": "Rechercher des produits" }, "searchCountry": "Rechercher un pays", "noCountriesFound": "Aucun pays trouvé" diff --git a/app/screens/CartScreen.tsx b/app/screens/CartScreen.tsx index 3efc582..84b0200 100644 --- a/app/screens/CartScreen.tsx +++ b/app/screens/CartScreen.tsx @@ -501,9 +501,9 @@ export const CartScreen = () => { {/* Replace SVG with actual icon component or image */} - + {/* */} - Panier (5) + {/* Panier (5) */} {cartList.map((item, index1) => ( diff --git a/app/screens/HomeScreen.tsx b/app/screens/HomeScreen.tsx index f6e5545..fe1c92d 100644 --- a/app/screens/HomeScreen.tsx +++ b/app/screens/HomeScreen.tsx @@ -756,7 +756,7 @@ export const HomeScreen = () => { onPress={navigateToSearch} > - 搜索商品 + {t("homePage.searchPlaceholder")} setShowImagePickerModal(true)} diff --git a/app/screens/ProductDetailScreen.tsx b/app/screens/ProductDetailScreen.tsx index b365df6..13034a7 100644 --- a/app/screens/ProductDetailScreen.tsx +++ b/app/screens/ProductDetailScreen.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useCallback } from "react"; +import React, { useEffect, useCallback, useState } from "react"; import { View, Text, @@ -15,7 +15,8 @@ import { InteractionManager, Platform, StatusBar, - SafeAreaView + SafeAreaView, + Modal } from "react-native"; import fontSize from "../utils/fontsizeUtils"; import widthUtils from "../utils/widthUtils"; @@ -26,13 +27,14 @@ import ShoppingCartIcon from "../components/ShoppingCartIcon"; import HeartIcon from "../components/HeartIcon"; import HeartRedIcon from "../components/HeartIconRed"; import ShareIcon from "../components/ShareIcon"; -import { useState } from "react"; import { Image as ExpoImage, ImageBackground } from "expo-image"; import useUserStore from "../store/user"; import { getSubjectTransLanguage } from "../utils/languageUtils"; import { useTranslation } from "react-i18next"; import { getBurialPointData } from "../store/burialPoint"; import useBurialPointStore from "../store/burialPoint"; +import * as ImagePicker from "expo-image-picker"; +import * as FileSystem from "expo-file-system"; import { productApi, @@ -79,6 +81,8 @@ export const ProductDetailScreen = () => { ); const [priceSelectedSku, setPriceSelectedSku] = useState(); const [showBottomSheet, setShowBottomSheet] = useState(false); + const [showImagePickerModal, setShowImagePickerModal] = useState(false); + const [galleryUsed, setGalleryUsed] = useState(false); const groupData = ( res: ProductDetailParams, priceSelectedSku: SkuAttribute[] @@ -386,6 +390,9 @@ export const ProductDetailScreen = () => { navigation.navigate("Search"); }); }, [navigation]); + const handleCameraPress = useCallback(() => { + setShowImagePickerModal(true); + }, []); const handleProductPress = useCallback( (item: similar) => { InteractionManager.runAfterInteractions(() => { @@ -412,6 +419,123 @@ export const ProductDetailScreen = () => { )); }; + // 清理expo-image-picker临时文件 + const cleanupImagePickerCache = async () => { + try { + // Skip cache cleanup on web platform + if (Platform.OS === 'web') { + console.log('Cache cleanup skipped on web platform'); + setGalleryUsed(false); + return; + } + + // 相册选择后清理临时缓存 + const cacheDir = `${FileSystem.cacheDirectory}ImagePicker`; + await FileSystem.deleteAsync(cacheDir, { idempotent: true }); + console.log("已清理ImagePicker缓存"); + + // 立即重置状态,无需用户干预 + setGalleryUsed(false); + } catch (error) { + console.log("清理缓存错误", error); + // Even if cleanup fails, reset the state + setGalleryUsed(false); + } + }; + + // 处理从相册选择 + const handleChooseFromGallery = useCallback(async () => { + console.log("handleChooseFromGallery"); + setShowImagePickerModal(false); + + // 等待模态窗关闭后再执行 + setTimeout(async () => { + try { + // 请求相册权限 + const permissionResult = + await ImagePicker.requestMediaLibraryPermissionsAsync(); + if (permissionResult.status !== "granted") { + console.log("相册权限被拒绝"); + return; + } + + // 打开相册 + const result = await ImagePicker.launchImageLibraryAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [4, 3], + quality: 1, + }); + + if (!result.canceled && result.assets && result.assets.length > 0) { + console.log("相册选择成功:", result.assets[0].uri); + + await cleanupImagePickerCache(); + navigation.navigate("ImageSearchResultScreen", { + image: result.assets[0].uri, + type: 1, + }); + } + } catch (error: any) { + console.error("相册错误:", error); + // 出错时也清理缓存 + await cleanupImagePickerCache(); + } + }, 500); + }, [navigation, userStore.user]); + + // 处理相机拍照 + const handleTakePhoto = useCallback(async () => { + console.log("handleTakePhoto"); + setShowImagePickerModal(false); + + // 等待模态窗关闭后再执行 + setTimeout(async () => { + try { + const permissionResult = + await ImagePicker.requestCameraPermissionsAsync(); + if (permissionResult.status !== "granted") { + console.log("相机权限被拒绝"); + return; + } + + const result = await ImagePicker.launchCameraAsync({ + mediaTypes: ImagePicker.MediaTypeOptions.Images, + allowsEditing: true, + aspect: [4, 3], + quality: 1, + }); + + if (!result.canceled && result.assets && result.assets.length > 0) { + console.log("拍照成功:", result.assets[0].uri); + + // 使用后清理缓存 + await cleanupImagePickerCache(); + navigation.navigate("ImageSearchResultScreen", { + image: result.assets[0].uri, + type: 1, + }); + } + } catch (error: any) { + console.error("相机错误:", error); + // 出错时也清理缓存 + await cleanupImagePickerCache(); + } + }, 500); + }, [navigation, userStore.user]); + + // 重置应用状态函数 + const resetAppState = useCallback(() => { + // 重置标记 + setGalleryUsed(false); + + // 清理缓存 + cleanupImagePickerCache(); + + // 提示用户 + Alert.alert("已重置", "现在您可以使用相机功能了"); + }, []); + return ( @@ -431,10 +555,14 @@ export const ProductDetailScreen = () => { > - - 搜索 - - + + + 搜索 + + + + + { @@ -830,6 +958,57 @@ export const ProductDetailScreen = () => { )} + + {/* Image Picker Modal */} + setShowImagePickerModal(false)} + > + setShowImagePickerModal(false)} + > + + {!galleryUsed ? ( + // 正常状态,显示相机选项 + + + 拍照 + + ) : ( + // 已使用相册状态,显示重置选项 + + 重置相机功能 + + )} + + + + + 从相册选择 + + + setShowImagePickerModal(false)} + > + 取消 + + + + ); }; @@ -1560,4 +1739,42 @@ const styles = StyleSheet.create({ backgroundColor: '#e0e0e0', borderRadius: 3, }, + imagePickerOverlay: { + flex: 1, + backgroundColor: "rgba(0, 0, 0, 0.5)", + justifyContent: "flex-end", + }, + imagePickerContent: { + backgroundColor: "#fff", + borderTopLeftRadius: 10, + borderTopRightRadius: 10, + paddingTop: 20, + }, + imagePickerOption: { + flexDirection: "row", + alignItems: "center", + justifyContent: "center", + paddingVertical: 15, + }, + imagePickerText: { + fontSize: fontSize(16), + color: "#333", + marginLeft: 10, + }, + imagePickerDivider: { + height: 1, + backgroundColor: "#eee", + marginHorizontal: 20, + }, + imagePickerCancelButton: { + alignItems: "center", + paddingVertical: 15, + borderTopWidth: 1, + borderTopColor: "#eee", + marginTop: 10, + }, + imagePickerCancelText: { + fontSize: fontSize(16), + color: "#333", + }, });