small refactoring
This commit is contained in:
+106
-56
@@ -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<MatrixState>) => void;
|
||||
};
|
||||
|
||||
const MatrixContext = createContext<MatrixContextType | undefined>(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<MatrixState>(() => getInitialState(authenticatedUser?.lastState));
|
||||
const updateMatrixState = (newState: Partial<MatrixState>) => {
|
||||
setMatrixState(prevState => ({...prevState, ...newState}));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (authenticatedUser?.lastState) {
|
||||
console.log("Authenticated user or lastState changed, updating matrix context...");
|
||||
setMatrixState(getInitialState(authenticatedUser.lastState));
|
||||
}
|
||||
}, [authenticatedUser]);
|
||||
|
||||
return (
|
||||
<AuthenticatedWrapper>
|
||||
<Tabs
|
||||
screenOptions={({route}) => ({
|
||||
headerStyle: {
|
||||
backgroundColor: theme.theme.colors.primaryContainer,
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: theme.theme.colors.onPrimaryContainer,
|
||||
},
|
||||
headerTitleContainerStyle: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
headerRight: () => (
|
||||
<Link href="/settings" style={{marginRight: 16}}>
|
||||
<Feather
|
||||
name="settings"
|
||||
size={24}
|
||||
color={theme.theme.colors.onPrimaryContainer}
|
||||
/>
|
||||
</Link>
|
||||
),
|
||||
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}) => (
|
||||
<Tabs.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
options={{
|
||||
title: shouldHideText ? '' : title,
|
||||
tabBarIcon: ({color}) => (
|
||||
<MatrixContext.Provider value={{matrixState, updateMatrixState}}>
|
||||
<Tabs
|
||||
screenOptions={({route}) => ({
|
||||
headerStyle: {
|
||||
backgroundColor: theme.colors.primaryContainer,
|
||||
},
|
||||
headerTitleStyle: {
|
||||
color: theme.colors.onPrimaryContainer,
|
||||
},
|
||||
headerTitleContainerStyle: {
|
||||
paddingHorizontal: 16,
|
||||
},
|
||||
headerRight: () => (
|
||||
<Link href="/settings" style={{marginRight: 16}}>
|
||||
<Feather
|
||||
name="settings"
|
||||
size={24}
|
||||
color={theme.colors.onPrimaryContainer}
|
||||
/>
|
||||
</Link>
|
||||
),
|
||||
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}) => (
|
||||
<Tabs.Screen
|
||||
key={name}
|
||||
name={name}
|
||||
options={{
|
||||
title: shouldHideText ? '' : title,
|
||||
tabBarIcon: ({color}) => (
|
||||
<Feather size={28} name={icon} color={color}/>
|
||||
),
|
||||
),
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Tabs.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
title: 'Einstellungen',
|
||||
href: null, // prevents showing in the tab bar
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Tabs.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
title: 'Einstellungen',
|
||||
href: null, // prevents showing in the tab bar
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
</Tabs>
|
||||
</MatrixContext.Provider>
|
||||
</AuthenticatedWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
+18
-21
@@ -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<TextProps>(
|
||||
authenticatedUser?.lastState?.text || {
|
||||
text: '',
|
||||
color: [255, 255, 255],
|
||||
align: 'center',
|
||||
speed: 50,
|
||||
size: 16,
|
||||
}
|
||||
);
|
||||
const { matrixState, updateMatrixState } = useMatrix();
|
||||
|
||||
const updateTextProp = (prop: Partial<TextProps>) => {
|
||||
setTextProps(prev => ({ ...prev, ...prop }));
|
||||
updateMatrixState({
|
||||
text: { ...matrixState.text, ...prop },
|
||||
global: { ...matrixState.global, mode: 'text' }
|
||||
});
|
||||
};
|
||||
|
||||
const handleSendToMatrix = () => {
|
||||
console.log("Sende an Matrix:", matrixState);
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemedBackground>
|
||||
<View style={styles.contentWrapper}>
|
||||
<View style={[styles.contentWrapper]}>
|
||||
<View style={styles.inputGroup}>
|
||||
<ThemedTextInput
|
||||
label="Text"
|
||||
value={textProps.text}
|
||||
value={matrixState.text.text}
|
||||
onChangeText={(text) => updateTextProp({ text })}
|
||||
/>
|
||||
|
||||
<ColorSelector
|
||||
onSelect={(color) => updateTextProp({ color })}
|
||||
defaultColor={textProps.color}
|
||||
defaultColor={matrixState.text.color}
|
||||
/>
|
||||
|
||||
<ThemedSegmentedButtons
|
||||
value={textProps.align}
|
||||
value={matrixState.text.align}
|
||||
onValueChange={(align) => updateTextProp({ align })}
|
||||
options={{
|
||||
left: 'Links',
|
||||
@@ -56,7 +52,7 @@ export default function TextScreen() {
|
||||
<View style={styles.actionGroup}>
|
||||
<ThemedButton
|
||||
mode="contained"
|
||||
onPress={() => console.log(textProps)}
|
||||
onPress={handleSendToMatrix}
|
||||
title={"An die Matrix senden"}
|
||||
/>
|
||||
</View>
|
||||
@@ -69,11 +65,12 @@ const styles = StyleSheet.create({
|
||||
contentWrapper: {
|
||||
flex: 1,
|
||||
justifyContent: 'space-between',
|
||||
paddingVertical: 20,
|
||||
padding: 20,
|
||||
},
|
||||
inputGroup: {
|
||||
gap: 15,
|
||||
},
|
||||
actionGroup: {
|
||||
paddingTop: 20,
|
||||
}
|
||||
});
|
||||
@@ -48,7 +48,7 @@ export default function ChangePasswordForm({ onSuccess, onCancel }: ChangePasswo
|
||||
|
||||
{apiResponse && apiResponse.data?.message && (
|
||||
<View style={[styles.apiResponseBox, { backgroundColor: apiResponse.ok ? theme.colors.success : theme.colors.error }]}>
|
||||
<Text variant="bodyMedium"style={{ color: apiResponse.ok ? theme.colors.onSuccess : theme.colors.onError }}>
|
||||
<Text variant="bodyMedium" style={{ color: apiResponse.ok ? theme.colors.onSuccess : theme.colors.onError }}>
|
||||
{apiResponse.data.message}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -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<T extends string> = {
|
||||
value: T;
|
||||
|
||||
Reference in New Issue
Block a user