chore: Refactor UI components and improve styling across various screens

This commit is contained in:
2025-12-27 04:33:25 +01:00
parent 63e30d3c4d
commit 295654f5cf
24 changed files with 640 additions and 303 deletions
+41 -3
View File
@@ -1,12 +1,50 @@
import React from "react";
import {View, Text} from "react-native";
import {Feather} from "@expo/vector-icons";
import ThemedHeader from "@/src/components/themed/ThemedHeader";
import ThemedBackground from "@/src/components/themed/ThemedBackground";
import ColorSelector from "@/src/components/themed/ColorSelector";
import SaveToMatrixButton from "@/src/components/SaveToMatrixButton";
import { useMatrixStore } from "@/src/stores";
import {useColors} from "@/src/hooks/useColors";
export default function ClockScreen() {
const {colors} = useColors();
const clockConfig = useMatrixStore((s) => s.matrixState.clock);
const updateClockConfig = useMatrixStore((s) => s.updateClockConfig);
return (
<ThemedBackground>
<ThemedHeader>
Clock Mode
</ThemedHeader>
<View className="flex-1 justify-between">
<View>
<ThemedHeader subtitle="Zeige die Uhrzeit an">
Uhr Modus
</ThemedHeader>
<View className="bg-surface dark:bg-surface-dark rounded-2xl p-6 mt-4">
<View className="items-center mb-6">
<View className="w-16 h-16 rounded-full bg-primary/10 dark:bg-primary-light/10 items-center justify-center mb-3">
<Feather name="clock" size={32} color={colors.primary} />
</View>
<Text className="text-base font-medium text-onSurface dark:text-onSurface-dark">
Uhr Anzeige
</Text>
</View>
<View>
<Text className="text-sm font-medium text-muted dark:text-muted-dark mb-2">
Uhrzeitfarbe
</Text>
<ColorSelector
onSelect={(color) => updateClockConfig({ color })}
defaultColor={clockConfig.color}
/>
</View>
</View>
</View>
<SaveToMatrixButton mode="clock" />
</View>
</ThemedBackground>
);
}
+61 -39
View File
@@ -17,6 +17,8 @@ import ThemedButton from "@/src/components/themed/ThemedButton";
import {useColors} from "@/src/hooks/useColors";
import {useAuth} from "@/src/stores/authStore";
import {MaterialIcons} from '@expo/vector-icons';
import { useMatrixStore } from "@/src/stores";
import SaveToMatrixButton from "@/src/components/SaveToMatrixButton";
export default function ImageScreen() {
const {token} = useAuth();
@@ -27,6 +29,9 @@ export default function ImageScreen() {
const [deletingFile, setDeletingFile] = useState<string | null>(null);
const {colors} = useColors();
const imageConfig = useMatrixStore((s) => s.matrixState.image);
const updateImageConfig = useMatrixStore((s) => s.updateImageConfig);
const fetchStoredFiles = async () => {
setLoadingFiles(true);
try {
@@ -154,98 +159,105 @@ export default function ImageScreen() {
return (
<ThemedBackground>
<ThemedHeader>
Bildschirm für Bildauswahl
<ThemedHeader subtitle="Lade Bilder hoch und zeige sie an">
Bilder Modus
</ThemedHeader>
<View className="flex-1 w-full p-4">
<View className="flex-1 w-full">
{uploading ? (
<View className="flex-1 justify-center items-center">
<View className="flex-1 justify-center items-center bg-surface dark:bg-surface-dark rounded-2xl p-8">
<ActivityIndicator size="large" color={colors.primary}/>
<Text className="mt-2.5 text-base text-onSurface dark:text-onSurface-dark">
<Text className="mt-4 text-base font-medium text-onSurface dark:text-onSurface-dark">
Datei wird hochgeladen...
</Text>
</View>
) : (
<CustomImagePicker
onSuccess={onSuccess}
onFailure={onFailure}
onCanceled={onCanceled}
/>
<View className="bg-surface dark:bg-surface-dark rounded-2xl p-5">
<CustomImagePicker
onSuccess={onSuccess}
onFailure={onFailure}
onCanceled={onCanceled}
/>
</View>
)}
<View className="my-5 items-center">
<View className="my-4">
<ThemedButton
onPress={toggleFilesList}
title={showFiles ? "Dateien ausblenden" : "Gespeicherte Dateien anzeigen"}
mode="contained"
mode={showFiles ? "outlined" : "contained"}
icon={showFiles ? "eye-off" : "folder"}
/>
</View>
{showFiles && (
<View className="flex-1 w-full">
<ThemedHeader>Gespeicherte Dateien</ThemedHeader>
<Text className="text-base font-semibold text-onSurface dark:text-onSurface-dark mb-3">
Gespeicherte Dateien
</Text>
{loadingFiles ? (
<ActivityIndicator size="large" color={colors.primary}/>
<View className="items-center py-8">
<ActivityIndicator size="large" color={colors.primary}/>
</View>
) : files.length > 0 ? (
<FlatList
data={files}
keyExtractor={(item) => item.key}
renderItem={({item}) => (
<View
className="p-3 my-2 border rounded-lg relative border-outline dark:border-outline-dark"
>
<Text className="font-bold text-onSurface dark:text-onSurface-dark">
<View className="p-4 my-1.5 rounded-xl relative bg-surface dark:bg-surface-dark border border-outline/30 dark:border-outline-dark/30">
<Text className="font-semibold text-onSurface dark:text-onSurface-dark mb-1">
{item.originalName}
</Text>
<Text className="text-onSurface dark:text-onSurface-dark">
Typ: {item.mimeType}
<Text className="text-sm text-muted dark:text-muted-dark">
{item.mimeType} {formatFileSize(item.size)}
</Text>
<Text className="text-onSurface dark:text-onSurface-dark">
Größe: {formatFileSize(item.size)}
<Text className="text-xs text-muted dark:text-muted-dark mt-1">
{formatDate(item.lastModified)}
</Text>
<Text className="text-onSurface dark:text-onSurface-dark">
Zuletzt geändert: {formatDate(item.lastModified)}
</Text>
<View className="flex-row absolute top-3 right-3">
<View className="flex-row absolute top-3 right-3 gap-2">
<TouchableOpacity
className="w-9 h-9 rounded-full justify-center items-center ml-2 bg-primary"
className="w-10 h-10 rounded-xl justify-center items-center bg-primary"
onPress={() => viewFile(item.key)}
>
<MaterialIcons name="visibility" size={24} color="white"/>
<MaterialIcons name="visibility" size={22} color="white"/>
</TouchableOpacity>
<TouchableOpacity
className="w-9 h-9 rounded-full justify-center items-center ml-2 bg-error"
className="w-10 h-10 rounded-xl justify-center items-center bg-error"
onPress={() => confirmDeleteFile(item.key)}
>
<MaterialIcons name="delete" size={24} color="white"/>
<MaterialIcons name="delete" size={22} color="white"/>
</TouchableOpacity>
</View>
</View>
)}
/>
) : (
<Text className="text-center text-onSurface dark:text-onSurface-dark">
Keine Dateien gefunden
</Text>
<View className="items-center py-8 bg-surface dark:bg-surface-dark rounded-2xl">
<Text className="text-muted dark:text-muted-dark">
Keine Dateien gefunden
</Text>
</View>
)}
</View>
)}
<Modal
animationType="slide"
animationType="fade"
transparent={true}
visible={!!deletingFile}
onRequestClose={cancelDelete}
>
<View className="flex-1 justify-center items-center bg-black/50">
<View className="w-4/5 bg-surface dark:bg-surface-dark rounded-lg p-5 items-center">
<Text className="mb-4 text-center text-onSurface dark:text-onSurface-dark">
Sind Sie sicher, dass Sie diese Datei löschen möchten?
<View className="flex-1 justify-center items-center bg-black/60 px-6">
<View className="w-full max-w-sm bg-surface dark:bg-surface-dark rounded-2xl p-6">
<Text className="text-lg font-semibold text-center text-onSurface dark:text-onSurface-dark mb-2">
Datei löschen?
</Text>
<View className="flex-row justify-between w-full">
<Text className="text-sm text-center text-muted dark:text-muted-dark mb-6">
Diese Aktion kann nicht rückgängig gemacht werden.
</Text>
<View className="gap-2">
<ThemedButton
onPress={() => {
if (deletingFile) {
@@ -255,6 +267,7 @@ export default function ImageScreen() {
}}
title="Ja, löschen"
mode="contained"
className="bg-error"
/>
<ThemedButton
onPress={cancelDelete}
@@ -265,6 +278,15 @@ export default function ImageScreen() {
</View>
</View>
</Modal>
{imageConfig.image && (
<View className="mt-4">
<Text className="text-sm text-muted dark:text-muted-dark mb-2">
Ausgewähltes Bild: {imageConfig.image}
</Text>
<SaveToMatrixButton mode="image" />
</View>
)}
</View>
</ThemedBackground>
);
+46 -3
View File
@@ -1,13 +1,56 @@
import React from "react";
import {View, Text} from "react-native";
import {Feather} from "@expo/vector-icons";
import ThemedBackground from "@/src/components/themed/ThemedBackground";
import ThemedHeader from "@/src/components/themed/ThemedHeader";
import ThemedCheckbox from "@/src/components/themed/ThemedCheckbox";
import SaveToMatrixButton from "@/src/components/SaveToMatrixButton";
import { useMatrixStore } from "@/src/stores";
import { useAuth } from "@/src/stores/authStore";
import {useColors} from "@/src/hooks/useColors";
export default function MusicScreen() {
const {colors} = useColors();
const { authenticatedUser } = useAuth();
const musicConfig = useMatrixStore((s) => s.matrixState.music);
const updateMusicConfig = useMatrixStore((s) => s.updateMusicConfig);
const hasSpotify = !!authenticatedUser?.spotifyConfig;
return (
<ThemedBackground>
<ThemedHeader>
Music Mode
</ThemedHeader>
<View className="flex-1 justify-between">
<View>
<ThemedHeader subtitle="Visualisiere deine Musik">
Musik Modus
</ThemedHeader>
<View className="bg-surface dark:bg-surface-dark rounded-2xl p-6 mt-4">
<View className="items-center mb-6">
<View className="w-16 h-16 rounded-full bg-primary/10 dark:bg-primary-light/10 items-center justify-center mb-3">
<Feather name="music" size={32} color={colors.primary} />
</View>
<Text className="text-base font-medium text-onSurface dark:text-onSurface-dark">
Musik Visualisierung
</Text>
{!hasSpotify && (
<Text className="text-sm text-muted dark:text-muted-dark text-center mt-2">
Verbinde Spotify in den Einstellungen
</Text>
)}
</View>
<ThemedCheckbox
label="Vollbild-Modus"
description="Zeigt die Visualisierung im Vollbild"
value={musicConfig.fullscreen}
onValueChange={(fullscreen) => updateMusicConfig({ fullscreen })}
/>
</View>
</View>
<SaveToMatrixButton mode="music" />
</View>
</ThemedBackground>
);
}
+41 -35
View File
@@ -1,62 +1,68 @@
import ThemedBackground from "@/src/components/themed/ThemedBackground";
import ThemedTextInput from "@/src/components/themed/ThemedTextInput";
import ThemedButton from "@/src/components/themed/ThemedButton";
import ColorSelector from "@/src/components/themed/ColorSelector";
import {View} from "react-native";
import {View, Text} from "react-native";
import ThemedSegmentedButtons from "@/src/components/themed/ThemedSegmentedButtons";
import { MatrixState } from '@/src/model/User';
import { useMatrixStore } from "@/src/stores";
import ThemedHeader from "@/src/components/themed/ThemedHeader";
import SaveToMatrixButton from "@/src/components/SaveToMatrixButton";
type TextProps = MatrixState['text'];
export default function TextScreen() {
const textConfig = useMatrixStore((s) => s.matrixState.text);
const updateTextConfig = useMatrixStore((s) => s.updateTextConfig);
const setGlobalMode = useMatrixStore((s) => s.setGlobalMode);
const matrixState = useMatrixStore((s) => s.matrixState);
const updateTextProp = (prop: Partial<TextProps>) => {
updateTextConfig(prop);
setGlobalMode('text');
};
const handleSendToMatrix = () => {
console.log("Sende an Matrix:", matrixState);
};
return (
<ThemedBackground>
<View className="flex-1 justify-between p-5">
<View className="flex-1 justify-between">
<View className="gap-4">
<ThemedTextInput
label="Text"
value={textConfig.text}
onChangeText={(text) => updateTextProp({ text })}
/>
<ThemedHeader subtitle="Zeige Text auf deiner Matrix an">
Text Modus
</ThemedHeader>
<ColorSelector
onSelect={(color) => updateTextProp({ color })}
defaultColor={textConfig.color}
/>
<View className="bg-surface dark:bg-surface-dark rounded-2xl p-5 gap-4">
<ThemedTextInput
label="Dein Text"
value={textConfig.text}
onChangeText={(text) => updateTextProp({ text })}
className="my-0"
/>
<ThemedSegmentedButtons
value={textConfig.align}
onValueChange={(align) => updateTextProp({ align })}
options={{
left: 'Links',
center: 'Mitte',
right: 'Rechts',
}}
/>
<View>
<Text className="text-sm font-medium text-muted dark:text-muted-dark mb-2">
Textfarbe
</Text>
<ColorSelector
onSelect={(color) => updateTextProp({ color })}
defaultColor={textConfig.color}
/>
</View>
<View>
<Text className="text-sm font-medium text-muted dark:text-muted-dark mb-2">
Ausrichtung
</Text>
<ThemedSegmentedButtons
value={textConfig.align}
onValueChange={(align) => updateTextProp({ align })}
options={{
left: 'Links',
center: 'Mitte',
right: 'Rechts',
}}
className="my-0"
/>
</View>
</View>
</View>
<View className="pt-5">
<ThemedButton
mode="contained"
onPress={handleSendToMatrix}
title={"An die Matrix senden"}
/>
</View>
<SaveToMatrixButton mode="text" />
</View>
</ThemedBackground>
);