diff --git a/LeftOvers/App.tsx b/LeftOvers/App.tsx index 2e84e61..0a3b7a1 100644 --- a/LeftOvers/App.tsx +++ b/LeftOvers/App.tsx @@ -8,6 +8,7 @@ import HomeStackScreen from './navigation/HomeStackScreen'; import ProfilesStackScreen from './navigation/ProfileStackScreen'; import CookingStackScreen from './navigation/CookingStackScreen'; import BottomBar from './navigation/BottomBar'; +import { ThemeProvider } from './theme/ThemeContext'; import HomeIcon from './assets/images/home.png'; import ProfileIcon from './assets/images/person_icon.png'; @@ -19,12 +20,14 @@ const Tab = createBottomTabNavigator(); export default function App() { return ( - - }> - - - - - + + + }> + + + + + + ); } \ No newline at end of file diff --git a/LeftOvers/navigation/BottomBar.tsx b/LeftOvers/navigation/BottomBar.tsx index 67be5f2..4f49f36 100644 --- a/LeftOvers/navigation/BottomBar.tsx +++ b/LeftOvers/navigation/BottomBar.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import { View, Text, TouchableOpacity, Image, Pressable } from 'react-native'; import { GestureResponderEvent, StyleSheet } from 'react-native'; import {Appearance } from 'react-native'; @@ -10,44 +10,64 @@ import ProfileIcon from '../assets/images/person_icon.png'; import CookingIcon from '../assets/images/cook.png'; import LightIcon from '../assets/images/update.png'; import DarkIcon from '../assets/images/validate.png'; +import ThemeContext from '../theme/ThemeContext'; export default function BottomBar({ state, descriptors, navigation }) { - const [colorScheme, setScheme] = useState( - Appearance.getColorScheme(), - ); - const [iconThemeButton, setThemeIconButton] = useState(( colorScheme === 'dark' ) ? LightIcon : DarkIcon) - const [textThemeButton, setTextThemeButton] = useState(( colorScheme === 'dark' ) ? 'Light' : 'Dark'); - - useEffect(() => { - const subscription = Appearance.addChangeListener( - (preferences: AppearancePreferences) => { - const {colorScheme: scheme} = preferences; - setScheme(scheme); - }, - ); - - return () => subscription?.remove(); - }, [setScheme]); + const {theme, toggleTheme} = useContext(ThemeContext) + const [iconThemeButton, setThemeIconButton] = useState(( theme === 'dark' ) ? LightIcon : DarkIcon) + const [textThemeButton, setTextThemeButton] = useState(( theme === 'dark' ) ? 'Light' : 'Dark'); const onThemeButtonPress = (event: GestureResponderEvent) => { if (textThemeButton === "Light") { - setThemeIconButton(ProfileIcon); + setThemeIconButton(DarkIcon); setTextThemeButton("Dark"); - //Appearance.setColorScheme('light') + toggleTheme('light'); } else { - setThemeIconButton(HomeIcon); + setThemeIconButton(LightIcon); setTextThemeButton("Light"); - //Appearance.setColorScheme('dark') + toggleTheme('dark') } console.log('TextThemeButton is now: ' + textThemeButton); } + const styles = StyleSheet.create({ + BottomBarMainContainer: { + position: 'absolute', + bottom: 0, + right: 0, + left: 0, + height: 70, + backgroundColor: theme === 'dark' ? "#3F3C42": "transparent" + }, + BottomBarBlurContainer: { + flexDirection: 'row', + alignItems: 'center', + alignContent: 'space-around', + padding: 2, + borderBlockColor: theme === 'light' ? '#F2F0E4' : '#222222', + borderWidth: 3, + borderLeftColor: theme === 'light'? '#F2F0E4' : '#222222', + borderLeftWidth: 3, + borderRightColor: theme === 'light'? '#F2F0E4' : '#222222', + borderRightWidth: 3 + }, + BottomBarIcon: { + width: 35, + height: 35 + }, + BottomBarElementContainer: { + flexDirection: 'column', + alignItems: 'center', + margin: 3 + } + }) + return ( {state.routes.map((route, index) => { const { options } = descriptors[route.key]; @@ -90,7 +110,7 @@ export default function BottomBar({ state, descriptors, navigation }) { onPress={onPress} style={[styles.BottomBarElementContainer, { flex: 1 }]} > - + {label} @@ -106,35 +126,4 @@ export default function BottomBar({ state, descriptors, navigation }) { ); -} - -const styles = StyleSheet.create({ - BottomBarMainContainer: { - position: 'absolute', - bottom: 0, - right: 0, - left: 0, - height: 70 - }, - BottomBarBlurContainer: { - flexDirection: 'row', - alignItems: 'center', - alignContent: 'space-around', - padding: 2, - borderBlockColor: '#F2F0E4', - borderWidth: 3, - borderLeftColor: '#F2F0E4', - borderLeftWidth: 3, - borderRightColor: '#F2F0E4', - borderRightWidth: 3 - }, - BottomBarIcon: { - width: 35, - height: 35 - }, - BottomBarElementContainer: { - flexDirection: 'column', - alignItems: 'center', - margin: 3 - } -}) \ No newline at end of file +} \ No newline at end of file diff --git a/LeftOvers/package-lock.json b/LeftOvers/package-lock.json index e074240..6e908f5 100644 --- a/LeftOvers/package-lock.json +++ b/LeftOvers/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "dependencies": { "@expo/webpack-config": "^19.0.0", + "@react-native-async-storage/async-storage": "^1.19.7", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", @@ -3942,6 +3943,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "1.19.7", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.7.tgz", + "integrity": "sha512-zvfhOWWnjzeP4exfgNwDUot7MQafEEJnbjjNsVKWRxRuQT521GLSHUJQHjMTLg19QPT+HbsGjL7rJzKkmXuq7w==", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.60 <1.0" + } + }, "node_modules/@react-native-community/cli": { "version": "11.3.7", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz", @@ -12269,6 +12281,25 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-options/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -20455,6 +20486,14 @@ } } }, + "@react-native-async-storage/async-storage": { + "version": "1.19.7", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.19.7.tgz", + "integrity": "sha512-zvfhOWWnjzeP4exfgNwDUot7MQafEEJnbjjNsVKWRxRuQT521GLSHUJQHjMTLg19QPT+HbsGjL7rJzKkmXuq7w==", + "requires": { + "merge-options": "^3.0.4" + } + }, "@react-native-community/cli": { "version": "11.3.7", "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-11.3.7.tgz", @@ -26667,6 +26706,21 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, + "merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "requires": { + "is-plain-obj": "^2.1.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" + } + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", diff --git a/LeftOvers/package.json b/LeftOvers/package.json index a671046..a224bbe 100644 --- a/LeftOvers/package.json +++ b/LeftOvers/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "@expo/webpack-config": "^19.0.0", + "@react-native-async-storage/async-storage": "^1.19.7", "@react-navigation/bottom-tabs": "^6.5.11", "@react-navigation/native": "^6.1.9", "@react-navigation/native-stack": "^6.9.17", diff --git a/LeftOvers/theme/ThemeContext.tsx b/LeftOvers/theme/ThemeContext.tsx new file mode 100644 index 0000000..080fec7 --- /dev/null +++ b/LeftOvers/theme/ThemeContext.tsx @@ -0,0 +1,42 @@ +import React, {createContext, useState, useEffect} from 'react'; +import AsyncStorage from '@react-native-async-storage/async-storage'; + + +interface ThemeContextType { + theme: string, + toggleTheme: (any)=> void +}; + +const ThemeContext = createContext(null); + +export const ThemeProvider = ({children}) => { + const [theme, setTheme] = useState('light'); + + useEffect(() => { + // Load saved theme from storage + const getTheme = async () => { + try { + const savedTheme = await AsyncStorage.getItem('theme'); + if (savedTheme) { + setTheme(savedTheme); + } + } catch (error) { + console.log('Error loading theme:', error); + } + }; + getTheme(); + }, []); + + const toggleTheme = newTheme => { + setTheme(newTheme); + AsyncStorage.setItem('theme', newTheme) + }; + + return ( + + {children} + + ); +}; + +export default ThemeContext; \ No newline at end of file