diff --git a/app/_layout.tsx b/app/_layout.tsx
index 6f79126..0a38cb4 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,7 +1,8 @@
import { Slot } from 'expo-router';
import React, { useEffect } from 'react';
-import { initDatabase } from '../services/database';
+import { addCategory, initDatabase } from '../services/database';
import { AuthProvider } from './contexts/AuthContext';
+import { ThemeProvider } from './contexts/ThemeContext';
export default function _layout() {
@@ -12,7 +13,9 @@ export default function _layout() {
console.log("layout called")
return (
-
+
+
+
)
}
\ No newline at end of file
diff --git a/app/contexts/ThemeContext.tsx b/app/contexts/ThemeContext.tsx
new file mode 100644
index 0000000..9e00714
--- /dev/null
+++ b/app/contexts/ThemeContext.tsx
@@ -0,0 +1,97 @@
+import {useContext, createContext, useState, useEffect} from "react"
+import AsyncStorage from "@react-native-async-storage/async-storage"
+import { useColorScheme } from "react-native";
+import themeColors from "../../constants/colors";
+
+
+interface ThemeProps {
+ isSystemTheme?: boolean
+ theme: "light" | "dark";
+ colors: typeof themeColors.light & typeof themeColors.dark;
+ applySystemTheme?: () => void;
+ applyTheme?: (theme: "light" | "dark") => void;
+}
+
+const THEME_KEY = "THEME"
+const SYSTEM_THEME_KEY = "SYSTEM_THEME"
+
+const ThemeContext = createContext({theme: "light", colors: themeColors.light})
+
+export const useTheme = () => {
+ return useContext(ThemeContext)
+}
+
+export const ThemeProvider = ({children} : any) => {
+ const currentSystemTheme = useColorScheme()
+ const [isSystemTheme, setIsSystemTheme] = useState(true);
+ const [theme, setTheme] = useState<"light" | "dark">("light");
+ const [colors, setColors] = useState(themeColors.light)
+
+ useEffect(() => {
+ console.log("effect called")
+ const loadTheme = async () => {
+ try {
+ const is_system_theme = await AsyncStorage.getItem(SYSTEM_THEME_KEY)
+ const saved_theme = await AsyncStorage.getItem(THEME_KEY);
+
+ if(is_system_theme !== "false"){//We will use !== false bacause system theme should be used if unspecified
+ applySystemTheme();
+ return;
+ }
+
+ if(saved_theme === "light" || saved_theme === "dark"){
+ applyTheme(saved_theme);
+ }
+
+ } catch (error) {
+ console.error(error)
+ }
+ }
+ loadTheme();
+ }, [currentSystemTheme])
+
+
+ const applySystemTheme = () => {
+ const storeSystemTheme = async () => {
+ console.log("applySystemTheme")
+ await AsyncStorage.setItem(SYSTEM_THEME_KEY, "true")
+ }
+
+ storeSystemTheme();
+ setIsSystemTheme(true)
+ applyThemeInternal(currentSystemTheme ?? "light")
+ }
+
+ const applyThemeInternal = (theme: "light" | "dark") => {
+ const storeTheme = async (theme: "light" | "dark") => {
+ await AsyncStorage.setItem(THEME_KEY, theme)
+ }
+
+ setTheme(theme);
+ storeTheme(theme);
+ setColors(themeColors[theme])
+ }
+
+ const applyTheme = (theme: "light" | "dark") => {
+ const unsetSytemTheme = async () => {
+ AsyncStorage.setItem(SYSTEM_THEME_KEY, "false");
+ }
+ unsetSytemTheme()
+ setIsSystemTheme(false);
+ applyThemeInternal(theme);
+ }
+
+ const value = {
+ isSystemTheme: isSystemTheme,
+ applyTheme: applyTheme,
+ applySystemTheme: applySystemTheme,
+ theme: theme,
+ colors: colors,
+ }
+
+ return (
+
+ {children}
+
+ )
+}
diff --git a/package-lock.json b/package-lock.json
index 2e67c4c..f07d162 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "1.0.0",
"dependencies": {
"@expo/vector-icons": "^13.0.0",
+ "@react-native-async-storage/async-storage": "1.18.2",
"@react-navigation/native": "^6.0.2",
"expo": "~49.0.15",
"expo-font": "~11.4.0",
@@ -4277,6 +4278,17 @@
"react": "^16.8 || ^17.0 || ^18.0"
}
},
+ "node_modules/@react-native-async-storage/async-storage": {
+ "version": "1.18.2",
+ "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.18.2.tgz",
+ "integrity": "sha512-dM8AfdoeIxlh+zqgr0o5+vCTPQ0Ru1mrPzONZMsr7ufp5h+6WgNxQNza7t0r5qQ6b04AJqTlBNixTWZxqP649Q==",
+ "dependencies": {
+ "merge-options": "^3.0.4"
+ },
+ "peerDependencies": {
+ "react-native": "^0.0.0-0 || 0.60 - 0.72 || 1000.0.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",
@@ -13452,6 +13464,25 @@
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha512-OcjA+jzjOYzKmKS6IQVALHLVz+rNTMPoJvCztFaZxwG14wtAW7VRZjwTQu06vKCYOxh4jVnik7ya0SXTB0W+xA=="
},
+ "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",
diff --git a/package.json b/package.json
index 8fff007..a625b05 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
},
"dependencies": {
"@expo/vector-icons": "^13.0.0",
+ "@react-native-async-storage/async-storage": "1.18.2",
"@react-navigation/native": "^6.0.2",
"expo": "~49.0.15",
"expo-font": "~11.4.0",