|
|
|
@ -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<any>(); |
|
|
|
|
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 ( |
|
|
|
|
<SafeAreaView style={styles.safeArea}> |
|
|
|
|
<StatusBar barStyle="dark-content" backgroundColor="#fff" /> |
|
|
|
@ -431,10 +555,14 @@ export const ProductDetailScreen = () => {
|
|
|
|
|
> |
|
|
|
|
<BackIcon size={fontSize(20)} /> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
<TouchableOpacity style={styles.search} onPress={handleSearchPress}> |
|
|
|
|
<Text style={styles.searchText}>搜索</Text> |
|
|
|
|
<CameraIcon size={fontSize(20)} /> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
<View style={styles.search}> |
|
|
|
|
<TouchableOpacity onPress={handleSearchPress}> |
|
|
|
|
<Text style={styles.searchText}>搜索</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
<TouchableOpacity onPress={handleCameraPress}> |
|
|
|
|
<CameraIcon size={fontSize(20)} /> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
</View> |
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.searchIcon} |
|
|
|
|
onPress={() => { |
|
|
|
@ -830,6 +958,57 @@ export const ProductDetailScreen = () => {
|
|
|
|
|
)} |
|
|
|
|
</View> |
|
|
|
|
</View> |
|
|
|
|
|
|
|
|
|
{/* Image Picker Modal */} |
|
|
|
|
<Modal |
|
|
|
|
visible={showImagePickerModal} |
|
|
|
|
animationType="slide" |
|
|
|
|
transparent={true} |
|
|
|
|
onRequestClose={() => setShowImagePickerModal(false)} |
|
|
|
|
> |
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.imagePickerOverlay} |
|
|
|
|
activeOpacity={1} |
|
|
|
|
onPress={() => setShowImagePickerModal(false)} |
|
|
|
|
> |
|
|
|
|
<View style={styles.imagePickerContent}> |
|
|
|
|
{!galleryUsed ? ( |
|
|
|
|
// 正常状态,显示相机选项
|
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.imagePickerOption} |
|
|
|
|
onPress={handleTakePhoto} |
|
|
|
|
> |
|
|
|
|
<CameraIcon size={24} color="#333" /> |
|
|
|
|
<Text style={styles.imagePickerText}>拍照</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
) : ( |
|
|
|
|
// 已使用相册状态,显示重置选项
|
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.imagePickerOption} |
|
|
|
|
onPress={resetAppState} |
|
|
|
|
> |
|
|
|
|
<Text style={styles.imagePickerText}>重置相机功能</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
)} |
|
|
|
|
|
|
|
|
|
<View style={styles.imagePickerDivider} /> |
|
|
|
|
|
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.imagePickerOption} |
|
|
|
|
onPress={handleChooseFromGallery} |
|
|
|
|
> |
|
|
|
|
<Text style={styles.imagePickerText}>从相册选择</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
|
|
|
|
|
<TouchableOpacity |
|
|
|
|
style={styles.imagePickerCancelButton} |
|
|
|
|
onPress={() => setShowImagePickerModal(false)} |
|
|
|
|
> |
|
|
|
|
<Text style={styles.imagePickerCancelText}>取消</Text> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
</View> |
|
|
|
|
</TouchableOpacity> |
|
|
|
|
</Modal> |
|
|
|
|
</SafeAreaView> |
|
|
|
|
); |
|
|
|
|
}; |
|
|
|
@ -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", |
|
|
|
|
}, |
|
|
|
|
}); |
|
|
|
|