Compare commits

..

No commits in common. "2b995758620fabd4dd645f26c951a62b8914d202" and "3ced969c4f7b483ac6310953a72d9819284a6ec1" have entirely different histories.

12 changed files with 155 additions and 506 deletions

View File

@ -1,7 +1,11 @@
import {Appbar, Portal, Button, Dialog, Menu, Text, useTheme} from "react-native-paper"; import {Appbar, Portal, Button, Dialog, Menu, Text, useTheme} from "react-native-paper";
import {Image, useColorScheme, View} from "react-native"; import {Image, StyleSheet, useColorScheme, View} from "react-native";
import React, {useState} from "react"; import React, {useState} from "react";
import styles from "@/app/styles";
const styles = StyleSheet.create({
logoContainer: { flex: 1, alignItems: "center" },
logo: { width: 150, height: 75, resizeMode: "contain" },
});
const Nav = ({ toggleProfile }: { toggleProfile: () => void; }) => { const Nav = ({ toggleProfile }: { toggleProfile: () => void; }) => {
const theme = useTheme(); const theme = useTheme();
@ -24,11 +28,11 @@ const Nav = ({ toggleProfile }: { toggleProfile: () => void; }) => {
}} }}
iconColor={theme.colors.primary} /> iconColor={theme.colors.primary} />
</View> </View>
<View style={styles.logoContainer} > <View style={styles.logoContainer}>
<Image source={ <Image source={
colorScheme === 'dark' ? colorScheme === 'dark' ?
require("../assets/images/pogdark_logo_inverse.png") : require("../assets/images/pogdark_logo.png") require("../assets/images/pogdark_logo_inverse.png") : require("../assets/images/pogdark_logo.png")
} style={styles.logo} resizeMode={"contain"} /> } style={styles.logo} />
</View> </View>
<Appbar.Action icon="pencil" onPress={toggleProfile} iconColor={ theme.colors.primary } /> <Appbar.Action icon="pencil" onPress={toggleProfile} iconColor={ theme.colors.primary } />
</Appbar.Header> </Appbar.Header>

View File

@ -1,13 +1,11 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Platform, View, TouchableOpacity } from "react-native"; import { Platform, View, TouchableOpacity, StyleSheet } from "react-native";
import { Button, TextInput, Dialog, Portal, Avatar, useTheme, Text } from "react-native-paper"; import { Button, TextInput, Dialog, Portal, Avatar, useTheme, Text } from "react-native-paper";
import { Asset } from 'expo-asset'; import { Asset } from 'expo-asset';
import * as FileSystem from 'expo-file-system'; import * as FileSystem from 'expo-file-system';
import * as ImagePicker from "expo-image-picker"; import * as ImagePicker from "expo-image-picker";
import themes from '@/app/themes'; import { themes } from '@/app/themes';
import styles from "@/app/styles"; import { featureFlags } from '@/featureFlags';
import log from "@/util/log"
import featureFlags from '@/util/featureFlags';
interface ProfileScreenProps { interface ProfileScreenProps {
visible: boolean; visible: boolean;
@ -68,7 +66,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, i
const loadImage = async () => { const loadImage = async () => {
if (!image || image === "") { if (!image || image === "") {
log.debug("Loading ", image); console.log("Loading ", image);
await loadDefaultImage(); await loadDefaultImage();
} }
}; };
@ -80,7 +78,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, i
if (!result.canceled && result.assets.length > 0) { if (!result.canceled && result.assets.length > 0) {
if (result.assets[0].base64 !== image) { // Only update if the image actually changes if (result.assets[0].base64 !== image) { // Only update if the image actually changes
setImage(result.assets[0].base64 || image); setImage(result.assets[0].base64 || image);
log.debug("Picking Image"); console.log("Picking Image");
} }
} }
}; };
@ -126,7 +124,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, i
onChangeText={(newName) => { onChangeText={(newName) => {
if (newName !== name) { // Only trigger change if it's different if (newName !== name) { // Only trigger change if it's different
setName(newName); setName(newName);
log.debug("Name change"); console.log("Name change");
} }
}} }}
style={{ marginBottom: 15, fontFamily: "SpaceReg" }} style={{ marginBottom: 15, fontFamily: "SpaceReg" }}
@ -142,7 +140,7 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, i
<TouchableOpacity <TouchableOpacity
key={userTheme} key={userTheme}
style={[styles.themeButton, { backgroundColor: themes[userTheme as keyof typeof themes]['light'].colors.primary }]} style={[styles.themeButton, { backgroundColor: themes[userTheme as keyof typeof themes]['light'].colors.primary }]}
onPress={() => {setTheme(userTheme); log.debug("Changing Theme: ", userTheme)}} onPress={() => {setTheme(userTheme); console.log("Changing Theme: ", userTheme)}}
> >
<View style={[styles.halfCircle, { backgroundColor: themes[userTheme as keyof typeof themes]['dark'].colors.primary }]} /> <View style={[styles.halfCircle, { backgroundColor: themes[userTheme as keyof typeof themes]['dark'].colors.primary }]} />
</TouchableOpacity> </TouchableOpacity>
@ -167,4 +165,30 @@ const ProfileScreen: React.FC<ProfileScreenProps> = ({ visible, name, setName, i
); );
}; };
const styles = StyleSheet.create({
themeContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
alignItems: 'center',
marginTop: 10,
},
themeButton: {
width: 50,
height: 50,
borderRadius: 25,
justifyContent: 'center',
alignItems: 'flex-start',
overflow: 'hidden',
borderWidth: 1,
borderColor: 'black',
},
halfCircle: {
width: '50%',
height: '100%',
position: 'absolute',
bottom: 0,
},
});
export default ProfileScreen; export default ProfileScreen;

