switched to react navigation stacks instead of modals

main
alex 2023-07-23 19:59:43 +00:00
parent 0b7612a8a6
commit af351d4168
14 changed files with 446 additions and 372 deletions

133
App.js
View File

@ -2,7 +2,7 @@ import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar"; import { StatusBar } from "expo-status-bar";
import { Text, View } from "react-native"; import { Text, View } from "react-native";
import { createDrawerNavigator } from "@react-navigation/drawer"; import { createDrawerNavigator } from "@react-navigation/drawer";
import { NavigationContainer } from "@react-navigation/native"; import { DefaultTheme, NavigationContainer } from "@react-navigation/native";
import SideBar from "./src/Components/SideBar"; import SideBar from "./src/Components/SideBar";
import { import {
AppContext, AppContext,
@ -20,7 +20,18 @@ import { createStackNavigator } from "@react-navigation/stack";
import { TouchableOpacity } from "react-native"; import { TouchableOpacity } from "react-native";
import MyIcon from "./src/Components/Icon"; import MyIcon from "./src/Components/Icon";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { LightsEditActionModalContent } from "./src/Screens/Device/modals/EditActions/Lights"; import {
LayersEditActionColorModeSelectionModalContent,
LightsEditActionModalContent,
} from "./src/Screens/Device/modals/EditActions/Lights";
import ChooseSceneModalContent from "./src/Screens/Device/modals/ChooseScene";
import CreateSceneModalContent from "./src/Screens/Device/modals/ChooseScene/CreateScene";
import AddSceneActionModalContent from "./src/Screens/Device/modals/AddSceneAction";
import LayerSelectionModalContent from "./src/Screens/Device/modals/AddSceneAction/LayerSelection";
import {
SettingsAppColorSchemeModalContent,
SettingsAppLanguageModalContent,
} from "./src/Screens/Settings";
const Drawer = createDrawerNavigator(); const Drawer = createDrawerNavigator();
const Stack = createStackNavigator(); const Stack = createStackNavigator();
@ -66,20 +77,32 @@ export function MyApp() {
loadData(); loadData();
}, []); }, []);
const options = ({ navigation }) => { const options = ({ navigation, pageTitle }) => {
return getScreenStackOptions( return getScreenStackOptions(
navigation, navigation,
t("screens.device.scenes.modalLayersEditAction.headerTitle"), pageTitle,
appContext.appTheme.text, appContext.appTheme.text,
appContext.appTheme.backgroundColor, appContext.appTheme.backgroundColor,
true true
); );
}; };
const navigatonTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: appContext.appTheme.backgroundColor,
},
};
return ( return (
<SafeAreaView style={{ height: "100%" }}> <SafeAreaView style={{ height: "100%" }}>
<NavigationContainer> <NavigationContainer theme={navigatonTheme}>
<Stack.Navigator screenOptions={{ headerTitleAlign: "center" }}> <Stack.Navigator
screenOptions={{
headerTitleAlign: "center",
}}
>
<Stack.Screen <Stack.Screen
name="drawer" name="drawer"
component={MyDrawer} component={MyDrawer}
@ -87,9 +110,103 @@ export function MyApp() {
/> />
<Stack.Screen <Stack.Screen
name="modalLayersEditActionIsOpen" name="modalChooseScene"
component={ChooseSceneModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalChooseScene.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalCreateScene"
component={CreateSceneModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalCreateScene.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalAddSceneAction"
component={AddSceneActionModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalAddSceneAction.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalLayerSection"
component={LayerSelectionModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalLayerSection.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalLayersEditAction"
component={LightsEditActionModalContent} component={LightsEditActionModalContent}
options={options} options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalLayersEditAction.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalLayersEditActionColorModeSelection"
component={LayersEditActionColorModeSelectionModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalLayersEditActionColorModeSelection.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalSettingsAppColorScheme"
component={SettingsAppColorSchemeModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t("screens.settings.appColorSchemeModalTitle"),
})
}
/>
<Stack.Screen
name="modalSettingsAppLanguage"
component={SettingsAppLanguageModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t("screens.settings.languageModalTitle"),
})
}
/> />
</Stack.Navigator> </Stack.Navigator>
</NavigationContainer> </NavigationContainer>

View File

@ -36,11 +36,11 @@
"infoNoActionsAvailableInScene": "Keine Aktionen in der Szene vorhanden", "infoNoActionsAvailableInScene": "Keine Aktionen in der Szene vorhanden",
"buttonAddAction": "Aktion hinzufügen", "buttonAddAction": "Aktion hinzufügen",
"modalChooseScene": { "modalChooseScene": {
"headerTitle": "Wähle eine Szene aus", "pageTitle": "Wähle eine Szene aus",
"textButtonAddScene": "Neue Szene erstellen" "textButtonAddScene": "Neue Szene erstellen"
}, },
"modalCreateScene": { "modalCreateScene": {
"headerTitle": "Szene erstellen", "pageTitle": "Szene erstellen",
"options": { "options": {
"emptyScene": "Leere Szene erstellen", "emptyScene": "Leere Szene erstellen",
"standardScene": "Standard Szene erstellen", "standardScene": "Standard Szene erstellen",
@ -48,7 +48,7 @@
} }
}, },
"modalAddSceneAction": { "modalAddSceneAction": {
"headerTitle": "Aktion hinzufügen", "pageTitle": "Aktion hinzufügen",
"actions": { "actions": {
"layers": "Ebenen", "layers": "Ebenen",
"motor": "Motor", "motor": "Motor",
@ -62,10 +62,13 @@
} }
}, },
"modalLayerSection": { "modalLayerSection": {
"headerTitle": "Layer auswahl" "pageTitle": "Layer auswahl"
}, },
"modalLayersEditAction": { "modalLayersEditAction": {
"headerTitle": "Ebenen bearbeiten" "pageTitle": "Ebenen bearbeiten"
},
"modalLayersEditActionColorModeSelection": {
"pageTitle": "Wähle einen Farbmodus"
} }
} }
}, },
@ -79,7 +82,9 @@
"pageTitle": "Einstellungen", "pageTitle": "Einstellungen",
"settingsCardTitle": "Einstellungen", "settingsCardTitle": "Einstellungen",
"languageText": "Sprache", "languageText": "Sprache",
"languageModalTitle": "Sprache anpassen",
"appColorSchemeText": "Anzeigemodus", "appColorSchemeText": "Anzeigemodus",
"appColorSchemeModalTitle": "Anzeigemodus anpassen",
"appColorSchemePicker": { "appColorSchemePicker": {
"auto": "System Standard", "auto": "System Standard",
"dark": "Dunkel", "dark": "Dunkel",

View File

@ -36,11 +36,11 @@
"infoNoActionsAvailableInScene": "No actions available in the scene", "infoNoActionsAvailableInScene": "No actions available in the scene",
"buttonAddAction": "Add action", "buttonAddAction": "Add action",
"modalChooseScene": { "modalChooseScene": {
"headerTitle": "Choose a scene", "pageTitle": "Choose a scene",
"textButtonAddScene": "Create new scene" "textButtonAddScene": "Create new scene"
}, },
"modalCreateScene": { "modalCreateScene": {
"headerTitle": "Create scene", "pageTitle": "Create scene",
"options": { "options": {
"emptyScene": "Create empty scene", "emptyScene": "Create empty scene",
"standardScene": "Create standard scene", "standardScene": "Create standard scene",
@ -48,7 +48,7 @@
} }
}, },
"modalAddSceneAction": { "modalAddSceneAction": {
"headerTitle": "Add action", "pageTitle": "Add action",
"actions": { "actions": {
"layers": "Layers", "layers": "Layers",
"motor": "Motor", "motor": "Motor",
@ -62,10 +62,13 @@
} }
}, },
"modalLayerSection": { "modalLayerSection": {
"headerTitle": "Layer selection" "pageTitle": "Layer selection"
}, },
"modalLayersEditAction": { "modalLayersEditAction": {
"headerTitle": "Edit layers" "pageTitle": "Edit layers"
},
"modalLayersEditActionColorModeSelection": {
"pageTitle": "Choose a color mode"
} }
} }
}, },
@ -79,7 +82,9 @@
"pageTitle": "Settings", "pageTitle": "Settings",
"settingsCardTitle": "Settings", "settingsCardTitle": "Settings",
"languageText": "Language", "languageText": "Language",
"languageModalTitle": "Customize language",
"appColorSchemeText": "Appearance", "appColorSchemeText": "Appearance",
"appColorSchemeModalTitle": "Customize appearance",
"appColorSchemePicker": { "appColorSchemePicker": {
"auto": "System default", "auto": "System default",
"dark": "Dark", "dark": "Dark",

View File

@ -268,22 +268,6 @@ export function MyColorPickerV2({ isUserExpertModeEnabled, appThemeText }) {
onChange={onColorSelect} onChange={onColorSelect}
boundedThumb boundedThumb
> >
<TouchableOpacity
onPress={() =>
setColorSwatchesFavorites([
...colorSwatchesFavorites,
selectedColorPickerColor.value,
])
}
style={{
position: "absolute",
top: -18,
right: 2,
}}
>
<MyIcon name="star-outline" size={20} />
</TouchableOpacity>
<View style={{ flexDirection: "row", justifyContent: "space-evenly" }}> <View style={{ flexDirection: "row", justifyContent: "space-evenly" }}>
<Panel3 style={{ width: 200 }} /> <Panel3 style={{ width: 200 }} />

View File

@ -97,7 +97,7 @@ export function MyDefaultModalHeader({ title, closeModal }) {
<Text <Text
style={[ style={[
AppStyles.typography16, AppStyles.typography20,
{ fontWeight: "bold", color: appContext.appTheme.text }, { fontWeight: "bold", color: appContext.appTheme.text },
]} ]}
> >

View File

@ -1,7 +1,7 @@
import { DrawerContentScrollView, DrawerItem } from "@react-navigation/drawer"; import { DrawerContentScrollView, DrawerItem } from "@react-navigation/drawer";
import { useContext } from "react"; import { useContext } from "react";
import { Image, Text, TouchableOpacity, View } from "react-native"; import { Image, Text, TouchableOpacity, View } from "react-native";
import { AppContext, AppStyles } from "../../utils"; import { AppContext, AppSelectedUserDevice, AppStyles } from "../../utils";
import { Divider } from "../Divider"; import { Divider } from "../Divider";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import MyIcon from "../Icon"; import MyIcon from "../Icon";
@ -27,6 +27,8 @@ export default function Sidebar(props) {
? appContext.appTheme.drawer.item.activeTintColor ? appContext.appTheme.drawer.item.activeTintColor
: appContext.appTheme.drawer.item.inactiveTintColor; : appContext.appTheme.drawer.item.inactiveTintColor;
if (isFocused && isDevice) AppSelectedUserDevice.current = routeName;
return ( return (
<DrawerItem <DrawerItem
label={() => label={() =>
@ -138,11 +140,6 @@ export default function Sidebar(props) {
label={"Old Device"} label={"Old Device"}
onPress={() => props.navigation.navigate("Old Turtle")} onPress={() => props.navigation.navigate("Old Turtle")}
/> />
<MyDrawerItem
label={"test"}
onPress={() => props.navigation.navigate("test")}
/>
</DrawerContentScrollView> </DrawerContentScrollView>
<View style={{ justifyContent: "flex-end" }}> <View style={{ justifyContent: "flex-end" }}>

View File

@ -2,6 +2,7 @@ import { useState } from "react";
import { Text, TouchableHighlight, View } from "react-native"; import { Text, TouchableHighlight, View } from "react-native";
import MyButton from "../../../../../Components/Button"; import MyButton from "../../../../../Components/Button";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { AppSelectedUserDevice, ModalContainer } from "../../../../../utils";
function Layer({ number, selected, onPress }) { function Layer({ number, selected, onPress }) {
return ( return (
@ -36,9 +37,7 @@ function Layer({ number, selected, onPress }) {
); );
} }
export default function LayerSelectionModalContent({ export default function LayerSelectionModalContent({ navigation, route }) {
openLayersActionEditModal,
}) {
const { t } = useTranslation(); const { t } = useTranslation();
const [selectedLayer, setSelectedLayer] = useState([]); const [selectedLayer, setSelectedLayer] = useState([]);
@ -53,7 +52,7 @@ export default function LayerSelectionModalContent({
}; };
return ( return (
<> <ModalContainer>
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -77,9 +76,12 @@ export default function LayerSelectionModalContent({
title={t("screens.device.scenes.buttonAddAction")} title={t("screens.device.scenes.buttonAddAction")}
style={{ marginTop: 20, width: 180 }} style={{ marginTop: 20, width: 180 }}
disabled={selectedLayer.length === 0} disabled={selectedLayer.length === 0}
onPress={openLayersActionEditModal} onPress={() => {
navigation.navigate(AppSelectedUserDevice.current);
navigation.navigate("modalLayersEditAction", route.params);
}}
/> />
</View> </View>
</> </ModalContainer>
); );
} }

View File

@ -1,6 +1,6 @@
import { useContext } from "react"; import { useContext } from "react";
import { Image, Text, TouchableOpacity, View } from "react-native"; import { Image, ScrollView, Text, TouchableOpacity, View } from "react-native";
import { AppContext, AppStyles } from "../../../../utils"; import { AppContext, AppStyles, ModalContainer } from "../../../../utils";
import MyIcon from "../../../../Components/Icon"; import MyIcon from "../../../../Components/Icon";
import { Divider } from "../../../../Components/Divider"; import { Divider } from "../../../../Components/Divider";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@ -65,100 +65,103 @@ function Action({
); );
} }
export default function AddSceneActionModalContent({ export default function AddSceneActionModalContent({ navigation, route }) {
device,
openLayerSelectionModal,
}) {
const { t } = useTranslation(); const { t } = useTranslation();
// TODO: check model type for actions const deviceFirmwareVersion = route.params.deviceFirmwareVersion;
// TODO: show only actions by device model
return ( return (
<> <ScrollView>
<Action <ModalContainer>
text={t("screens.device.scenes.modalAddSceneAction.actions.layers")} <Action
iconName="lightbulb-on-outline" text={t("screens.device.scenes.modalAddSceneAction.actions.layers")}
imageSource={require("../../../../../assets/layers.gif")} iconName="lightbulb-on-outline"
onPress={openLayerSelectionModal} imageSource={require("../../../../../assets/layers.gif")}
deviceFirmwareVersion={device.firmwareVersion} onPress={() => navigation.navigate("modalLayerSection", route.params)}
supportedFirmwareVersions={["1.0.1"]} deviceFirmwareVersion={deviceFirmwareVersion}
/> supportedFirmwareVersions={["1.0.1"]}
/>
<Action <Action
text={t("screens.device.scenes.modalAddSceneAction.actions.motor")} text={t("screens.device.scenes.modalAddSceneAction.actions.motor")}
iconName="axis-z-rotate-counterclockwise" iconName="axis-z-rotate-counterclockwise"
imageSource={require("../../../../../assets/motor.gif")} imageSource={require("../../../../../assets/motor.gif")}
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]} supportedFirmwareVersions={["1.0.1"]}
/> />
<Action <Action
text={t("screens.device.scenes.modalAddSceneAction.actions.ambilight")} text={t(
iconName="television-ambient-light" "screens.device.scenes.modalAddSceneAction.actions.ambilight"
imageSource={require("../../../../../assets/ambilight.gif")} )}
onPress={() => console.log("pressed action")} iconName="television-ambient-light"
deviceFirmwareVersion={device.firmwareVersion} imageSource={require("../../../../../assets/ambilight.gif")}
supportedFirmwareVersions={["1.0.1"]} onPress={() => console.log("pressed action")}
/> deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]}
/>
<Action <Action
text={t( text={t(
"screens.device.scenes.modalAddSceneAction.actions.waitXSeconds" "screens.device.scenes.modalAddSceneAction.actions.waitXSeconds"
)} )}
iconName="timer-sand" iconName="timer-sand"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]} supportedFirmwareVersions={["1.0.1"]}
/> />
<Action <Action
text={t( text={t(
"screens.device.scenes.modalAddSceneAction.actions.waitUntilTimeX" "screens.device.scenes.modalAddSceneAction.actions.waitUntilTimeX"
)} )}
iconName="clock-time-eight-outline" iconName="clock-time-eight-outline"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]} supportedFirmwareVersions={["1.0.1"]}
/> />
<Action <Action
text={t("screens.device.scenes.modalAddSceneAction.actions.stop")} text={t("screens.device.scenes.modalAddSceneAction.actions.stop")}
iconName="pause-octagon-outline" iconName="pause-octagon-outline"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]} supportedFirmwareVersions={["1.0.1"]}
/> />
<Action <Action
text={t( text={t(
"screens.device.scenes.modalAddSceneAction.actions.timeControl" "screens.device.scenes.modalAddSceneAction.actions.timeControl"
)} )}
iconName="timer-cog" iconName="timer-cog"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.1"]} supportedFirmwareVersions={["1.0.1"]}
/> />
<Action <Action
text={t( text={t(
"screens.device.scenes.modalAddSceneAction.actions.waitForConfirmationWithKey" "screens.device.scenes.modalAddSceneAction.actions.waitForConfirmationWithKey"
)} )}
iconName="gesture-tap-button" iconName="gesture-tap-button"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.0"]} supportedFirmwareVersions={["1.0.0"]}
/> />
<Action <Action
text={t( text={t(
"screens.device.scenes.modalAddSceneAction.actions.jumpToScene" "screens.device.scenes.modalAddSceneAction.actions.jumpToScene"
)} )}
iconName="debug-step-over" iconName="debug-step-over"
onPress={() => console.log("pressed action")} onPress={() => console.log("pressed action")}
deviceFirmwareVersion={device.firmwareVersion} deviceFirmwareVersion={deviceFirmwareVersion}
supportedFirmwareVersions={["1.0.0"]} supportedFirmwareVersions={["1.0.0"]}
/> />
</> </ModalContainer>
</ScrollView>
); );
} }

View File

@ -1,13 +1,14 @@
import { useContext } from "react"; import { useContext } from "react";
import { AppContext, NewEmptyDeviceScene } from "../../../../../utils"; import {
AppContext,
ModalContainer,
NewEmptyDeviceScene,
} from "../../../../../utils";
import { FlatList } from "react-native"; import { FlatList } from "react-native";
import { MyPickerModalListItem } from "../../../../../Components/Modal"; import { MyPickerModalListItem } from "../../../../../Components/Modal";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
export default function CreateSceneModalContent({ export default function CreateSceneModalContent({ navigation, route }) {
device,
closeChooseSceneModals,
}) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const { t } = useTranslation(); const { t } = useTranslation();
@ -29,27 +30,29 @@ export default function CreateSceneModalContent({
]; ];
return ( return (
<FlatList <ModalContainer>
data={options} <FlatList
keyExtractor={(item) => item.id} data={options}
renderItem={({ item }) => ( keyExtractor={(item) => item.id}
<MyPickerModalListItem renderItem={({ item }) => (
itemName={item.name} <MyPickerModalListItem
onPress={() => { itemName={item.name}
appContext.setDevices((arr) => { onPress={() => {
const newArr = [...arr]; appContext.setDevices((arr) => {
const newArr = [...arr];
newArr[arr.findIndex((d) => d.id === device.id)].scenes.push( newArr[
NewEmptyDeviceScene() arr.findIndex((d) => d.id === route.params.id)
); ].scenes.push(NewEmptyDeviceScene());
return newArr; return newArr;
}); });
closeChooseSceneModals(); navigation.pop(2);
}} }}
/> />
)} )}
/> />
</ModalContainer>
); );
} }

