no devices found and buttons for factory reset and disconnect from device

main
alex 2023-08-13 10:45:23 +00:00
parent 22d4a8bae7
commit aa46586b98
14 changed files with 486 additions and 83 deletions

22
App.js
View File

@ -40,7 +40,6 @@ import MotorEditActionModalContent, {
} from "./src/Screens/Device/modals/EditActions/Motor"; } from "./src/Screens/Device/modals/EditActions/Motor";
import WaitXSecondsEditActionModalContent from "./src/Screens/Device/modals/EditActions/Wait"; import WaitXSecondsEditActionModalContent from "./src/Screens/Device/modals/EditActions/Wait";
import StopEditActionModalContent from "./src/Screens/Device/modals/EditActions/Stop"; import StopEditActionModalContent from "./src/Screens/Device/modals/EditActions/Stop";
import AsyncStorage from "@react-native-async-storage/async-storage";
import SearchForNewDevicesModalContent from "./src/Screens/SearchForNewDevices"; import SearchForNewDevicesModalContent from "./src/Screens/SearchForNewDevices";
const Drawer = createDrawerNavigator(); const Drawer = createDrawerNavigator();
@ -48,6 +47,9 @@ const Stack = createStackNavigator();
const SettingsScreen = lazy(() => import("./src/Screens/Settings")); const SettingsScreen = lazy(() => import("./src/Screens/Settings"));
const HelpScreen = lazy(() => import("./src/Screens/Help")); const HelpScreen = lazy(() => import("./src/Screens/Help"));
const NoDevicesConnectedScreen = lazy(() =>
import("./src/Screens/NoDevicesConnected")
);
export function MyApp() { export function MyApp() {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
@ -363,6 +365,11 @@ function MyDrawer() {
<Drawer.Screen name="Help" component={HelpScreenStack} /> <Drawer.Screen name="Help" component={HelpScreenStack} />
<Drawer.Screen name="Settings" component={SettingsScreenStack} /> <Drawer.Screen name="Settings" component={SettingsScreenStack} />
<Drawer.Screen
name="_noDevicesConnected"
component={NoDevicesConnectedStack}
/>
</Drawer.Navigator> </Drawer.Navigator>
); );
} }
@ -379,6 +386,19 @@ const DeviceScreenStack = (props) => {
); );
}; };
const NoDevicesConnectedStack = (props) => {
const { t } = useTranslation();
return (
<MyScreenStack
name="noDevicesConnected"
pageTitle={t("screens.noDevicesConnected.pageTitle")}
component={NoDevicesConnectedScreen}
navigation={props.navigation}
/>
);
};
const HelpScreenStack = (props) => { const HelpScreenStack = (props) => {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -7,7 +7,9 @@
"sideBar": { "sideBar": {
"devicesTitle": "Geräte", "devicesTitle": "Geräte",
"settings": "Einstellungen", "settings": "Einstellungen",
"help": "Hilfe" "help": "Hilfe",
"noDevicesConnected": "Keine Geräte verbunden",
"textButtonSearchForNewDevices": "Suche nach neuen Geräten"
}, },
"screens": { "screens": {
"device": { "device": {
@ -20,11 +22,30 @@
"deviceModelText": "Gerätemodell", "deviceModelText": "Gerätemodell",
"deviceFirmwareVersionText": "Firmware Version", "deviceFirmwareVersionText": "Firmware Version",
"deviceLastUpdatedText": "Letzte Aktualisierung", "deviceLastUpdatedText": "Letzte Aktualisierung",
"deviceMacAddressText": "MAC-Adresse",
"deviceIPAddressText": "IP-Adresse", "deviceIPAddressText": "IP-Adresse",
"modalSettingsChangeDeviceDisplayName": { "modalSettingsChangeDeviceDisplayName": {
"pageTitle": "Gerätename ändern", "pageTitle": "Gerätename ändern",
"textTitle": "Gerätename", "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." "textDescription": "Der Name wird lokal auf dem Gerät gespeichert und dient dazu, die verbundenen Geräte in der App voneinander zu unterscheiden."
},
"closeConnectionTitle": "Verbindung zum Gerät trennen",
"closeConnectionDescription": "Die Verbindung zum Gerät wird getrennt. Um das Gerät wieder zu verwenden, müssen Sie es erneut mit der App verbinden.",
"closeConnectionButton": "Verbindung trennen",
"resetToFactorySettingsTitle": "Auf Werkseinstellungen zurücksetzen",
"resetToFactorySettingsDescription": "Alle Einstellungen werden auf die Werkseinstellungen zurückgesetzt. Dies kann nicht rückgängig gemacht werden.",
"resetToFactorySettingsButton": "Zurücksetzen",
"bottomSheetModalCloseConnection": {
"headerTitle": "Verbindung trennen",
"description": "Die Verbindung zum Gerät wird getrennt. Um das Gerät wieder zu verwenden, müssen Sie es erneut mit der App verbinden.",
"cancelButton": "Abbrechen",
"confirmButton": "Verbindung trennen"
},
"bottomSheetModalResetToFactorySettings": {
"headerTitle": "Auf Werkseinstellungen zurücksetzen",
"description": "Alle Einstellungen werden auf die Werkseinstellungen zurückgesetzt. Dies kann nicht rückgängig gemacht werden.",
"cancelButton": "Abbrechen",
"confirmButton": "Zurücksetzen"
} }
}, },
"scenes": { "scenes": {
@ -159,6 +180,11 @@
} }
} }
}, },
"noDevicesConnected": {
"pageTitle": "Keine Geräte verbunden",
"textDescription": "Es sind keine Geräte mit der App verbunden. Verbinden Sie ein Gerät, um es zu verwenden.",
"buttonSearchForNewDevices": "Nach neuen Geräten suchen"
},
"help": { "help": {
"pageTitle": "Hilfe" "pageTitle": "Hilfe"
}, },

