All checks were successful
Build Flutter Web and Docker Image for Local Registry / Build React Native Web App (push) Successful in 10m32s
148 lines
5.9 KiB
TypeScript
148 lines
5.9 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { Platform } from "react-native";
|
|
import { Button, TextInput, Dialog, Portal, Avatar, useTheme } from "react-native-paper";
|
|
import { Asset } from 'expo-asset';
|
|
import * as FileSystem from 'expo-file-system';
|
|
import * as ImagePicker from "expo-image-picker";
|
|
|
|
interface ProfileScreenProps {
|
|
visible: boolean;
|
|
id: string;
|
|
name: string;
|
|
setName: (name: string) => void;
|
|
image: string;
|
|
setImage: (image: string) => void;
|
|
setChanged: (dataChanged: boolean) => void;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, image, setImage, setChanged, onClose }) => {
|
|
const { colors } = useTheme();
|
|
const isNameEmpty = !name.trim();
|
|
|
|
// Track the initial values when the component first mounts
|
|
const [initialName, setInitialName] = useState(name);
|
|
const [initialImage, setInitialImage] = useState(image);
|
|
|
|
useEffect(() => {
|
|
if (visible) {
|
|
setInitialName(name); // Store initial name when the profile opens
|
|
setInitialImage(image); // 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 === "") {
|
|
console.log("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);
|
|
console.log("Picking Image");
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleSave = () => {
|
|
// Check if the name or image has changed
|
|
const hasChanged = name !== initialName || image !== initialImage;
|
|
if (hasChanged) {
|
|
setChanged(true);
|
|
}
|
|
onClose(); // Close the profile screen
|
|
};
|
|
|
|
return (
|
|
<Portal>
|
|
<Dialog
|
|
visible={visible}
|
|
onDismiss={() => {
|
|
if (!isNameEmpty) { // Prevent closing if name is empty
|
|
onClose();
|
|
}
|
|
}}
|
|
style={{ backgroundColor: colors.background }}>
|
|
<Dialog.Title style={{ color: colors.onBackground, textAlign: 'center' }}>Edit Your Profile</Dialog.Title>
|
|
<Dialog.Content>
|
|
<Avatar.Image
|
|
size={100}
|
|
source={image ? { uri: `data:image/png;base64,${image}` } : require("../assets/images/default_profile_image.png")}
|
|
style={{ alignSelf: 'center', marginBottom: 15 }}
|
|
/>
|
|
<Button
|
|
onPress={pickImage}
|
|
mode="contained"
|
|
style={{ backgroundColor: colors.primary, marginBottom: 10 }}
|
|
labelStyle={{ color: colors.onPrimary }}
|
|
>
|
|
Change Profile Picture
|
|
</Button>
|
|
<TextInput
|
|
label="Your Pet's Name"
|
|
mode="outlined"
|
|
value={name}
|
|
onChangeText={(newName) => {
|
|
if (newName !== name) { // Only trigger change if it's different
|
|
setName(newName);
|
|
console.log("Name change");
|
|
}
|
|
}}
|
|
style={{ marginBottom: 15, backgroundColor: colors.surface }}
|
|
placeholderTextColor={colors.onSurface}
|
|
theme={{ colors: { text: colors.onSurface } }}
|
|
/>
|
|
</Dialog.Content>
|
|
<Dialog.Actions>
|
|
<Button
|
|
onPress={handleSave}
|
|
mode="contained"
|
|
disabled={isNameEmpty} // Disable if name is empty
|
|
style={{
|
|
backgroundColor: isNameEmpty ? colors.tertiary : colors.secondary, // Dim the button
|
|
opacity: isNameEmpty ? 0.5 : 1, // Visually dim the button
|
|
}}
|
|
labelStyle={{ color: colors.onPrimary }}
|
|
>
|
|
Save
|
|
</Button>
|
|
</Dialog.Actions>
|
|
</Dialog>
|
|
</Portal>
|
|
);
|
|
};
|
|
|
|
export default ProfileScreen;
|