View File

@ -1,20 +1,19 @@
import { useContext } from "react"; import { useContext } from "react";
import { FlatList } from "react-native"; import { FlatList } from "react-native";
import { AppContext } from "../../../../utils"; import { AppContext, ModalContainer } from "../../../../utils";
import { MyPickerModalListItem } from "../../../../Components/Modal"; import { MyPickerModalListItem } from "../../../../Components/Modal";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { MyTextButton } from "../../../../Components/Button"; import { MyTextButton } from "../../../../Components/Button";
import MyResult from "../../../../Components/Result"; import MyResult from "../../../../Components/Result";
export default function ChooseSceneModalContent({ export default function ChooseSceneModalContent({ navigation, route }) {
device,
openCreateSceneModal,
}) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const { t } = useTranslation(); const { t } = useTranslation();
const device = route.params;
return ( return (
<> <ModalContainer>
{device.scenes.length === 0 ? ( {device.scenes.length === 0 ? (
<MyResult <MyResult
text={"Keine Szenen vorhanden"} text={"Keine Szenen vorhanden"}
@ -38,6 +37,8 @@ export default function ChooseSceneModalContent({
return newArr; return newArr;
}); });
navigation.goBack();
}} }}
/> />
)} )}
@ -47,9 +48,11 @@ export default function ChooseSceneModalContent({
<MyTextButton <MyTextButton
style={{ marginTop: 10 }} style={{ marginTop: 10 }}
actionColor={!device.scenes.length} actionColor={!device.scenes.length}
onPress={openCreateSceneModal} onPress={() =>
navigation.navigate("modalCreateScene", { id: device.id })
}
title={t("screens.device.scenes.modalChooseScene.textButtonAddScene")} title={t("screens.device.scenes.modalChooseScene.textButtonAddScene")}
/> />
</> </ModalContainer>
); );
} }

