From a4da1a6294ed0f96e25158c4bb2cf2177746ad37 Mon Sep 17 00:00:00 2001 From: StarAppeal Date: Wed, 24 Sep 2025 02:42:54 +0200 Subject: [PATCH] small refactoring --- app/(tabs)/_layout.tsx | 162 ++++++++++++------ app/(tabs)/modes/text.tsx | 39 ++--- src/components/ChangePasswordForm.tsx | 2 +- .../themed/ThemedSegmentedButtons.tsx | 1 - 4 files changed, 125 insertions(+), 79 deletions(-) diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index 43ad93f..26663e0 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,11 +1,12 @@ import {Link, Tabs} from 'expo-router'; -import React from "react"; +import React, {createContext, useContext, useState, useEffect } from "react"; import {Feather} from "@expo/vector-icons"; import {useTheme} from "@/src/context/ThemeProvider"; import AuthenticatedWrapper from "@/src/components/AuthenticatedWrapper"; -import {Dimensions} from "react-native"; +import { useWindowDimensions } from "react-native"; +import {MatrixState} from "@/src/model/User"; +import {useAuth} from "@/src/context/AuthProvider"; -const screenWidth = Dimensions.get("window").width; const tabs = [ @@ -16,66 +17,115 @@ const tabs = [ {name: 'modes/clock', title: 'Uhr', icon: 'clock'}, ] as const; +type MatrixContextType = { + matrixState: MatrixState; + updateMatrixState: (newState: Partial) => void; +}; + +const MatrixContext = createContext(undefined); + +export const useMatrix = () => { + const context = useContext(MatrixContext); + if (!context) throw new Error("useMatrix must be used within a MatrixProvider"); + return context; +}; + +const getInitialState = (lastState?: MatrixState | null): MatrixState => { + const defaults: MatrixState = { + global: { mode: 'idle', brightness: 100 }, + text: { text: 'Hello World', align: 'center', speed: 50, size: 16, color: [255, 255, 255] }, + image: { image: 'dino.gif' }, + clock: { color: [0, 255, 0] }, + music: { fullscreen: false } + }; + + return { + ...defaults, + ...(lastState || {}), + global: { ...defaults.global, ...(lastState?.global || {}) }, + text: { ...defaults.text, ...(lastState?.text || {}) }, + image: { ...defaults.image, ...(lastState?.image || {}) }, + clock: { ...defaults.clock, ...(lastState?.clock || {}) }, + music: { ...defaults.music, ...(lastState?.music || {}) }, + }; +}; + export default function TabLayout() { - const theme = useTheme(); - const shouldHideText = (screenWidth < 400); + const {theme} = useTheme(); + const {authenticatedUser} = useAuth(); + const { width } = useWindowDimensions(); + const shouldHideText = (width < 400); + + const [matrixState, setMatrixState] = useState(() => getInitialState(authenticatedUser?.lastState)); + const updateMatrixState = (newState: Partial) => { + setMatrixState(prevState => ({...prevState, ...newState})); + }; + + useEffect(() => { + if (authenticatedUser?.lastState) { + console.log("Authenticated user or lastState changed, updating matrix context..."); + setMatrixState(getInitialState(authenticatedUser.lastState)); + } + }, [authenticatedUser]); return ( - ({ - headerStyle: { - backgroundColor: theme.theme.colors.primaryContainer, - }, - headerTitleStyle: { - color: theme.theme.colors.onPrimaryContainer, - }, - headerTitleContainerStyle: { - paddingHorizontal: 16, - }, - headerRight: () => ( - - - - ), - tabBarActiveTintColor: theme.theme.colors.primary, - tabBarInactiveTintColor: theme.theme.colors.onSurfaceVariant, - tabBarStyle: { - backgroundColor: theme.theme.colors.surface, - borderTopColor: theme.theme.colors.outline, - elevation: 4, - }, - tabBarItemStyle: { - borderLeftWidth: route.name === tabs[0].name ? 0 : 1, - borderLeftColor: theme.theme.colors.outlineVariant, // Trennlinienfarbe - }, - })} - > - {tabs.map(({name, title, icon}) => ( - ( + + ({ + headerStyle: { + backgroundColor: theme.colors.primaryContainer, + }, + headerTitleStyle: { + color: theme.colors.onPrimaryContainer, + }, + headerTitleContainerStyle: { + paddingHorizontal: 16, + }, + headerRight: () => ( + + + + ), + tabBarActiveTintColor: theme.colors.primary, + tabBarInactiveTintColor: theme.colors.onSurfaceVariant, + tabBarStyle: { + backgroundColor: theme.colors.surface, + borderTopColor: theme.colors.outline, + elevation: 4, + }, + tabBarItemStyle: { + borderLeftWidth: route.name === tabs[0].name ? 0 : 1, + borderLeftColor: theme.colors.outlineVariant, + }, + })} + > + {tabs.map(({name, title, icon}) => ( + ( - ), + ), + }} + /> + ))} + + - ))} - - - + + ); } diff --git a/app/(tabs)/modes/text.tsx b/app/(tabs)/modes/text.tsx index 784a783..7263145 100644 --- a/app/(tabs)/modes/text.tsx +++ b/app/(tabs)/modes/text.tsx @@ -1,49 +1,45 @@ import ThemedBackground from "@/src/components/themed/ThemedBackground"; -import { useState } from "react"; import ThemedTextInput from "@/src/components/themed/ThemedTextInput"; import ThemedButton from "@/src/components/themed/ThemedButton"; -import { useAuth } from "@/src/context/AuthProvider"; import ColorSelector from "@/src/components/themed/ColorSelector"; -import { View, StyleSheet } from "react-native"; +import {View, StyleSheet} from "react-native"; import ThemedSegmentedButtons from "@/src/components/themed/ThemedSegmentedButtons"; import { MatrixState } from '@/src/model/User'; +import {useMatrix} from "@/app/(tabs)/_layout"; type TextProps = MatrixState['text']; export default function TextScreen() { - const { authenticatedUser } = useAuth(); - - const [textProps, setTextProps] = useState( - authenticatedUser?.lastState?.text || { - text: '', - color: [255, 255, 255], - align: 'center', - speed: 50, - size: 16, - } - ); + const { matrixState, updateMatrixState } = useMatrix(); const updateTextProp = (prop: Partial) => { - setTextProps(prev => ({ ...prev, ...prop })); + updateMatrixState({ + text: { ...matrixState.text, ...prop }, + global: { ...matrixState.global, mode: 'text' } + }); + }; + + const handleSendToMatrix = () => { + console.log("Sende an Matrix:", matrixState); }; return ( - + updateTextProp({ text })} /> updateTextProp({ color })} - defaultColor={textProps.color} + defaultColor={matrixState.text.color} /> updateTextProp({ align })} options={{ left: 'Links', @@ -56,7 +52,7 @@ export default function TextScreen() { console.log(textProps)} + onPress={handleSendToMatrix} title={"An die Matrix senden"} /> @@ -69,11 +65,12 @@ const styles = StyleSheet.create({ contentWrapper: { flex: 1, justifyContent: 'space-between', - paddingVertical: 20, + padding: 20, }, inputGroup: { gap: 15, }, actionGroup: { + paddingTop: 20, } }); \ No newline at end of file diff --git a/src/components/ChangePasswordForm.tsx b/src/components/ChangePasswordForm.tsx index 812c9e2..fe7201a 100644 --- a/src/components/ChangePasswordForm.tsx +++ b/src/components/ChangePasswordForm.tsx @@ -48,7 +48,7 @@ export default function ChangePasswordForm({ onSuccess, onCancel }: ChangePasswo {apiResponse && apiResponse.data?.message && ( - + {apiResponse.data.message} diff --git a/src/components/themed/ThemedSegmentedButtons.tsx b/src/components/themed/ThemedSegmentedButtons.tsx index 5928113..2198b79 100644 --- a/src/components/themed/ThemedSegmentedButtons.tsx +++ b/src/components/themed/ThemedSegmentedButtons.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { View, StyleSheet, StyleProp, ViewStyle } from 'react-native'; import { SegmentedButtons } from 'react-native-paper'; -import { useTheme } from '@/src/context/ThemeProvider'; export type SegmentedButton = { value: T;