View File

@ -7,7 +7,9 @@
"sideBar": { "sideBar": {
"devicesTitle": "Devices", "devicesTitle": "Devices",
"settings": "Settings", "settings": "Settings",
"help": "Help" "help": "Help",
"noDevicesConnected": "No devices connected",
"textButtonSearchForNewDevices": "Search for new devices"
}, },
"screens": { "screens": {
"device": { "device": {
@ -20,11 +22,30 @@
"deviceModelText": "Device model", "deviceModelText": "Device model",
"deviceFirmwareVersionText": "Firmware Version", "deviceFirmwareVersionText": "Firmware Version",
"deviceLastUpdatedText": "Last updated", "deviceLastUpdatedText": "Last updated",
"deviceMacAddressText": "MAC address",
"deviceIPAddressText": "IP address", "deviceIPAddressText": "IP address",
"modalSettingsChangeDeviceDisplayName": { "modalSettingsChangeDeviceDisplayName": {
"pageTitle": "Customize device name", "pageTitle": "Customize device name",
"textTitle": "Device name", "textTitle": "Device name",
"textDescription": "The name of the device is stored locally on the device and serves you to distinguish the connected devices from each other in the app." "textDescription": "The name of the device is stored locally on the device and serves you to distinguish the connected devices from each other in the app."
},
"closeConnectionTitle": "Disconnect from device",
"closeConnectionDescription": "The connection to the device will be disconnected. To use the device again, you'll need to reconnect it with the app.",
"closeConnectionButton": "Disconnect",
"resetToFactorySettingsTitle": "Reset to Factory Settings",
"resetToFactorySettingsDescription": "All settings will be reset to their factory defaults. This action cannot be undone.",
"resetToFactorySettingsButton": "Reset",
"bottomSheetModalCloseConnection": {
"headerTitle": "Disconnect Connection",
"description": "The connection to the device is being disconnected. To use the device again, you will need to reconnect it with the app.",
"cancelButton": "Cancel",
"confirmButton": "Disconnect"
},
"bottomSheetModalResetToFactorySettings": {
"headerTitle": "Reset to Factory Settings",
"description": "All settings will be reset to their factory defaults. This cannot be undone.",
"cancelButton": "Cancel",
"confirmButton": "Reset"
} }
}, },
"scenes": { "scenes": {
@ -159,6 +180,9 @@
} }
} }
}, },
"noDevicesConnected": {
"pageTitle": "No devices connected"
},
"help": { "help": {
"pageTitle": "Help" "pageTitle": "Help"
}, },