View File

@ -7,14 +7,14 @@ import {
import Card from "../../../../../Components/Card"; import Card from "../../../../../Components/Card";
import MyDropdown from "../../../../../Components/Dropdown"; import MyDropdown from "../../../../../Components/Dropdown";
import { useContext, useState } from "react"; import { useContext, useState } from "react";
import { AppContext } from "../../../../../utils"; import { AppContext, ModalContainer } from "../../../../../utils";
import MyModal, { import MyModal, {
MyDefaultModalHeader, MyDefaultModalHeader,
MyPickerModalListItem, MyPickerModalListItem,
} from "../../../../../Components/Modal"; } from "../../../../../Components/Modal";
import { MyColorPickerV2 } from "../../../../../Components/ColorPicker"; import { MyColorPickerV2 } from "../../../../../Components/ColorPicker";
export function LightsEditActionModalContent({ route }) { export function LightsEditActionModalContent({ navigation, route }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const [modalColorModeSelectionIsOpen, setModalColorSelectionModeIsOpen] = const [modalColorModeSelectionIsOpen, setModalColorSelectionModeIsOpen] =
useState(false); useState(false);
@ -64,7 +64,12 @@ export function LightsEditActionModalContent({ route }) {
appContext.appLanguage appContext.appLanguage
] ]
} }
onPress={() => setModalColorSelectionModeIsOpen(true)} onPress={() =>
navigation.navigate("modalLayersEditActionColorModeSelection", {
supportedLightModes: supportedLightModes,
selectedLightMode: selectedLightMode,
})
}
/> />
<MyColorPickerV2 <MyColorPickerV2
@ -77,32 +82,31 @@ export function LightsEditActionModalContent({ route }) {
<Card key={i} /> <Card key={i} />
))} ))}
</ScrollView> </ScrollView>
<MyModal
isOpen={modalColorModeSelectionIsOpen}
closeModal={() => setModalColorSelectionModeIsOpen(false)}
header={
<MyDefaultModalHeader
title={"Farbmodus wählen"}
closeModal={() => setModalColorSelectionModeIsOpen(false)}
/>
}
content={
<FlatList
data={supportedLightModes}
renderItem={({ item, index }) => (
<MyPickerModalListItem
itemName={item.name[appContext.appLanguage]}
itemSelected={selectedLightMode === index}
onPress={() => {
setSelectedLightMode(index);
setModalColorSelectionModeIsOpen(false);
}}
/>
)}
/>
}
/>
</View> </View>
); );
} }
export function LayersEditActionColorModeSelectionModalContent({
navigation,
route,
}) {
const appContext = useContext(AppContext);
return (
<ModalContainer>
<FlatList
data={route.params.supportedLightModes}
renderItem={({ item, index }) => (
<MyPickerModalListItem
itemName={item.name[appContext.appLanguage]}
itemSelected={route.params.selectedLightMode === index}
onPress={() => {
// TODO: set selected light mode directly in appContext actions
navigation.goBack();
}}
/>
)}
/>
</ModalContainer>
);
}

