import React, { useEffect, useState } from 'react'; import { Platform, View, TouchableOpacity } from "react-native"; import { Button, TextInput, Dialog, Portal, Avatar, useTheme, Text } from "react-native-paper"; import { Asset } from 'expo-asset'; import * as FileSystem from 'expo-file-system'; import * as ImagePicker from "expo-image-picker"; import themes from '@/assets/themes'; import styles from "@/assets/styles"; import log from "@/util/log" import featureFlags from '@/util/featureFlags'; interface ProfileScreenProps { visible: boolean; id: string; name: string; setName: (name: string) => void; image: string; setImage: (image: string) => void; setChanged: (dataChanged: boolean) => void; setTheme: (theme: string) => void; currentTheme: string; onClose: () => void; } const Profile: React.FC = ({ visible, name, setName, image, setImage, setChanged, currentTheme, setTheme, onClose }) => { const theme = useTheme(); const isNameEmpty = !name.trim(); const themeColors = ['red', 'blue', 'yellow', 'green', 'orange', 'purple']; // Track the initial values when the component first mounts const [initialName, setInitialName] = useState(name); const [initialImage, setInitialImage] = useState(image); const [initialTheme, setInitialTheme] = useState(currentTheme); useEffect(() => { if (visible) { setInitialName(name); // Store initial name when the profile opens setInitialImage(image); setInitialTheme(currentTheme)// Store initial image when the profile opens } }, [visible]); // Reset when the dialog is opened useEffect(() => { const loadDefaultImage = async () => { const asset = Asset.fromModule(require("../assets/images/default_profile_image.png")); await asset.downloadAsync(); if (Platform.OS === 'web') { const response = await fetch(asset.uri); const blob = await response.blob(); return new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => { const base64String = reader.result?.toString().replace(/^data:.+;base64,/, ''); resolve(base64String); if (typeof base64String == "string") { setImage(base64String); } else { throw new Error("Failed to load asset."); } }; reader.readAsDataURL(blob); }); } else if (asset.uri) { const base64 = await FileSystem.readAsStringAsync(asset.uri, { encoding: FileSystem.EncodingType.Base64 }); setImage(base64); } }; const loadImage = async () => { if (!image || image === "") { log.debug("Loading ", image); await loadDefaultImage(); } }; loadImage().then(() => null); }, [image]); const pickImage = async () => { let result = await ImagePicker.launchImageLibraryAsync({ base64: true }); if (!result.canceled && result.assets.length > 0) { if (result.assets[0].base64 !== image) { // Only update if the image actually changes setImage(result.assets[0].base64 || image); log.debug("Picking Image"); } } }; const handleSave = () => { // Check if the name or image has changed const hasChanged = name !== initialName || image !== initialImage || currentTheme !== initialTheme; if (hasChanged) { setChanged(true); } onClose(); // Close the profile screen }; return ( { if (!isNameEmpty) { // Prevent closing if name is empty onClose(); } }} style={{ backgroundColor: theme.colors.background }}> Edit Your Profile { if (newName !== name) { // Only trigger change if it's different setName(newName); log.debug("Name change"); } }} style={{ marginBottom: 15, fontFamily: "SpaceReg" }} placeholderTextColor={theme.colors.primary} textColor={theme.colors.primary} theme={{ colors: { text: theme.colors.primary }}} /> {featureFlags.enableThemeSelection && ( <> Choose Theme {themeColors.map((userTheme) => ( {setTheme(userTheme); log.debug("Changing Theme: ", userTheme)}} > ))} )} ); }; export default Profile;