10
package-lock.json generated
View File

@ -23,6 +23,7 @@
"react-native": "0.71.8", "react-native": "0.71.8",
"react-native-draggable-flatlist": "^4.0.1", "react-native-draggable-flatlist": "^4.0.1",
"react-native-gesture-handler": "~2.9.0", "react-native-gesture-handler": "~2.9.0",
"react-native-linear-gradient": "^2.8.2",
"react-native-pager-view": "6.1.2", "react-native-pager-view": "6.1.2",
"react-native-reanimated": "~2.14.4", "react-native-reanimated": "~2.14.4",
"react-native-safe-area-context": "4.5.0", "react-native-safe-area-context": "4.5.0",
@ -11939,6 +11940,15 @@
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.19.tgz", "resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.19.tgz",
"integrity": "sha512-1dVk9NwhoyKHCSxcrM6vY6cxmojeATsBobDicX0ZKr7DgUF2cBQRTKsimQFvzH8XhOVXyH8p4HyDSZNIFI8OlQ==" "integrity": "sha512-1dVk9NwhoyKHCSxcrM6vY6cxmojeATsBobDicX0ZKr7DgUF2cBQRTKsimQFvzH8XhOVXyH8p4HyDSZNIFI8OlQ=="
}, },
"node_modules/react-native-linear-gradient": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.2.tgz",
"integrity": "sha512-hgmCsgzd58WNcDCyPtKrvxsaoETjb/jLGxis/dmU3Aqm2u4ICIduj4ECjbil7B7pm9OnuTkmpwXu08XV2mpg8g==",
"peerDependencies": {
"react": "*",
"react-native": "*"
}
},
"node_modules/react-native-pager-view": { "node_modules/react-native-pager-view": {
"version": "6.1.2", "version": "6.1.2",
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.1.2.tgz", "resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.1.2.tgz",

View File

@ -24,6 +24,7 @@
"react-native": "0.71.8", "react-native": "0.71.8",
"react-native-draggable-flatlist": "^4.0.1", "react-native-draggable-flatlist": "^4.0.1",
"react-native-gesture-handler": "~2.9.0", "react-native-gesture-handler": "~2.9.0",
"react-native-linear-gradient": "^2.8.2",
"react-native-pager-view": "6.1.2", "react-native-pager-view": "6.1.2",
"react-native-reanimated": "~2.14.4", "react-native-reanimated": "~2.14.4",
"react-native-safe-area-context": "4.5.0", "react-native-safe-area-context": "4.5.0",

View File

@ -15,9 +15,15 @@ export default function MyButton({
disabled, disabled,
onPress, onPress,
buttonLeftComponent, buttonLeftComponent,
buttonBackgroundColor,
}) { }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const bBackgroundColor =
buttonBackgroundColor === undefined
? appContext.appTheme.colors.primary
: buttonBackgroundColor;
return ( return (
<TouchableHighlight <TouchableHighlight
disabled={disabled} disabled={disabled}
@ -27,7 +33,7 @@ export default function MyButton({
<View <View
style={[ style={[
{ {
backgroundColor: appContext.appTheme.colors.primary, backgroundColor: bBackgroundColor,
borderRadius: 6, borderRadius: 6,
padding: 10, padding: 10,
}, },
@ -37,7 +43,12 @@ export default function MyButton({
]} ]}
> >
{buttonLeftComponent} {buttonLeftComponent}
<Text style={{ textAlign: "center", color: appContext.appTheme.text }}> <Text
style={{
textAlign: "center",
color: appContext.appTheme.buttonTextColor,
}}
>
{title} {title}
</Text> </Text>
</View> </View>

View File

@ -1,4 +1,4 @@
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useRef, useState } from "react";
import { AppContext, AppStyles, ModalContainer } from "../../utils"; import { AppContext, AppStyles, ModalContainer } from "../../utils";
import { import {
Modal, Modal,
@ -7,13 +7,21 @@ import {
Text, Text,
TouchableWithoutFeedback, TouchableWithoutFeedback,
View, View,
FlatList,
} from "react-native"; } from "react-native";
import MyIcon from "../Icon"; import MyIcon from "../Icon";
import MyTextInput from "../TextInput"; import MyTextInput from "../TextInput";
import { MyIconButton } from "../Button"; import { MyIconButton } from "../Button";
import { Divider } from "../Divider"; import { Divider } from "../Divider";
import MyPressable from "../Pressable"; import MyPressable from "../Pressable";
import { FlatList } from "react-native-gesture-handler"; import Animated, {
Easing,
useAnimatedStyle,
useSharedValue,
withSpring,
withTiming,
} from "react-native-reanimated";
import { StatusBar } from "expo-status-bar";
//const modalContentStyle = { margin: 10, paddingTop: 10 }; //const modalContentStyle = { margin: 10, paddingTop: 10 };
@ -333,34 +341,74 @@ export function MyBottomSheetModal({
}) { }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const translateY = useSharedValue(0);
const opacity = useSharedValue(0);
translateY.value = withTiming(isOpen ? 0 : modalHeight, {
duration: 250,
easing: Easing.ease,
});
opacity.value = withTiming(isOpen ? 1 : 0, {
duration: 250,
easing: Easing.ease,
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateY: translateY.value }],
opacity: opacity.value,
}));
const handleCloseModal = () => {
translateY.value = withTiming(modalHeight, {
duration: 100,
easing: Easing.ease,
});
opacity.value = withTiming(0, { duration: 100, easing: Easing.ease });
setTimeout(() => closeModal(), 100);
};
return ( return (
<Modal <Modal
statusBarTranslucent
visible={isOpen} visible={isOpen}
transparent transparent
animationType="slide"
style={{ flex: 1 }} style={{ flex: 1 }}
onRequestClose={() => closeModal()} onRequestClose={() => handleCloseModal()}
> >
<TouchableWithoutFeedback onPress={() => closeModal()}> <TouchableWithoutFeedback onPress={() => handleCloseModal()}>
<View style={{ flex: 1 }} />
</TouchableWithoutFeedback>
<View>
<View <View
style={{ style={{
backgroundColor: appContext.appTheme.card.backgroundColor, flex: 1,
height: modalHeight, backgroundColor:
borderTopLeftRadius: 20, appContext.appTheme.modal.transparentBackgroundColor,
borderTopRightRadius: 20,
paddingTop: 12,
shadowRadius: 8,
shadowOffset: {
width: 0,
height: -10,
},
shadowColor: "#000000",
elevation: 6,
}} }}
/>
</TouchableWithoutFeedback>
<View
style={{
backgroundColor: appContext.appTheme.modal.transparentBackgroundColor,
}}
>
<Animated.View
style={[
{
backgroundColor: appContext.appTheme.card.backgroundColor,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
height: modalHeight,
paddingTop: 12,
shadowRadius: 8,
shadowOffset: {
width: 0,
height: -10,
},
shadowColor: "#000000",
elevation: 6,
},
animatedStyle,
]}
> >
<View <View
style={{ style={{
@ -384,12 +432,12 @@ export function MyBottomSheetModal({
iconSize={24} iconSize={24}
iconColor={appContext.appTheme.icon} iconColor={appContext.appTheme.icon}
iconName="close" iconName="close"
onPress={() => closeModal()} onPress={() => handleCloseModal()}
/> />
</View> </View>
{children} {children}
</View> </Animated.View>
</View> </View>
</Modal> </Modal>
); );

View File

@ -17,7 +17,11 @@ export default function MyResult({ text, iconName }) {
<Text <Text
style={[ style={[
AppStyles.typography16, AppStyles.typography16,
{ color: appContext.appTheme.text, marginTop: 10 }, {
color: appContext.appTheme.text,
marginTop: 10,
textAlign: "center",
},
]} ]}
> >
{text} {text}

View File

@ -5,7 +5,8 @@ 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";
import { MyIconButton } from "../Button"; import { MyIconButton, MyTextButton } from "../Button";
import MyResult from "../Result";
export default function Sidebar(props) { export default function Sidebar(props) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
@ -104,6 +105,9 @@ export default function Sidebar(props) {
); );
}; };
const openModalSearchForNewDevices = () =>
props.navigation.navigate("modalSearchForNewDevices");
return ( return (
<> <>
{appContext.isUserDeveloperModeEnabled ? ( {appContext.isUserDeveloperModeEnabled ? (
@ -147,23 +151,38 @@ export default function Sidebar(props) {
iconName="plus" iconName="plus"
iconSize={24} iconSize={24}
style={{ padding: 2 }} style={{ padding: 2 }}
onPress={() => props.navigation.navigate("modalSearchForNewDevices")} onPress={() => openModalSearchForNewDevices()}
/> />
</View> </View>
<DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}> <DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}>
{appContext.devices.map((device, i) => ( {appContext.devices.length > 0 ? (
<MyDrawerItem appContext.devices.map((device) => (
key={device.id} <MyDrawerItem
_deviceId={device.id} key={device.id}
isDevice _deviceId={device.id}
deviceName={device.displayName} isDevice
deviceModel={device.deviceModel} deviceName={device.displayName}
onPress={() => props.navigation.navigate(device.displayName)} deviceModel={device.deviceModel}
iconName={"glass-stange"} onPress={() => props.navigation.navigate(device.displayName)}
routeName={device.displayName} iconName={"glass-stange"}
/> routeName={device.displayName}
))} />
))
) : (
<View style={{ alignItems: "center", marginTop: 20, gap: 10 }}>
<MyResult
text={t("sideBar.noDevicesConnected")}
iconName={"selection-search"}
/>
<MyTextButton
title={t("sideBar.textButtonSearchForNewDevices")}
actionColor
onPress={() => openModalSearchForNewDevices()}
/>
</View>
)}
</DrawerContentScrollView> </DrawerContentScrollView>
<View style={{ justifyContent: "flex-end" }}> <View style={{ justifyContent: "flex-end" }}>

View File

@ -64,6 +64,8 @@ const windowHeight = Dimensions.get("window").height;
const modalHeight = windowHeight * 0.6; // 60 % of device screen const modalHeight = windowHeight * 0.6; // 60 % of device screen
console.log("modalHe", modalHeight);
export default function WaitEditActionModalContent({ navigation, route }) { export default function WaitEditActionModalContent({ navigation, route }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -132,21 +132,6 @@ export default function SceneView({ navigation }) {
const lastSceneAction = deviceSceneActions[deviceSceneActions.length - 1]; const lastSceneAction = deviceSceneActions[deviceSceneActions.length - 1];
console.log(
"lastSceneAction",
lastSceneAction?.type === Constants.actionType.stop
);
/*
) : (
<ActionListItem
navigation={navigation}
device={device}
item={deviceSceneActions[deviceSceneActions.length - 1]}
/>
)}
*/
return ( return (
<> <>
{device.selectedScene === "" ? ( {device.selectedScene === "" ? (

View File

@ -1,41 +1,58 @@
import { ScrollView, Text, View } from "react-native"; import { Button, ScrollView, Text, View } from "react-native";
import Card from "../../Components/Card"; import Card from "../../Components/Card";
import { useContext, useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { AppContext, AppSelectedUserDevice, AppStyles } from "../../utils"; import {
AppContext,
AppSelectedUserDevice,
AppStyles,
GetDevice,
} 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 { MyIconButton } from "../../Components/Button"; import MyButton, { MyIconButton, MyTextButton } from "../../Components/Button";
import { MyBottomSheetModal, MyConfirmModal } from "../../Components/Modal";
export default function SettingsView({ navigation }) { export default function SettingsView({ navigation }) {
const appContext = useContext(AppContext); const appContext = useContext(AppContext);
const { t } = useTranslation(); const { t } = useTranslation();
const [switchState, setSwitchState] = useState(false); const [switchState, setSwitchState] = useState(false);
const [textDeviceIdHidden, setTextDeviceIdHidden] = useState(true); const [textDeviceIdHidden, setTextDeviceIdHidden] = useState(true);
const [textDeviceMacAddressHidden, setTextDeviceMacAddressHidden] =
useState(true);
const [
isBottomSheetModalCloseConnectionOpen,
setIsBottomSheetModalCloseConnectionOpen,
] = useState(false);
const [
isBottomSheetModalResetToFactorySettingsOpen,
setIsBottomSheetModalResetToFactorySettingsOpen,
] = useState(false);
const device = appContext.devices.find( const device = GetDevice(appContext.devices);
(d) => d.id === AppSelectedUserDevice.current.id
);
const SettingsText = ({ containerStyle, title, description, hidden }) => { const SettingsText = ({ containerStyle, title, description, hidden }) => {
return ( return (
<View style={containerStyle}> <View style={[containerStyle]}>
<Text <View>
style={ <Text
([AppStyles.typography16], { color: appContext.appTheme.text }) style={
} ([AppStyles.typography16], { color: appContext.appTheme.text })
> }
{title} >
</Text> {title}
<Text </Text>
selectable
style={ <Text
([AppStyles.typography14], selectable
{ color: appContext.appTheme.textSecondary }) style={
} ([AppStyles.typography14],
> { color: appContext.appTheme.textSecondary })
{hidden ? "************" : description} }
</Text> >
{hidden ? "************" : description}
</Text>
</View>
</View> </View>
); );
}; };
@ -46,9 +63,39 @@ export default function SettingsView({ navigation }) {
}); });
}, []); }, []);
const deleteDeviceFromApp = () => {
console.log("dev", appContext.devices.length);
appContext.setDevices((devices) =>
devices.filter((d) => d.id !== device.id)
);
appContext.setDeviceScenes((scenes) =>
scenes.filter((s) => s.deviceId !== device.id)
);
appContext.setDeviceSceneActions((actions) =>
actions.filter((a) => a.deviceId !== device.id)
);
console.log("dev", appContext.devices.length);
// show no devices connected screen if there are no devices left
if (appContext.devices.length < 2) {
navigation.navigate("_noDevicesConnected");
}
// TODO: remove device from app async storage if it is not already handled by appContext
};
const bottomSheetModalHeight = appContext.appLanguage === "en" ? 150 : 170;
return ( return (
<ScrollView> <ScrollView>
<Card cardTopicText={t("screens.device.settings.settingsTitle")}> <Card
cardTopicText={t("screens.device.settings.settingsTitle")}
disablePaddingBottom
>
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -69,7 +116,10 @@ export default function SettingsView({ navigation }) {
</View> </View>
</Card> </Card>
<Card cardTopicText={t("screens.device.settings.deviceInformationText")}> <Card
cardTopicText={t("screens.device.settings.deviceInformationText")}
disablePaddingBottom
>
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -118,6 +168,31 @@ export default function SettingsView({ navigation }) {
<Divider /> <Divider />
<View
style={{
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
}}
>
<SettingsText
title={t("screens.device.settings.deviceMacAddressText")}
description={device.deviceMacAddress}
hidden={textDeviceMacAddressHidden}
/>
<MyIconButton
onPress={() =>
setTextDeviceMacAddressHidden(!textDeviceMacAddressHidden)
}
iconName={textDeviceMacAddressHidden ? "eye-off" : "eye"}
iconSize={18}
style={{ padding: 4 }}
/>
</View>
<Divider />
<View <View
style={{ style={{
flexDirection: "row", flexDirection: "row",
@ -139,6 +214,150 @@ export default function SettingsView({ navigation }) {
/> />
</View> </View>
</Card> </Card>
<Card cardTopicText={"Geräteverwaltung"}>
<SettingsText
title={t("screens.device.settings.closeConnectionTitle")}
description={t("screens.device.settings.closeConnectionDescription")}
/>
<View style={{ alignItems: "center", marginTop: 6 }}>
<MyButton
title={t("screens.device.settings.closeConnectionButton")}
style={{
width: "80%",
}}
onPress={() => setIsBottomSheetModalCloseConnectionOpen(true)}
/>
</View>
<MyBottomSheetModal
isOpen={isBottomSheetModalCloseConnectionOpen}
closeModal={() => setIsBottomSheetModalCloseConnectionOpen(false)}
headerTitle={t(
"screens.device.settings.bottomSheetModalCloseConnection.headerTitle"
)}
modalHeight={bottomSheetModalHeight}
>
<View style={{ margin: 10 }}>
<Text
style={[
{ color: appContext.appTheme.text },
AppStyles.typography14,
]}
>
{t(
"screens.device.settings.bottomSheetModalCloseConnection.description"
)}
</Text>
<View
style={{
flexDirection: "row",
gap: 10,
justifyContent: "center",
marginTop: 10,
}}
>
<MyButton
title={t(
"screens.device.settings.bottomSheetModalCloseConnection.cancelButton"
)}
style={{ width: 100 }}
buttonBackgroundColor={appContext.appTheme.buttonSecondary}
onPress={() => setIsBottomSheetModalCloseConnectionOpen(false)}
/>
<MyButton
title={t(
"screens.device.settings.bottomSheetModalCloseConnection.confirmButton"
)}
style={{ width: 160 }}
onPress={() => {
// TODO: is a request needed to the esp? or is it enough to just remove the device from the app?
console.log("close connection to device", device.id);
deleteDeviceFromApp();
}}
/>
</View>
</View>
</MyBottomSheetModal>
<Divider />
<SettingsText
title={t("screens.device.settings.resetToFactorySettingsTitle")}
description={t(
"screens.device.settings.resetToFactorySettingsDescription"
)}
/>
<View style={{ alignItems: "center", marginTop: 6 }}>
<MyButton
title={t("screens.device.settings.resetToFactorySettingsButton")}
style={{ width: "80%" }}
onPress={() =>
setIsBottomSheetModalResetToFactorySettingsOpen(true)
}
/>
</View>
<MyBottomSheetModal
isOpen={isBottomSheetModalResetToFactorySettingsOpen}
closeModal={() =>
setIsBottomSheetModalResetToFactorySettingsOpen(false)
}
headerTitle={t(
"screens.device.settings.bottomSheetModalResetToFactorySettings.headerTitle"
)}
modalHeight={bottomSheetModalHeight}
>
<View style={{ margin: 10 }}>
<Text
style={[
{ color: appContext.appTheme.text },
AppStyles.typography14,
]}
>
{t(
"screens.device.settings.bottomSheetModalResetToFactorySettings.description"
)}
</Text>
<View
style={{
flexDirection: "row",
gap: 10,
justifyContent: "center",
marginTop: 10,
}}
>
<MyButton
title={t(
"screens.device.settings.bottomSheetModalResetToFactorySettings.cancelButton"
)}
style={{ width: 100 }}
buttonBackgroundColor={appContext.appTheme.buttonSecondary}
onPress={() =>
setIsBottomSheetModalResetToFactorySettingsOpen(false)
}
/>
<MyButton
title={t(
"screens.device.settings.bottomSheetModalResetToFactorySettings.confirmButton"
)}
style={{ width: 160 }}
onPress={() => {
// TODO: API request to esp for reset to factory settings
console.log("reseting esp and closing connection", device.id);
deleteDeviceFromApp();
}}
/>
</View>
</View>
</MyBottomSheetModal>
</Card>
</ScrollView> </ScrollView>
); );
} }

View File

@ -0,0 +1,26 @@
import { useTranslation } from "react-i18next";
import { View } from "react-native";
import MyResult from "../../Components/Result";
import { MyTextButton } from "../../Components/Button";
// this screen is shown when no devices are connected to the app
export default function NoDevicesConnectedScreen({ navigation }) {
const { t } = useTranslation();
// TODO: add ref to faq for help to connect a new device
return (
<View style={{ alignItems: "center", margin: 20, gap: 10 }}>
<MyResult
text={t("screens.noDevicesConnected.textDescription")}
iconName={"selection-search"}
/>
<MyTextButton
title={t("screens.noDevicesConnected.buttonSearchForNewDevices")}
actionColor
onPress={() => navigation.navigate("modalSearchForNewDevices")}
/>
</View>
);
}

View File

@ -89,6 +89,8 @@ const DarkAppTheme = {
text: "#fff", text: "#fff",
textSecondary: "#ddd", textSecondary: "#ddd",
textDisabled: "#b2bec3", textDisabled: "#b2bec3",
buttonTextColor: "#fff",
buttonSecondary: "#818081",
backgroundColor: "#21252a", backgroundColor: "#21252a",
card: { card: {
backgroundColor: "#2b3139", backgroundColor: "#2b3139",
@ -128,6 +130,7 @@ const DarkAppTheme = {
}, },
colorPickerDisabled: "rgba(0, 0, 0, 0.3)", colorPickerDisabled: "rgba(0, 0, 0, 0.3)",
modal: { modal: {
transparentBackgroundColor: "rgba(0, 0, 0, 0.4)",
pressedPickerItemColor: "rgba(0, 0, 0, 0.3)", pressedPickerItemColor: "rgba(0, 0, 0, 0.3)",
}, },
}; };
@ -142,6 +145,8 @@ const LightAppTheme = {
text: "#000", text: "#000",
textSecondary: "#555", textSecondary: "#555",
textDisabled: "#636e72", textDisabled: "#636e72",
buttonTextColor: "#fff",
buttonSecondary: "#aaa69d",
backgroundColor: "#f7f7f7", backgroundColor: "#f7f7f7",
card: { card: {
backgroundColor: "#fff", backgroundColor: "#fff",
@ -180,6 +185,7 @@ const LightAppTheme = {
}, },
colorPickerDisabled: "rgba(0, 0, 0, 0.3)", colorPickerDisabled: "rgba(0, 0, 0, 0.3)",
modal: { modal: {
transparentBackgroundColor: "rgba(0, 0, 0, 0.3)",
pressedPickerItemColor: "rgba(0, 0, 0, 0.1)", pressedPickerItemColor: "rgba(0, 0, 0, 0.1)",
}, },
}; };
@ -515,6 +521,7 @@ const devDevices = [
id: "1f21a12a-0bec-4336-99bb-df3f9fc9f537", // deviceId id: "1f21a12a-0bec-4336-99bb-df3f9fc9f537", // deviceId
displayName: "Turtle", displayName: "Turtle",
deviceModel: "Aurora", deviceModel: "Aurora",
deviceMacAddress: "12:34:56:78:9A:BC",
deviceIp: "127.0.0.1", deviceIp: "127.0.0.1",
firmware: { firmware: {
version: "1.0.1", version: "1.0.1",
@ -526,6 +533,7 @@ const devDevices = [
id: "5b331a12a-0bec-4336-99bb-df3f9fc9f537", // deviceId id: "5b331a12a-0bec-4336-99bb-df3f9fc9f537", // deviceId
displayName: "Elona", displayName: "Elona",
deviceModel: "Aurora", deviceModel: "Aurora",
deviceMacAddress: "AB:CD:EF:12:34:56",
deviceIp: "192.168.0.1", deviceIp: "192.168.0.1",
firmware: { firmware: {
version: "1.0.1", version: "1.0.1",