View File

@ -1,16 +1,12 @@
import { FlatList, Text, TouchableOpacity, View } from "react-native"; import { FlatList, Text, TouchableOpacity, View } from "react-native";
import Card from "../../Components/Card"; import Card from "../../Components/Card";
import { AppContext, IsPlatformIos } from "../../utils"; import { AppContext } from "../../utils";
import { useContext, useState } from "react"; import { useContext } from "react";
import MyDropdown from "../../Components/Dropdown"; import MyDropdown from "../../Components/Dropdown";
import MyIcon from "../../Components/Icon"; import MyIcon from "../../Components/Icon";
import MyModal, { MyDefaultModalHeader } from "../../Components/Modal";
import CreateSceneModalContent from "./modals/ChooseScene/CreateScene";
import ChooseSceneModalContent from "./modals/ChooseScene";
import AddSceneActionModalContent from "./modals/AddSceneAction";
import LayerSelectionModalContent from "./modals/AddSceneAction/LayerSelection";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import MyResult from "../../Components/Result"; import MyResult from "../../Components/Result";
import { MyTextButton } from "../../Components/Button";
export default function SceneView({ navigation, device }) { export default function SceneView({ navigation, device }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
@ -20,58 +16,18 @@ export default function SceneView({ navigation, device }) {
(scene) => scene.id === device.selectedScene (scene) => scene.id === device.selectedScene
); );
const [modalOpenStates, setModalOpenStates] = useState({
modalChooseSceneIsOpen: false,
modalCreateSceneIsOpen: false,
modalAddSceneActionIsOpen: false,
modalLayerSectionIsOpen: false,
modalLayersEditActionIsOpen: false,
});
const setModalOpen = (modalName, open) =>
setModalOpenStates((prevState) => ({
...prevState,
[modalName]: open,
}));
const closeChooseSceneModals = () =>
setModalOpenStates((prevState) => ({
...prevState,
modalChooseSceneIsOpen: false,
modalCreateSceneIsOpen: false,
}));
const openLayersActionEditModal = () => {
setModalOpenStates((prevState) => ({
...prevState,
modalChooseSceneIsOpen: false,
modalCreateSceneIsOpen: false,
modalAddSceneActionIsOpen: false,
modalLayerSectionIsOpen: false,
}));
// setTimeout is needed, otherwise the modal would not open on iOS
IsPlatformIos()
? setTimeout(
() =>
setModalOpenStates((prevState) => ({
...prevState,
modalLayersEditActionIsOpen: true,
})),
600
)
: setModalOpenStates((prevState) => ({
...prevState,
modalLayersEditActionIsOpen: true,
}));
};
return ( return (
<> <>
<Card> <Card>
<MyDropdown <MyDropdown
label={t("screens.device.scenes.dropdownSceneSelection.label")} label={t("screens.device.scenes.dropdownSceneSelection.label")}
onPress={() => setModalOpen("modalChooseSceneIsOpen", true)} onPress={() =>
navigation.navigate("modalChooseScene", {
id: device.id,
selectedScene: device.selectedScene,
scenes: device.scenes,
})
}
selectedItemLabel={ selectedItemLabel={
device.selectedScene === null device.selectedScene === null
? t( ? t(
@ -110,7 +66,7 @@ export default function SceneView({ navigation, device }) {
<Text>{item.name}</Text> <Text>{item.name}</Text>
<TouchableOpacity <TouchableOpacity
onPress={() => onPress={() =>
navigation.navigate("modalLayersEditActionIsOpen", { navigation.navigate("modalLayersEditAction", {
deviceFirmwareVersion: device.firmware.version, deviceFirmwareVersion: device.firmware.version,
}) })
} }
@ -122,85 +78,19 @@ export default function SceneView({ navigation, device }) {
)} )}
/> />
)} )}
<MyTextButton
title={t("screens.device.scenes.buttonAddAction")}
style={{ marginTop: 10 }}
actionColor={deviceScene.actions.length === 0}
onPress={() =>
navigation.navigate("modalAddSceneAction", {
deviceFirmwareVersion: device.firmware.version,
})
}
/>
</View> </View>
)} )}
<MyModal
isOpen={modalOpenStates.modalChooseSceneIsOpen}
closeModal={() => setModalOpen("modalChooseSceneIsOpen", false)}
header={
<MyDefaultModalHeader
title={t("screens.device.scenes.modalChooseScene.headerTitle")}
closeModal={() => setModalOpen("modalChooseSceneIsOpen", false)}
/>
}
content={
<ChooseSceneModalContent
device={{
id: device.id,
selectedScene: device.selectedScene,
scenes: device.scenes,
}}
openCreateSceneModal={() =>
setModalOpen("modalCreateSceneIsOpen", true)
}
/>
}
>
<MyModal
isOpen={modalOpenStates.modalCreateSceneIsOpen}
closeModal={() => setModalOpen("modalCreateSceneIsOpen", false)}
header={
<MyDefaultModalHeader
title={t("screens.device.scenes.modalCreateScene.headerTitle")}
closeModal={() => setModalOpen("modalCreateSceneIsOpen", false)}
/>
}
content={
<CreateSceneModalContent
device={{ id: device.id }}
closeChooseSceneModals={closeChooseSceneModals}
/>
}
/>
</MyModal>
<MyModal
scrollView
isOpen={modalOpenStates.modalAddSceneActionIsOpen}
closeModal={() => setModalOpen("modalAddSceneActionIsOpen", false)}
header={
<MyDefaultModalHeader
title={t("screens.device.scenes.modalAddSceneAction.headerTitle")}
closeModal={() => setModalOpen("modalAddSceneActionIsOpen", false)}
/>
}
content={
<AddSceneActionModalContent
device={{ firmwareVersion: device.firmware.version }}
openLayerSelectionModal={() =>
setModalOpen("modalLayerSectionIsOpen", true)
}
/>
}
>
<MyModal
scrollView
isOpen={modalOpenStates.modalLayerSectionIsOpen}
closeModal={() => setModalOpen("modalLayerSectionIsOpen", false)}
header={
<MyDefaultModalHeader
title={t("screens.device.scenes.modalLayerSection.headerTitle")}
closeModal={() => setModalOpen("modalLayerSectionIsOpen", false)}
/>
}
content={
<LayerSelectionModalContent
openLayersActionEditModal={() => openLayersActionEditModal()}
/>
}
/>
</MyModal>
</> </>
); );
} }

