work on the sticker expo app up to the emoji picker
This commit is contained in:
parent
d9922d5ec5
commit
ba572f9d69
84
App.js
84
App.js
|
|
@ -1,10 +1,69 @@
|
|||
import { StatusBar } from 'expo-status-bar';
|
||||
import { StyleSheet, Text, View } from 'react-native';
|
||||
import { StyleSheet, Text, View, Image } from 'react-native';
|
||||
import { useState } from 'react';
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
|
||||
import ImageViewer from './components/ImageViewer';
|
||||
import Button from './components/Button';
|
||||
import CircleButton from './components/CircleButton';
|
||||
import IconButton from './components/IconButton';
|
||||
import Picker from './components/Picker';
|
||||
|
||||
const backgroundImage = require('./assets/images/background-image.png')
|
||||
|
||||
export default function App() {
|
||||
const [selectedImage, setSelectedImage] = useState(null);
|
||||
const [showAppOptions, setShowAppOptions] = useState(false);
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
|
||||
const pickImageAsync = async () => {
|
||||
let result = await ImagePicker.launchImageLibraryAsync({
|
||||
allowsEditing: true,
|
||||
quality: 1,
|
||||
});
|
||||
|
||||
if (!result.canceled) {
|
||||
setSelectedImage(result.assets[0].uri);
|
||||
setShowAppOptions(true);
|
||||
} else {
|
||||
alert('You did not select any image.');
|
||||
}
|
||||
};
|
||||
const onReset = () => {
|
||||
setShowAppOptions(false);
|
||||
};
|
||||
const onAddSticker = () => {
|
||||
setIsModalVisible(true);
|
||||
};
|
||||
const onModalClose = () => {
|
||||
setIsModalVisible(false);
|
||||
};
|
||||
const onSaveImageAsync = async () => {
|
||||
// we will implement this later
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text>Open up App.js to start working on your app!</Text>
|
||||
<View style={styles.imageContainer}>
|
||||
<ImageViewer placeholderImageSource={backgroundImage} selectedImage={selectedImage} />
|
||||
</View>
|
||||
{showAppOptions ? (
|
||||
<View style={styles.optionsContainer}>
|
||||
<View style={styles.optionsRow}>
|
||||
<IconButton icon="refresh" label="Reset" onPress={onReset} />
|
||||
<CircleButton onPress={onAddSticker} />
|
||||
<IconButton icon="save-alt" label="Save" onPress={onSaveImageAsync} />
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View style={styles.buttonContainer}>
|
||||
<Button label="Choose a photo" override={true} onPress={pickImageAsync} />
|
||||
<Button label="Use this photo" override={false} onPress={() => setShowAppOptions(true)} />
|
||||
</View>
|
||||
)}
|
||||
<Picker isVisible={isModalVisible} onClose={onModalClose}>
|
||||
{/* A list of emoji component will go here */}
|
||||
</Picker>
|
||||
<StatusBar style="auto" />
|
||||
</View>
|
||||
);
|
||||
|
|
@ -13,8 +72,25 @@ export default function App() {
|
|||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#fff',
|
||||
backgroundColor: '#e9ffdb',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
justifyContent: 'center'
|
||||
},
|
||||
imageContainer: {
|
||||
flex: 1,
|
||||
paddingTop: 59
|
||||
},
|
||||
buttonContainer: {
|
||||
flex: 1 / 3,
|
||||
alignItems: 'center',
|
||||
rowGap: 10
|
||||
},
|
||||
optionsContainer: {
|
||||
position: 'absolute',
|
||||
bottom: 80,
|
||||
},
|
||||
optionsRow: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { StyleSheet, View, Pressable, Text } from 'react-native';
|
||||
import FontAwesome from "@expo/vector-icons/FontAwesome";
|
||||
|
||||
export default function Button({ label, override, onPress }) {
|
||||
if (override) {
|
||||
return (
|
||||
<View style={styles.buttonContainer}>
|
||||
<Pressable style={styles.button} onPress={onPress}>
|
||||
<FontAwesome
|
||||
name="picture-o"
|
||||
size={18}
|
||||
color="#25292e"
|
||||
style={styles.buttonIcon}
|
||||
/>
|
||||
<Text style={styles.primaryButtonLabel}>{label}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<View style={styles.buttonContainer}>
|
||||
<Pressable style={styles.button} onPress={onPress}>
|
||||
<Text style={styles.buttonLabel}>{label}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
buttonContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
width: 320,
|
||||
height: 68,
|
||||
marginHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 3,
|
||||
backgroundColor: '#E3F988',
|
||||
borderRadius: 80
|
||||
},
|
||||
buttonIcon: {
|
||||
position: 'absolute',
|
||||
marginLeft: -30
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import { View, Pressable, StyleSheet } from 'react-native';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
|
||||
export default function CircleButton({ onPress }) {
|
||||
return (
|
||||
<View style={styles.circleButtonContainer}>
|
||||
<Pressable style={styles.circleButton} onPress={onPress}>
|
||||
<MaterialIcons name="add" size={38} color="#25292e" />
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
circleButtonContainer: {
|
||||
width: 84,
|
||||
height: 84,
|
||||
marginHorizontal: 60,
|
||||
borderWidth: 4,
|
||||
borderColor: '#ffd33d',
|
||||
borderRadius: 42,
|
||||
padding: 3,
|
||||
},
|
||||
circleButton: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
borderRadius: 42,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Pressable, StyleSheet, Text } from 'react-native';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
|
||||
export default function IconButton({ icon, label, onPress }) {
|
||||
return (
|
||||
<Pressable style={styles.iconButton} onPress={onPress}>
|
||||
<MaterialIcons name={icon} size={24} color="#000" />
|
||||
<Text style={styles.iconButtonLabel}>{label}</Text>
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
iconButton: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
iconButtonLabel: {
|
||||
color: '#000',
|
||||
marginTop: 12,
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { StatusBar } from 'expo-status-bar';
|
||||
import { StyleSheet, Text, View, Image } from 'react-native';
|
||||
|
||||
export default function ImageViewer({placeholderImageSource,selectedImage}){
|
||||
const imageSource = selectedImage ? { uri: selectedImage } : placeholderImageSource;
|
||||
return (
|
||||
<Image source={imageSource} style={styles.image} />
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
image:{
|
||||
width:350,
|
||||
height:450,
|
||||
borderRadius:80
|
||||
}
|
||||
})
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { Modal, View, Text, Pressable, StyleSheet } from 'react-native';
|
||||
import MaterialIcons from '@expo/vector-icons/MaterialIcons';
|
||||
|
||||
export default function Picker({ isVisible, children, onClose }) {
|
||||
return (
|
||||
<Modal animationType="slide" transparent={true} visible={isVisible}>
|
||||
<View style={styles.modalContent}>
|
||||
<View style={styles.titleContainer}>
|
||||
<Text style={styles.title}>Choose a sticker</Text>
|
||||
<Pressable onPress={onClose}>
|
||||
<MaterialIcons name="close" color="#000" size={22} />
|
||||
</Pressable>
|
||||
</View>
|
||||
{children}
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContent: {
|
||||
height: '25%',
|
||||
width: '100%',
|
||||
backgroundColor: '#25292e',
|
||||
borderTopRightRadius: 18,
|
||||
borderTopLeftRadius: 18,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
},
|
||||
titleContainer: {
|
||||
height: '16%',
|
||||
backgroundColor: '#464C55',
|
||||
borderTopRightRadius: 10,
|
||||
borderTopLeftRadius: 10,
|
||||
paddingHorizontal: 20,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
title: {
|
||||
color: '#000',
|
||||
fontSize: 16,
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES6",
|
||||
"module": "commonjs",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
|
@ -9,7 +9,9 @@
|
|||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@expo/metro-runtime": "~3.2.1",
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"expo": "~51.0.22",
|
||||
"expo-image-picker": "~15.0.7",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
|
|
@ -7796,6 +7798,25 @@
|
|||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-image-loader": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.7.0.tgz",
|
||||
"integrity": "sha512-cx+MxxsAMGl9AiWnQUzrkJMJH4eNOGlu7XkLGnAXSJrRoIiciGaKqzeaD326IyCTV+Z1fXvIliSgNW+DscvD8g==",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-image-picker": {
|
||||
"version": "15.0.7",
|
||||
"resolved": "https://registry.npmjs.org/expo-image-picker/-/expo-image-picker-15.0.7.tgz",
|
||||
"integrity": "sha512-u8qiPZNfDb+ap6PJ8pq2iTO7JKX+ikAUQ0K0c7gXGliKLxoXgDdDmXxz9/6QdICTshJBJlBvI0MwY5NWu7A/uw==",
|
||||
"dependencies": {
|
||||
"expo-image-loader": "~4.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-keep-awake": {
|
||||
"version": "13.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-keep-awake/-/expo-keep-awake-13.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
"react-native": "0.74.3",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native-web": "~0.19.10",
|
||||
"@expo/metro-runtime": "~3.2.1"
|
||||
"@expo/metro-runtime": "~3.2.1",
|
||||
"@expo/vector-icons": "^14.0.2",
|
||||
"expo-image-picker": "~15.0.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0"
|
||||
|
|
|
|||
Loading…
Reference in New Issue