View File

@ -1,11 +1,9 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import useWebSocket from "react-use-websocket"; import useWebSocket from "react-use-websocket";
import axios from "axios"; import axios from "axios";
import {Animated, Easing, ImageBackground, useColorScheme, View} from "react-native"; import {Animated, Easing, ImageBackground, StyleSheet, useColorScheme, View} from "react-native";
import { Avatar, List, Button, useTheme, } from "react-native-paper"; import { Avatar, List, Button, useTheme, } from "react-native-paper";
import themes from "@/app/themes"; import { themes } from "@/app/themes";
import styles from "@/app/styles";
import log from "@/util/log"
export const API_URL = process.env.EXPO_PUBLIC_API_URL; export const API_URL = process.env.EXPO_PUBLIC_API_URL;
export const WS_URL = process.env.EXPO_PUBLIC_WS_URL; export const WS_URL = process.env.EXPO_PUBLIC_WS_URL;
@ -19,6 +17,55 @@ interface Message {
Timestamp: string; Timestamp: string;
} }
const styles = StyleSheet.create({
container: { flex: 1, alignItems: "stretch" },
listContainer: { flex: 1, width: "100%", backgroundColor: 'transparent' },
listSubheader: {
fontFamily: "Medium",
fontSize: 18, // Larger text
textAlign: "center", // Center the text
fontWeight: "bold", // Make it more distinct
marginBottom: 10, // Add spacing below
zIndex: 0,
},
listWrapper: { flex: 1, padding: 5 },
listRow: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-start", // Aligns subheaders properly
paddingHorizontal: 10, // Adds some spacing
},
listColumn: { flex: 1, paddingHorizontal: 5, zIndex: 1},
buttonContainer: {
flexDirection: "row",
justifyContent: "space-between",
alignSelf: "stretch",
paddingHorizontal: 10,
paddingBottom: 20,
},
actionButton: {
flex: 1,
marginHorizontal: 5,
},
card: {
marginVertical: 5,
elevation: 4, // Android shadow
shadowColor: "#000", // iOS shadow
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
borderRadius: 10,
},
imageBackground: {
position: "absolute", // Allows child elements to layer on top
width: "100%", // Ensure full coverage of the column
height: "100%", // Fully stretches to column height
resizeMode: "cover", // Ensures it fits well
opacity: 0.2, // Fades the image
zIndex: -1,
},
});
interface StatusProps { interface StatusProps {
id: string; id: string;
name: string; name: string;
@ -30,11 +77,11 @@ interface StatusProps {
} }
const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, setStatus, currentTheme, isProfileActive }) => { const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, setStatus, currentTheme, isProfileActive }) => {
log.debug("WebSocket URL: ", WS_URL); //console.log("WebSocket URL: ", WS_URL);
log.debug("API URL: ", API_URL); //console.log("API URL: ", API_URL);
const theme = useTheme(); const theme = useTheme();
const colorScheme = useColorScheme(); const colorScheme = useColorScheme();
log.debug(themes[currentTheme as keyof typeof themes][colorScheme === 'dark' ? 'dark' : 'light'].colors.primary); console.log(themes[currentTheme as keyof typeof themes][colorScheme === 'dark' ? 'dark' : 'light'].colors.primary);
const [messages, setMessages] = useState<Message[]>([]); const [messages, setMessages] = useState<Message[]>([]);
const { lastMessage } = useWebSocket(WS_URL + "/ws", { const { lastMessage } = useWebSocket(WS_URL + "/ws", {
@ -71,7 +118,7 @@ const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, set
}; };
useEffect(() => { useEffect(() => {
log.debug("Updated status: ", currentStatus); //console.log("Updated status: ", currentStatus);
if (currentStatus === "On the Way") { if (currentStatus === "On the Way") {
startPulsing(pulseAnimOnTheWay); startPulsing(pulseAnimOnTheWay);
@ -100,7 +147,7 @@ const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, set
try { try {
if (currentStatus === status) { if (currentStatus === status) {
// If pressed again, send "none" status and clear currentStatus // If pressed again, send "none" status and clear currentStatus
log.debug(`Removing status: ${status}`); console.log(`Removing status: ${status}`);
const message: Message = { const message: Message = {
Id: id, Id: id,
Name: name, Name: name,
@ -115,7 +162,7 @@ const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, set
}, 0) }, 0)
} else { } else {
// Otherwise, send the new status // Otherwise, send the new status
log.debug(`Setting status: ${status}`); console.log(`Setting status: ${status}`);
const message: Message = { const message: Message = {
Id: id, Id: id,
Name: name, Name: name,
@ -131,7 +178,7 @@ const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, set
} }
} catch (error) { } catch (error) {
log.error(`Error sending status '${status}':`, error); console.error(`Error sending status '${status}':`, error);
} }
}; };
@ -146,21 +193,21 @@ const StatusPage: React.FC<StatusProps> = ({ id, name, image, currentStatus, set
if (lastMessage?.data) { if (lastMessage?.data) {
try { try {
const newMessage: Message = JSON.parse(lastMessage.data); const newMessage: Message = JSON.parse(lastMessage.data);
log.debug("Current Status", currentStatus); console.log("Current Status", currentStatus);
setMessages((prev) => { setMessages((prev) => {
if (newMessage.Id === id && newMessage.Status !== currentStatus) { if (newMessage.Id === id && newMessage.Status !== currentStatus) {
log.debug("Status different, change to: ", newMessage.Status); console.log("Status different, change to: ", newMessage.Status);
setTimeout(() => { setTimeout(() => {
setStatus(newMessage.Status); setStatus(newMessage.Status);
}, 0); }, 0);
//return prev.filter((msg) => msg.Id !== newMessage.Id); //return prev.filter((msg) => msg.Id !== newMessage.Id);
}else{ }else{
log.debug("Status equal, no change"); console.log("Status equal, no change");
} }
return prev.filter((msg) => msg.Id !== newMessage.Id).concat(newMessage); return prev.filter((msg) => msg.Id !== newMessage.Id).concat(newMessage);
}); });
} catch (error) { } catch (error) {
log.error("Error parsing WebSocket message:", error); console.error("Error parsing WebSocket message:", error);
} }
} }
}, [lastMessage, setStatus, id]); }, [lastMessage, setStatus, id]);

View File

@ -5,9 +5,8 @@ import { useEffect } from 'react';
import 'react-native-reanimated'; import 'react-native-reanimated';
import { useColorScheme } from 'react-native'; import { useColorScheme } from 'react-native';
import { PaperProvider, Provider } from "react-native-paper"; import { PaperProvider, Provider } from "react-native-paper";
import { themes } from '@/app/themes'
import { UserProvider, useUser } from "@/context/UserContext"; import { UserProvider, useUser } from "@/context/UserContext";
import themes from '@/app/themes'
import log from "@/util/log"
// Prevent the splash screen from auto-hiding before asset loading is complete. // Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync(); SplashScreen.preventAutoHideAsync();
@ -22,9 +21,9 @@ export default function RootLayout() {
function InnerRootLayout() { function InnerRootLayout() {
const { currentTheme } = useUser(); // Access the currentTheme from UserContext const { currentTheme } = useUser(); // Access the currentTheme from UserContext
log.debug(currentTheme); console.log(currentTheme);
const colorScheme = useColorScheme(); const colorScheme = useColorScheme();
log.debug(colorScheme); console.log(colorScheme);
const [loaded] = useFonts({ const [loaded] = useFonts({
SpaceReg: require('../assets/fonts/SpaceMono-Regular.ttf'), SpaceReg: require('../assets/fonts/SpaceMono-Regular.ttf'),
SpaceBold: require('../assets/fonts/SpaceMono-Bold.ttf'), SpaceBold: require('../assets/fonts/SpaceMono-Bold.ttf'),

View File

@ -1,12 +1,10 @@
import React from 'react'; import React from 'react';
import {View, Text } from "react-native"; import {View, StyleSheet, Text } from "react-native";
import { useTheme } from "react-native-paper"; import { useTheme } from "react-native-paper";
import ProfileScreen from "@/app/ProfileScreen"; import ProfileScreen from "@/app/ProfileScreen";
import StatusPage from "@/app/StatusPage"; import StatusPage from "@/app/StatusPage";
import Nav from "@/app/Nav"; import Nav from "@/app/Nav";
import { useUser } from "@/context/UserContext"; import { useUser } from "@/context/UserContext";
import styles from "@/app/styles";
import log from "@/util/log"
const Index = () => { const Index = () => {
const theme = useTheme(); const theme = useTheme();
@ -28,16 +26,16 @@ const Index = () => {
} = useUser(); } = useUser();
if (isLoading) { if (isLoading) {
log.debug("Still loading"); console.log("Still loading");
return ( return (
<View style={[styles.indexContainer, { backgroundColor: theme.colors.background, justifyContent: 'center', alignItems: 'center' }]}> <View style={[styles.container, { backgroundColor: theme.colors.background, justifyContent: 'center', alignItems: 'center' }]}>
<Text>Loading...</Text> <Text>Loading...</Text>
</View> </View>
); );
} }
return ( return (
<View style={[styles.indexContainer, { backgroundColor: theme.colors.background }]}> <View style={[styles.container, { backgroundColor: theme.colors.background }]}>
<Nav <Nav
toggleProfile={() => setProfileActive(true)} toggleProfile={() => setProfileActive(true)}
/> />
@ -66,4 +64,15 @@ const Index = () => {
); );
}; };
const styles = StyleSheet.create({
container: { flex: 1, alignItems: "stretch" },
imageBackground: {
position: "absolute", // Allows child elements to layer on top
width: "100%", // Ensure full coverage of the column
height: "100%", // Fully stretches to column height
resizeMode: "cover", // Ensures it fits well
opacity: 0.3, // Fades the image
},
});
export default Index; export default Index;

View File

@ -1,89 +0,0 @@
import {StyleSheet} from "react-native";
const styles = StyleSheet.create({
//StatusPage
container: { flex: 1, alignItems: "stretch" },
listContainer: { flex: 1, width: "100%", backgroundColor: 'transparent' },
listSubheader: {
fontFamily: "Medium",
fontSize: 18, // Larger text
textAlign: "center", // Center the text
fontWeight: "bold", // Make it more distinct
marginBottom: 10, // Add spacing below
zIndex: 0,
},
listWrapper: { flex: 1, padding: 5 },
listRow: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "flex-start", // Aligns subheaders properly
paddingHorizontal: 10, // Adds some spacing
},
listColumn: { flex: 1, paddingHorizontal: 5, zIndex: 1},
buttonContainer: {
flexDirection: "row",
justifyContent: "space-between",
alignSelf: "stretch",
paddingHorizontal: 10,
paddingBottom: 20,
},
actionButton: {
flex: 1,
marginHorizontal: 5,
},
card: {
marginVertical: 5,
elevation: 4, // Android shadow
shadowColor: "#000", // iOS shadow
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
borderRadius: 10,
},
imageBackground: {
position: "absolute", // Allows child elements to layer on top
width: "100%", // Ensure full coverage of the column
height: "100%", // Fully stretches to column height
resizeMode: "cover", // Ensures it fits well
opacity: 0.2, // Fades the image
zIndex: -1,
},
//profile screen
themeContainer: {
flexDirection: 'row',
justifyContent: 'space-around',
alignSelf: 'center',
//alignItems: 'center',
marginTop: 10,
},
themeButton: {
width: 50,
height: 50,
borderRadius: 25,
justifyContent: 'center',
alignItems: 'flex-start',
overflow: 'hidden',
borderWidth: 1,
borderColor: 'black',
},
halfCircle: {
width: '50%',
height: '100%',
position: 'absolute',
bottom: 0,
},
//Nav
logoContainer: { flex: 1, alignItems: "center" },
logo: { width: 150, height: 75 },
//index
indexImageBackground: {
position: "absolute", // Allows child elements to layer on top
width: "100%", // Ensure full coverage of the column
height: "100%", // Fully stretches to column height
resizeMode: "cover", // Ensures it fits well
opacity: 0.3, // Fades the image
},
indexContainer: { flex: 1, alignItems: "stretch" },
});
export default styles;

View File

@ -1,6 +1,6 @@
import { MD3LightTheme, MD3DarkTheme } from 'react-native-paper'; import { MD3LightTheme, MD3DarkTheme } from 'react-native-paper';
const themes = { export const themes = {
purple: { purple: {
light: MD3LightTheme, light: MD3LightTheme,
dark: MD3DarkTheme, dark: MD3DarkTheme,
@ -106,345 +106,3 @@ const themes = {
}, },
} }
}; };
export const oldThemes = {
purple: {
light: MD3LightTheme,
dark: MD3DarkTheme,
},
red: {
light: {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: '#D32F2F',
onPrimary: '#FFFFFF',
primaryContainer: '#FFCDD2',
onPrimaryContainer: '#4A0D0D',
secondary: '#FF5252',
onSecondary: '#FFFFFF',
secondaryContainer: '#FFEBEE',
onSecondaryContainer: '#5D1E1E',
tertiary: '#C2185B',
onTertiary: '#FFFFFF',
tertiaryContainer: '#F8BBD0',
onTertiaryContainer: '#550027',
background: '#FFFFFF',
onBackground: '#121212',
surface: '#F5F5F5',
onSurface: '#1E1E1E',
error: '#B00020',
onError: '#FFFFFF',
outline: '#B71C1C',
inverseSurface: '#333333',
inverseOnSurface: '#FAFAFA',
inversePrimary: '#FFB4A9',
},
},
dark: {
...MD3DarkTheme,
colors: {
...MD3DarkTheme.colors,
primary: '#FF5252',
onPrimary: '#FFFFFF',
primaryContainer: '#7F0000',
onPrimaryContainer: '#FFDAD4',
secondary: '#FF8A80',
onSecondary: '#1E0000',
secondaryContainer: '#4A0D0D',
onSecondaryContainer: '#FFEBEE',
tertiary: '#FF4081',
onTertiary: '#1E001E',
tertiaryContainer: '#7A001A',
onTertiaryContainer: '#FFD9E3',
background: '#121212',
onBackground: '#E1E1E1',
surface: '#1E1E1E',
onSurface: '#FFFFFF',
error: '#CF6679',
onError: '#FFFFFF',
outline: '#FF6F61',
inverseSurface: '#E1E1E1',
inverseOnSurface: '#1E1E1E',
inversePrimary: '#D32F2F',
},
},
},
blue: {
light: {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: '#1976D2',
onPrimary: '#FFFFFF',
primaryContainer: '#BBDEFB',
onPrimaryContainer: '#0D47A1',
secondary: '#64B5F6',
onSecondary: '#FFFFFF',
secondaryContainer: '#E3F2FD',
onSecondaryContainer: '#1565C0',
tertiary: '#0288D1',
onTertiary: '#FFFFFF',
tertiaryContainer: '#81D4FA',
onTertiaryContainer: '#01579B',
background: '#FFFFFF',
onBackground: '#121212',
surface: '#F5F5F5',
onSurface: '#1E1E1E',
error: '#B00020',
onError: '#FFFFFF',
outline: '#1565C0',
inverseSurface: '#333333',
inverseOnSurface: '#FAFAFA',
inversePrimary: '#90CAF9',
},
},
dark: {
...MD3DarkTheme,
colors: {
...MD3DarkTheme.colors,
primary: '#64B5F6',
onPrimary: '#FFFFFF',
primaryContainer: '#0D47A1',
onPrimaryContainer: '#BBDEFB',
secondary: '#81D4FA',
onSecondary: '#1E1E1E',
secondaryContainer: '#1565C0',
onSecondaryContainer: '#E3F2FD',
tertiary: '#29B6F6',
onTertiary: '#1E1E1E',
tertiaryContainer: '#01579B',
onTertiaryContainer: '#81D4FA',
background: '#121212',
onBackground: '#E1E1E1',
surface: '#1E1E1E',
onSurface: '#FFFFFF',
error: '#CF6679',
onError: '#FFFFFF',
outline: '#64B5F6',
inverseSurface: '#E1E1E1',
inverseOnSurface: '#1E1E1E',
inversePrimary: '#1976D2',
},
},
},
yellow: {
light: {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: '#FBC02D',
onPrimary: '#000000',
primaryContainer: '#FFF9C4',
onPrimaryContainer: '#5F3700',
secondary: '#FFD54F',
onSecondary: '#000000',
secondaryContainer: '#FFF8E1',
onSecondaryContainer: '#775A00',
tertiary: '#FFB300',
onTertiary: '#FFFFFF',
tertiaryContainer: '#FFECB3',
onTertiaryContainer: '#603800',
background: '#FFFFFF',
onBackground: '#121212',
surface: '#F5F5F5',
onSurface: '#1E1E1E',
error: '#B00020',
onError: '#FFFFFF',
outline: '#FF8F00',
inverseSurface: '#333333',
inverseOnSurface: '#FAFAFA',
inversePrimary: '#FDD835',
},
},
dark: {
...MD3DarkTheme,
colors: {
...MD3DarkTheme.colors,
primary: '#FFD54F',
onPrimary: '#000000',
primaryContainer: '#5F3700',
onPrimaryContainer: '#FFF9C4',
secondary: '#FFEB3B',
onSecondary: '#000000',
secondaryContainer: '#775A00',
onSecondaryContainer: '#FFF8E1',
tertiary: '#FFB300',
onTertiary: '#1E1E1E',
tertiaryContainer: '#603800',
onTertiaryContainer: '#FFECB3',
background: '#121212',
onBackground: '#E1E1E1',
surface: '#1E1E1E',
onSurface: '#FFFFFF',
error: '#CF6679',
onError: '#FFFFFF',
outline: '#FDD835',
inverseSurface: '#E1E1E1',
inverseOnSurface: '#1E1E1E',
inversePrimary: '#FBC02D',
},
},
},
green: {
light: {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: '#388E3C', // Material Green 700
onPrimary: '#FFFFFF',
primaryContainer: '#C8E6C9',
onPrimaryContainer: '#004D00',
secondary: '#66BB6A',
onSecondary: '#FFFFFF',
secondaryContainer: '#E8F5E9',
onSecondaryContainer: '#1B5E20',
tertiary: '#2E7D32',
onTertiary: '#FFFFFF',
tertiaryContainer: '#A5D6A7',
onTertiaryContainer: '#003300',
background: '#FFFFFF',
onBackground: '#121212',
surface: '#F5F5F5',
onSurface: '#1E1E1E',
error: '#B00020',
onError: '#FFFFFF',
outline: '#388E3C',
inverseSurface: '#333333',
inverseOnSurface: '#FAFAFA',
inversePrimary: '#A5D6A7', // Soft green
},
},
dark: {
...MD3DarkTheme,
colors: {
...MD3DarkTheme.colors,
primary: '#66BB6A',
onPrimary: '#FFFFFF',
primaryContainer: '#004D00',
onPrimaryContainer: '#C8E6C9',
secondary: '#81C784',
onSecondary: '#1E1E1E',
secondaryContainer: '#1B5E20',
onSecondaryContainer: '#E8F5E9',
tertiary: '#43A047',
onTertiary: '#1E1E1E',
tertiaryContainer: '#003300',
onTertiaryContainer: '#A5D6A7',
background: '#121212',
onBackground: '#E1E1E1',
surface: '#1E1E1E',
onSurface: '#FFFFFF',
error: '#CF6679',
onError: '#FFFFFF',
outline: '#A5D6A7',
inverseSurface: '#E1E1E1',
inverseOnSurface: '#1E1E1E',
inversePrimary: '#388E3C', // Same as light theme primary
}
}
},
orange: {
light: {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: '#F57C00', // Material Orange 700
onPrimary: '#FFFFFF',
primaryContainer: '#FFCC80',
onPrimaryContainer: '#7A3300',
secondary: '#FFA726',
onSecondary: '#FFFFFF',
secondaryContainer: '#FFE0B2',
onSecondaryContainer: '#8E4700',
tertiary: '#EF6C00', // Deep orange
onTertiary: '#FFFFFF',
tertiaryContainer: '#FFD180',
onTertiaryContainer: '#622600',
background: '#FFFFFF',
onBackground: '#121212',
surface: '#F5F5F5',
onSurface: '#1E1E1E',
error: '#B00020',
onError: '#FFFFFF',
outline: '#F57C00',
inverseSurface: '#333333',
inverseOnSurface: '#FAFAFA',
inversePrimary: '#FFAB40', // Soft orange
},
},
dark: {
...MD3DarkTheme,
colors: {
...MD3DarkTheme.colors,
primary: '#FFA726',
onPrimary: '#FFFFFF',
primaryContainer: '#b38800',
onPrimaryContainer: '#FFCC80',
secondary: '#FFB74D',
onSecondary: '#1E1E1E',
secondaryContainer: '#5a4406',
onSecondaryContainer: '#FFE0B2',
tertiary: '#FB8C00',
onTertiary: '#1E1E1E',
tertiaryContainer: '#623400',
onTertiaryContainer: '#FFD180',
background: '#121212',
onBackground: '#E1E1E1',
surface: '#1E1E1E',
onSurface: '#FFFFFF',
error: '#CF6679',
onError: '#FFFFFF',
outline: '#FFAB40',
inverseSurface: '#E1E1E1',
inverseOnSurface: '#1E1E1E',
inversePrimary: '#F57C00', // Same as light theme primary
},
}
}
};
export const themePreviews = {
purple: {
light: '#6200EA', // Default Purple Light
dark: '#BB86FC', // Default Purple Dark
},
red: {
light: '#D32F2F',
dark: '#FF5252',
},
blue: {
light: '#1976D2',
dark: '#64B5F6',
},
yellow: {
light: '#FBC02D',
dark: '#FFD54F',
},
green: {
light: '#388E3C',
dark: '#66BB6A',
},
orange: {
light: '#F57C00',
dark: '#FFA726',
},
};
export default themes;

View File

@ -3,7 +3,6 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
import { AppState } from "react-native"; import { AppState } from "react-native";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import axios from "axios"; import axios from "axios";
import log from "@/util/log"
export const API_URL = process.env.EXPO_PUBLIC_API_URL; export const API_URL = process.env.EXPO_PUBLIC_API_URL;
@ -50,7 +49,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
const storedUserName = await AsyncStorage.getItem("userName"); const storedUserName = await AsyncStorage.getItem("userName");
const storedUserImage = await AsyncStorage.getItem("userImage"); const storedUserImage = await AsyncStorage.getItem("userImage");
const storedUserTheme = await AsyncStorage.getItem("theme"); const storedUserTheme = await AsyncStorage.getItem("theme");
log.debug("Stored theme: ", storedUserTheme); console.log("Stored theme: ", storedUserTheme);
if (storedUserId) { if (storedUserId) {
setUserId(storedUserId); setUserId(storedUserId);
setUserName(storedUserName || ""); setUserName(storedUserName || "");
@ -65,7 +64,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
setProfileActive(true); setProfileActive(true);
} }
} catch (error) { } catch (error) {
log.error("Error loading user data:", error); console.error("Error loading user data:", error);
} finally { } finally {
setIsLoading(false); setIsLoading(false);
} }
@ -83,10 +82,10 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
await AsyncStorage.setItem("userName", userName); await AsyncStorage.setItem("userName", userName);
await AsyncStorage.setItem("userImage", userImage); await AsyncStorage.setItem("userImage", userImage);
await AsyncStorage.setItem("theme", currentTheme); await AsyncStorage.setItem("theme", currentTheme);
log.debug("Current theme: ", currentTheme); console.log("Current theme: ", currentTheme);
setUserDataChanged(false); setUserDataChanged(false);
} catch (error) { } catch (error) {
log.error("Error saving user data:", error); console.error("Error saving user data:", error);
} }
}; };
@ -99,7 +98,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
if (!isLoading) { if (!isLoading) {
fetchCurrentStatus(); fetchCurrentStatus();
} else { } else {
log.debug("Waiting for loading to complete before fetching status..."); console.log("Waiting for loading to complete before fetching status...");
} }
} }
setAppState(AppState.currentState); setAppState(AppState.currentState);
@ -121,7 +120,7 @@ export const UserProvider: React.FC<UserProviderProps> = ({ children }) => {
}, 0); }, 0);
} }
} catch (error) { } catch (error) {
log.error("Error fetching status:", error); console.error("Error fetching status:", error);
} }
}; };