View File

@ -1,18 +1,15 @@
import { useContext, useState } from "react"; import { useContext } from "react";
import { Text, TouchableOpacity, View } from "react-native"; import { FlatList, Text, TouchableOpacity, View } from "react-native";
import Card from "../../Components/Card"; import Card from "../../Components/Card";
import { AppContext, AppStyles, Constants } from "../../utils"; import { AppContext, AppStyles, Constants, ModalContainer } from "../../utils";
import { Divider } from "../../Components/Divider"; import { Divider } from "../../Components/Divider";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import MySwitch from "../../Components/Switch"; import MySwitch from "../../Components/Switch";
import { MyPickerModal } from "../../Components/Modal"; import { MyPickerModalListItem } from "../../Components/Modal";
export default function SettingsScreen() { export default function SettingsScreen({ navigation }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const { t } = useTranslation(); const { t } = useTranslation();
const [modalAppColorSchemeVisible, setAppColorSchemeModalVisible] =
useState(false);
const [modalAppLanguageVisible, setModalAppLanguageVisible] = useState(false);
return ( return (
<View <View
@ -35,7 +32,7 @@ export default function SettingsScreen() {
</Text> </Text>
<TouchableOpacity <TouchableOpacity
onPress={() => setModalAppLanguageVisible(true)} onPress={() => navigation.navigate("modalSettingsAppLanguage")}
style={{ marginBottom: 6 }} style={{ marginBottom: 6 }}
> >
<View <View
@ -63,7 +60,9 @@ export default function SettingsScreen() {
</View> </View>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity onPress={() => setAppColorSchemeModalVisible(true)}> <TouchableOpacity
onPress={() => navigation.navigate("modalSettingsAppColorScheme")}
>
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -138,41 +137,72 @@ export default function SettingsScreen() {
onValueChange={(e) => appContext.setUserIsDeveloperModeEnabled(e)} onValueChange={(e) => appContext.setUserIsDeveloperModeEnabled(e)}
/> />
</View> </View>
<MyPickerModal
isOpen={modalAppColorSchemeVisible}
setIsOpen={setAppColorSchemeModalVisible}
items={[
{
label: t("screens.settings.appColorSchemePicker.auto"),
onPress: () => appContext.setAppColorScheme("auto"),
selected: appContext.appColorScheme === "auto",
},
{
label: t("screens.settings.appColorSchemePicker.dark"),
onPress: () => appContext.setAppColorScheme("dark"),
selected: appContext.appColorScheme === "dark",
},
{
label: t("screens.settings.appColorSchemePicker.light"),
onPress: () => appContext.setAppColorScheme("light"),
selected: appContext.appColorScheme === "light",
},
]}
/>
<MyPickerModal
isOpen={modalAppLanguageVisible}
setIsOpen={setModalAppLanguageVisible}
items={Constants.languages.map((language) => {
return {
label: language.label,
onPress: () => appContext.setAppLanguage(language.name),
selected: appContext.appLanguage === language.name,
};
})}
/>
</Card> </Card>
</View> </View>
); );
} }
export function SettingsAppLanguageModalContent({ navigation }) {
const appContext = useContext(AppContext);
return (
<ModalContainer>
<FlatList
data={Constants.languages}
renderItem={({ item, index }) => (
<MyPickerModalListItem
key={index}
itemName={item.label}
onPress={() => {
appContext.setAppLanguage(item.name);
navigation.goBack();
}}
itemSelected={appContext.appLanguage === item.name}
/>
)}
/>
</ModalContainer>
);
}
export function SettingsAppColorSchemeModalContent({ navigation }) {
const appContext = useContext(AppContext);
const { t } = useTranslation();
const items = [
{
label: t("screens.settings.appColorSchemePicker.auto"),
onPress: () => appContext.setAppColorScheme("auto"),
selected: appContext.appColorScheme === "auto",
},
{
label: t("screens.settings.appColorSchemePicker.dark"),
onPress: () => appContext.setAppColorScheme("dark"),
selected: appContext.appColorScheme === "dark",
},
{
label: t("screens.settings.appColorSchemePicker.light"),
onPress: () => appContext.setAppColorScheme("light"),
selected: appContext.appColorScheme === "light",
},
];
return (
<ModalContainer>
<FlatList
data={items}
renderItem={({ item, index }) => (
<MyPickerModalListItem
key={index}
itemName={item.label}
itemSelected={item.selected}
onPress={() => {
item.onPress();
navigation.goBack();
}}
/>
)}
/>
</ModalContainer>
);
}

View File

@ -1,7 +1,13 @@
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import { createContext, useState } from "react"; import { createContext, createRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Appearance, Platform, StyleSheet, Vibration } from "react-native"; import {
Appearance,
Platform,
StyleSheet,
Vibration,
View,
} from "react-native";
import uuid from "react-native-uuid"; import uuid from "react-native-uuid";
export const Constants = { export const Constants = {
@ -39,6 +45,10 @@ export const AppStyles = StyleSheet.create({
shadowOpacity: 0.2, // only ios shadowOpacity: 0.2, // only ios
shadowRadius: 1, // only ios shadowRadius: 1, // only ios
}, },
modal: {
flex: 1,
padding: 10,
},
}); });
const DarkAppTheme = { const DarkAppTheme = {
@ -342,7 +352,18 @@ const devDevices = [
lastUpdated: "11.07.2023 um 20:33 Uhr", lastUpdated: "11.07.2023 um 20:33 Uhr",
}, },
selectedScene: null, selectedScene: null,
scenes: [], scenes: [
{
id: "3f21a12a-0bec-4336-99bb-df3f9fc9f537",
name: "Yolo",
actions: [
{
id: 0,
name: "Haha",
},
],
},
],
}, },
]; ];
@ -354,6 +375,8 @@ export function NewEmptyDeviceScene() {
}; };
} }
export const AppSelectedUserDevice = createRef(null);
export const AppContext = createContext(appContextPreview); export const AppContext = createContext(appContextPreview);
export function AppProvider({ children }) { export function AppProvider({ children }) {
@ -429,3 +452,11 @@ export function IsPlatformIos() {
export function VibrateShort() { export function VibrateShort() {
Vibration.vibrate(50); Vibration.vibrate(50);
} }
export function ModalContainer({ children }) {
return (
<View style={AppStyles.modal}>
<View>{children}</View>
</View>
);
}