update scene name

main
alex 2023-08-01 21:20:40 +00:00
parent 3dd7afec41
commit 8bb1da8d00
15 changed files with 273 additions and 119 deletions

18
App.js
View File

@ -32,8 +32,9 @@ import {
SettingsAppColorSchemeModalContent,
SettingsAppLanguageModalContent,
} from "./src/Screens/Settings";
import { SettingsChangeDeviceDisplayName } from "./src/Screens/Device/settings";
import { EditActionAnimationSelectionModalContent } from "./src/Screens/Device/modals/EditActions";
import UpdateSceneNameModalContent from "./src/Screens/Device/modals/UpdateSceneName";
import SettingsChangeDeviceDisplayNameModalContent from "./src/Screens/Device/modals/SettingsChangeDeviceDisplayName";
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
@ -224,6 +225,19 @@ export function MyApp() {
}
/>
<Stack.Screen
name="modalUpdateSceneName"
component={UpdateSceneNameModalContent}
options={({ navigation }) =>
options({
navigation: navigation,
pageTitle: t(
"screens.device.scenes.modalUpdateSceneName.pageTitle"
),
})
}
/>
<Stack.Screen
name="modalSettingsAppColorScheme"
component={SettingsAppColorSchemeModalContent}
@ -248,7 +262,7 @@ export function MyApp() {
<Stack.Screen
name="modalSettingsChangeDeviceDisplayName"
component={SettingsChangeDeviceDisplayName}
component={SettingsChangeDeviceDisplayNameModalContent}
options={({ navigation }) =>
options({
navigation: navigation,

View File

@ -22,7 +22,7 @@
"deviceFirmwareVersionText": "Firmware Version",
"deviceLastUpdatedText": "Letzte Aktualisierung",
"modalSettingsChangeDeviceDisplayName": {
"pageTitle": "Gerätename anpassen",
"pageTitle": "Gerätename ändern",
"textTitle": "Gerätename",
"textDescription": "Der Name wird lokal auf dem Gerät gespeichert und dient dazu, die verbundenen Geräte in der App voneinander zu unterscheiden."
}
@ -93,6 +93,11 @@
"modalEditActionAnimationOutSelection": {
"pageTitle": "Animation out auswählen",
"noResult": "Keine Animationen verfügbar"
},
"modalUpdateSceneName": {
"pageTitle": "Szenennamen ändern",
"textTitle": "Szenenname",
"textDescription": "Benenne die Szene, um sie später leichter wiederzufinden."
}
}
},
@ -106,9 +111,9 @@
"pageTitle": "Einstellungen",
"settingsCardTitle": "Einstellungen",
"languageText": "Sprache",
"languageModalTitle": "Sprache anpassen",
"languageModalTitle": "Sprache ändern",
"appColorSchemeText": "Anzeigemodus",
"appColorSchemeModalTitle": "Anzeigemodus anpassen",
"appColorSchemeModalTitle": "Anzeigemodus ändern",
"appColorSchemePicker": {
"auto": "System Standard",
"dark": "Dunkel",

View File

@ -93,6 +93,11 @@
"modalEditActionAnimationOutSelection": {
"pageTitle": "Choose animation out",
"noResult": "No animations available"
},
"modalUpdateSceneName": {
"pageTitle": "Change scene name",
"textTitle": "Scene name",
"textDescription": "Give the scene a name to easily find it later"
}
}
},

View File

@ -35,6 +35,7 @@ export default function MyDropdown({
{selectedItemLabel}
</Text>
</View>
<MyIcon
name="chevron-down"
size={24}

View File

@ -1,24 +1,18 @@
import { useContext, useEffect, useState } from "react";
import { AppContext, AppStyles, IsPlatformIos } from "../../utils";
import {
KeyboardAvoidingView,
Modal,
ScrollView,
Text,
TextInput,
TouchableOpacity,
View,
} from "react-native";
import { AppContext, AppStyles, ModalContainer } from "../../utils";
import { Text, TouchableOpacity, View } from "react-native";
import { Divider } from "../Divider";
import MyIcon from "../Icon";
import { useTranslation } from "react-i18next";
import MyTextInput from "../TextInput";
import { MyIconButton } from "../Button";
const modalContentStyle = { margin: 10, paddingTop: 10 };
//const modalContentStyle = { margin: 10, paddingTop: 10 };
/*
transparent: set this to prevent modal reopening on iOS
https://github.com/facebook/react-native/issues/34018
*/
/*
export default function MyModal({
children,
isOpen,
@ -107,14 +101,19 @@ export function MyDefaultModalHeader({ title, closeModal }) {
<View style={{ marginRight: 40 }} />
</View>
);
}
} */
export function MyPickerModalListItem({ onPress, itemName, itemSelected }) {
export function MyPickerModalListItem({
onPress,
itemName,
itemSelected,
disabled,
}) {
const appContext = useContext(AppContext);
return (
<>
<TouchableOpacity onPress={onPress}>
<TouchableOpacity onPress={onPress} disabled={disabled}>
<View
style={{
flexDirection: "row",
@ -127,6 +126,7 @@ export function MyPickerModalListItem({ onPress, itemName, itemSelected }) {
style={[
AppStyles.typography16,
{ color: appContext.appTheme.text },
disabled && AppStyles.disabled,
]}
>
{itemName}
@ -147,6 +147,48 @@ export function MyPickerModalListItem({ onPress, itemName, itemSelected }) {
);
}
export function MyTextInputModalContent({
navigation,
defaultValue,
onCheckIconPress,
textInputTitle,
textInputDescription,
textMaxLength,
}) {
const [newValue, setNewValue] = useState(defaultValue);
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<MyIconButton
usePrimaryColor
iconName="check"
iconSize={24}
style={{ marginRight: 20 }}
onPress={() => {
navigation.goBack();
onCheckIconPress(newValue);
}}
disabled={newValue.length === 0}
/>
),
});
}, [navigation, newValue]);
return (
<ModalContainer>
<MyTextInput
textTitle={textInputTitle}
textDescription={textInputDescription}
value={newValue}
onChangeText={(v) => setNewValue(v)}
textMaxLength={textMaxLength}
/>
</ModalContainer>
);
}
/*
export function MyPickerModal({ isOpen, setIsOpen, items, searchFilter }) {
const appContext = useContext(AppContext);
const { t } = useTranslation();
@ -317,8 +359,8 @@ export function MyPickerModal({ isOpen, setIsOpen, items, searchFilter }) {
</KeyboardAvoidingView>
</Modal>
);
}
}*/
/*
export function MyTextInputModal({
isOpen,
setIsOpen,
@ -402,3 +444,4 @@ export function MyTextInputModal({
</Modal>
);
}
*/

View File

@ -23,6 +23,7 @@ export default function MySlider({
minimumTrackTintColor={appContext.appTheme.slider.minimumTrackTintColor}
maximumTrackTintColor={appContext.appTheme.slider.maximumTrackTintColor}
thumbTintColor={appContext.appTheme.slider.thumbTintColor}
step={1}
/>
);
}

View File

@ -5,6 +5,7 @@ import { useContext } from "react";
export default function MyTextInput({
textTitle,
textDescription,
textMaxLength,
value,
onChangeText,
}) {
@ -22,6 +23,7 @@ export default function MyTextInput({
borderBottomWidth: 1,
borderColor: appContext.appTheme.textInputBottomColor,
}}
maxLength={textMaxLength}
value={value}
onChangeText={onChangeText}
/>

View File

@ -1,13 +1,5 @@
import { useContext, useState } from "react";
import {
Image,
ScrollView,
StyleSheet,
View,
Text,
KeyboardAvoidingView,
Alert,
} from "react-native";
import { Image, ScrollView, StyleSheet, View, Text, Alert } from "react-native";
import { AppContext } from "../../utils";
import SettingsView from "./settings";
import SceneView from "./scene";

View File

@ -3,8 +3,7 @@ import {
AppContext,
AppSelectedUserDevice,
ModalContainer,
NewEmptyDeviceScene,
NewInitialDeviceScene,
NewDeviceScene,
} from "../../../../../utils";
import { FlatList } from "react-native";
import { MyPickerModalListItem } from "../../../../../Components/Modal";
@ -39,13 +38,33 @@ export default function CreateSceneModalContent({ navigation }) {
renderItem={({ item }) => (
<MyPickerModalListItem
itemName={item.name}
disabled={item.id === 2}
onPress={() => {
appContext.setDeviceScenes((arr) => [
...arr,
NewEmptyDeviceScene("Leere Szene"),
]);
if (item.id === 0 || item.id === 1) {
const newDeviceScene = NewDeviceScene(
item.id === 0 ? "Leere Szene" : "Standard Szene"
);
appContext.setDeviceScenes((arr) => [...arr, newDeviceScene]);
navigation.pop(2);
appContext.setDevices((arr) => {
let newArr = [...arr];
const deviceIndex = newArr.findIndex(
(device) => device.id === AppSelectedUserDevice.current.id
);
if (deviceIndex !== -1) {
newArr[deviceIndex].selectedScene = newDeviceScene.sceneId;
}
return newArr;
});
} else {
console.log("copy a scene");
}
}}
/>
)}

View File

@ -7,7 +7,7 @@ import {
ModalContainer,
} from "../../../../utils";
import MyDropdown from "../../../../Components/Dropdown";
import { useContext } from "react";
import { useContext, useState } from "react";
import MyResult from "../../../../Components/Result";
import { MyPickerModalListItem } from "../../../../Components/Modal";
import MyIcon from "../../../../Components/Icon";
@ -40,7 +40,12 @@ export default function EditActionAnimationsCardContent({
return (
<>
<Card>
<Text style={[AppStyles.typography14, { fontWeight: "bold", color: appContext.appTheme.text }]}>
<Text
style={[
AppStyles.typography14,
{ fontWeight: "bold", color: appContext.appTheme.text },
]}
>
{t(
"screens.device.scenes.editActionAnimationsCardContent.animationsIn"
)}
@ -75,7 +80,14 @@ export default function EditActionAnimationsCardContent({
))}
<Text
style={[AppStyles.typography14, { fontWeight: "bold", marginTop: 6, color: appContext.appTheme.text }]}
style={[
AppStyles.typography14,
{
fontWeight: "bold",
marginTop: 6,
color: appContext.appTheme.text,
},
]}
>
{t(
"screens.device.scenes.editActionAnimationsCardContent.animationsOut"
@ -195,6 +207,8 @@ export function EditActionAdjustmentContent({
appThemeText,
appLanguage,
}) {
const [sliderValue, setSliderValue] = useState(0);
if (adjustment.type === "slider") {
return (
<>
@ -209,10 +223,19 @@ export function EditActionAdjustmentContent({
style={[{ flex: 1 }, IsPlatformIos() && { marginLeft: 6 }]}
minimumValue={adjustment.min}
maximumValue={adjustment.max}
onValueChange={(v) =>
console.log(`change ${adjustment.variableName}`, v)
}
onValueChange={(v) => {
console.log(`change ${adjustment.variableName}`, v);
setSliderValue(v);
}}
value={sliderValue}
/>
<View style={{ width: 32, alignItems: "center" }}>
<Text style={{ color: appThemeText }}>
{sliderValue}
{adjustment.unitOfMeasurement}
</Text>
</View>
</View>
</>
);

View File

@ -0,0 +1,39 @@
import { useContext } from "react";
import { AppContext, Constants } from "../../../../utils";
import { useTranslation } from "react-i18next";
import { MyTextInputModalContent } from "../../../../Components/Modal";
export default function SettingsChangeDeviceDisplayNameModalContent({
navigation,
route,
}) {
const appContext = useContext(AppContext);
const { t } = useTranslation();
return (
<MyTextInputModalContent
navigation={navigation}
textMaxLength={Constants.globals.max_device_name_length}
defaultValue={route.params.displayName}
onCheckIconPress={(newDeviceDisplayName) => {
appContext.setDevices((arr) => {
let newArr = [...arr];
const foundIndex = newArr.findIndex((d) => d.id === route.params.id);
if (foundIndex !== -1) {
newArr[foundIndex].displayName = newDeviceDisplayName;
}
return newArr;
});
}}
textInputTitle={t(
"screens.device.settings.modalSettingsChangeDeviceDisplayName.textTitle"
)}
textInputDescription={t(
"screens.device.settings.modalSettingsChangeDeviceDisplayName.textDescription"
)}
/>
);
}

View File

@ -0,0 +1,38 @@
import { useContext } from "react";
import { AppContext, Constants } from "../../../../utils";
import { MyTextInputModalContent } from "../../../../Components/Modal";
import { useTranslation } from "react-i18next";
export default function UpdateSceneNameModalContent({ navigation, route }) {
const appContext = useContext(AppContext);
const { t } = useTranslation();
const { deviceSelectedScene, sceneName } = route.params;
return (
<MyTextInputModalContent
navigation={navigation}
textMaxLength={Constants.globals.max_scene_name_length}
defaultValue={sceneName}
textInputTitle={t("screens.device.scenes.modalUpdateSceneName.textTitle")}
textInputDescription={t(
"screens.device.scenes.modalUpdateSceneName.textDescription"
)}
onCheckIconPress={(newValue) => {
appContext.setDeviceScenes((arr) => {
let newArr = [...arr];
const foundSceneIndex = newArr.findIndex(
(scene) => scene.sceneId === deviceSelectedScene
);
if (foundSceneIndex !== -1) {
newArr[foundSceneIndex].name = newValue;
}
return newArr;
});
}}
/>
);
}

View File

@ -6,7 +6,7 @@ import MyDropdown from "../../Components/Dropdown";
import MyIcon from "../../Components/Icon";
import { useTranslation } from "react-i18next";
import MyResult from "../../Components/Result";
import { MyTextButton } from "../../Components/Button";
import { MyIconButton, MyTextButton } from "../../Components/Button";
import { useFocusEffect } from "@react-navigation/native";
export default function SceneView({ navigation }) {
@ -15,15 +15,40 @@ export default function SceneView({ navigation }) {
const [device, setDevice] = useState();
const getSelectedDeviceSceneName = () => {
const scenes = appContext.deviceScenes.find(
(s) => s.sceneId === device.selectedScene
);
return scenes === undefined ? "None" : scenes.name;
};
useFocusEffect(
useCallback(() => {
setDevice(GetDevice(appContext.devices));
console.log("callback");
if (device !== undefined) {
if (device.selectedScene !== null) {
navigation.setOptions({
headerRight: () => (
<MyIconButton
iconName="pencil"
iconSize={22}
style={{ marginRight: 20 }}
onPress={() =>
navigation.navigate("modalUpdateSceneName", {
deviceSelectedScene: device.selectedScene,
sceneName: getSelectedDeviceSceneName(),
})
}
/>
),
});
}
}
}, [device])
);
console.log("device", device !== undefined);
if (device === undefined) return <></>;
const getActionTypeIcon = (actionType) => {
@ -51,14 +76,6 @@ export default function SceneView({ navigation }) {
(a) => a.sceneId === device.selectedScene
);
const getSelectedDeviceScene = () => {
const scenes = appContext.deviceScenes.find(
(s) => s.sceneId === device.selectedScene
);
return scenes === undefined ? "None" : scenes.name;
};
return (
<>
<Card>
@ -74,7 +91,7 @@ export default function SceneView({ navigation }) {
? t(
"screens.device.scenes.dropdownSceneSelection.noSceneSelected"
)
: getSelectedDeviceScene()
: getSelectedDeviceSceneName()
}
/>
</Card>

View File

@ -1,16 +1,10 @@
import { Text, View } from "react-native";
import Card from "../../Components/Card";
import { useContext, useEffect, useState } from "react";
import {
AppContext,
AppSelectedUserDevice,
AppStyles,
ModalContainer,
} from "../../utils";
import { AppContext, AppSelectedUserDevice, AppStyles } from "../../utils";
import { Divider } from "../../Components/Divider";
import { useTranslation } from "react-i18next";
import MySwitch from "../../Components/Switch";
import MyTextInput from "../../Components/TextInput";
import { MyIconButton } from "../../Components/Button";
export default function SettingsView({ navigation }) {
@ -22,6 +16,12 @@ export default function SettingsView({ navigation }) {
(d) => d.id === AppSelectedUserDevice.current.id
);
useEffect(() => {
navigation.setOptions({
headerRight: null,
});
}, []);
return (
<>
<Card>
@ -176,57 +176,3 @@ export default function SettingsView({ navigation }) {
</>
);
}
export function SettingsChangeDeviceDisplayName({ navigation, route }) {
const appContext = useContext(AppContext);
const { t } = useTranslation();
const [newDeviceDisplayName, setNewDeviceDisplayName] = useState(
route.params.displayName
);
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<MyIconButton
usePrimaryColor
iconName="check"
iconSize={24}
style={{ marginRight: 20 }}
onPress={() => {
navigation.goBack();
appContext.setDevices((arr) => {
let newArr = [...arr];
const foundIndex = newArr.findIndex(
(d) => d.id === route.params.id
);
if (foundIndex !== -1) {
newArr[foundIndex].displayName = newDeviceDisplayName;
}
return newArr;
});
}}
disabled={newDeviceDisplayName.length === 0}
/>
),
});
}, [navigation, newDeviceDisplayName]);
return (
<ModalContainer>
<MyTextInput
textTitle={t(
"screens.device.settings.modalSettingsChangeDeviceDisplayName.textTitle"
)}
textDescription={t(
"screens.device.settings.modalSettingsChangeDeviceDisplayName.textDescription"
)}
value={newDeviceDisplayName}
onChangeText={(v) => setNewDeviceDisplayName(v)}
/>
</ModalContainer>
);
}

View File

@ -27,6 +27,10 @@ export const Constants = {
ambilight: 1,
motor: 2,
},
globals: {
max_device_name_length: 20,
max_scene_name_length: 20,
},
};
export const AppStyles = StyleSheet.create({
@ -220,6 +224,7 @@ const devDevicesFirmwareModes = {
},
min: 0,
max: 6,
unitOfMeasurement: "s",
},
],
},
@ -242,6 +247,7 @@ const devDevicesFirmwareModes = {
},
min: 0,
max: 100,
unitOfMeasurement: "s",
},
{
type: "slider",
@ -253,6 +259,7 @@ const devDevicesFirmwareModes = {
},
min: 1,
max: 10,
unitOfMeasurement: "s",
},
],
},
@ -285,6 +292,7 @@ const devDevicesFirmwareModes = {
iconName: "repeat-variant",
min: 1,
max: 60,
unitOfMeasurement: "s",
},
],
},
@ -317,6 +325,7 @@ const devDevicesFirmwareModes = {
iconName: "repeat-variant",
min: 1,
max: 60,
unitOfMeasurement: "s",
},
],
},
@ -370,7 +379,7 @@ const devDeviceScenes = [
},
];
export function NewEmptyDeviceScene(name) {
export function NewDeviceScene(name) {
return {
sceneId: GetUuid(),
deviceId: AppSelectedUserDevice.current.id,