View File

@ -1,5 +1,3 @@
const featureFlags = { export const featureFlags = {
enableThemeSelection: true, // Toggle this to true or false to enable/disable the feature enableThemeSelection: true, // Toggle this to true or false to enable/disable the feature
}; };
export default featureFlags;

22
package-lock.json generated
View File

@ -30,8 +30,8 @@
"react": "18.3.1", "react": "18.3.1",
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-native": "0.77.1", "react-native": "0.77.1",
"react-native-config": "~1.5.5",
"react-native-gesture-handler": "~2.20.2", "react-native-gesture-handler": "~2.20.2",
"react-native-logs": "~5.3.0",
"react-native-paper": "~5.13.1", "react-native-paper": "~5.13.1",
"react-native-reanimated": "~3.16.1", "react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0", "react-native-safe-area-context": "4.12.0",
@ -12430,6 +12430,20 @@
} }
} }
}, },
"node_modules/react-native-config": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/react-native-config/-/react-native-config-1.5.5.tgz",
"integrity": "sha512-dGdLnBU0cd5xL5bF0ROTmHYbsstZnQKOEPfglvZi1vStvAjpld14X25K6mY3KGPTMWAzx6TbjKeq5dR+ILuMMA==",
"license": "MIT",
"peerDependencies": {
"react-native-windows": ">=0.61"
},
"peerDependenciesMeta": {
"react-native-windows": {
"optional": true
}
}
},
"node_modules/react-native-gesture-handler": { "node_modules/react-native-gesture-handler": {
"version": "2.20.2", "version": "2.20.2",
"resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.20.2.tgz", "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.20.2.tgz",
@ -12470,12 +12484,6 @@
"react-native": ">=0.73.0" "react-native": ">=0.73.0"
} }
}, },
"node_modules/react-native-logs": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/react-native-logs/-/react-native-logs-5.3.0.tgz",
"integrity": "sha512-tq4S0JFy06ggu1D/udYeV80qPy5koURNNcKrVJmv0Hf3x44akysctaE4ARybD5Pv7MnFD8fP1VFhycSLjqXHQw==",
"license": "MIT"
},
"node_modules/react-native-paper": { "node_modules/react-native-paper": {
"version": "5.13.1", "version": "5.13.1",
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.13.1.tgz", "resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.13.1.tgz",

View File

@ -34,7 +34,6 @@
"react-dom": "18.3.1", "react-dom": "18.3.1",
"react-native": "0.77.1", "react-native": "0.77.1",
"react-native-gesture-handler": "~2.20.2", "react-native-gesture-handler": "~2.20.2",
"react-native-logs": "~5.3.0",
"react-native-reanimated": "~3.16.1", "react-native-reanimated": "~3.16.1",
"react-native-safe-area-context": "4.12.0", "react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0", "react-native-screens": "~4.4.0",

View File

@ -1,7 +0,0 @@
import { logger } from "react-native-logs";
const log = logger.createLogger({
severity: "error"
});
export default log;