new ui device design
parent
5ae3f9ffde
commit
d96311c3d6
8
App.js
8
App.js
|
@ -15,13 +15,14 @@ import { Suspense, lazy, useContext, useEffect } from "react";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
import "./i18n";
|
import "./i18n";
|
||||||
import DeviceScreen from "./src/Screens/Device";
|
import DeviceScreen from "./src/Screens/Device";
|
||||||
|
import DeviceOldScreen from "./src/Screens/DeviceOld";
|
||||||
|
|
||||||
|
const Drawer = createDrawerNavigator();
|
||||||
|
|
||||||
const SettingsScreen = lazy(() => import("./src/Screens/Settings"));
|
const SettingsScreen = lazy(() => import("./src/Screens/Settings"));
|
||||||
const FaqScreen = lazy(() => import("./src/Screens/FAQ"));
|
const FaqScreen = lazy(() => import("./src/Screens/FAQ"));
|
||||||
const FeedbackScreen = lazy(() => import("./src/Screens/Feedback"));
|
const FeedbackScreen = lazy(() => import("./src/Screens/Feedback"));
|
||||||
|
|
||||||
const Drawer = createDrawerNavigator();
|
|
||||||
|
|
||||||
export function MyApp() {
|
export function MyApp() {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ export function MyApp() {
|
||||||
<NavigationContainer>
|
<NavigationContainer>
|
||||||
<Drawer.Navigator
|
<Drawer.Navigator
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
// headerShown: false,
|
headerShown: true,
|
||||||
headerStyle: {
|
headerStyle: {
|
||||||
backgroundColor: appContext.appTheme.backgroundColor,
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
},
|
},
|
||||||
|
@ -75,6 +76,7 @@ export function MyApp() {
|
||||||
drawerContent={(props) => <SideBar {...props} />}
|
drawerContent={(props) => <SideBar {...props} />}
|
||||||
>
|
>
|
||||||
<Drawer.Screen name="Turtle" component={DeviceScreen} />
|
<Drawer.Screen name="Turtle" component={DeviceScreen} />
|
||||||
|
<Drawer.Screen name="Old Turtle" component={DeviceOldScreen} />
|
||||||
<Drawer.Screen name="FAQ" component={FaqScreen} />
|
<Drawer.Screen name="FAQ" component={FaqScreen} />
|
||||||
<Drawer.Screen name="Feedback" component={FeedbackScreen} />
|
<Drawer.Screen name="Feedback" component={FeedbackScreen} />
|
||||||
<Drawer.Screen name="Settings" component={SettingsScreen} />
|
<Drawer.Screen name="Settings" component={SettingsScreen} />
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 4.3 MiB |
Binary file not shown.
After Width: | Height: | Size: 2.3 MiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
|
@ -26,6 +26,7 @@
|
||||||
"react-native-safe-area-context": "4.5.0",
|
"react-native-safe-area-context": "4.5.0",
|
||||||
"react-native-screens": "~3.20.0",
|
"react-native-screens": "~3.20.0",
|
||||||
"react-native-tab-view": "^3.5.2",
|
"react-native-tab-view": "^3.5.2",
|
||||||
|
"react-native-uuid": "^2.0.1",
|
||||||
"reanimated-color-picker": "^2.3.1"
|
"reanimated-color-picker": "^2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -5010,34 +5011,6 @@
|
||||||
"react-native-screens": ">= 3.0.0"
|
"react-native-screens": ">= 3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@react-navigation/drawer/node_modules/color": {
|
|
||||||
"version": "4.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
|
||||||
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
|
||||||
"dependencies": {
|
|
||||||
"color-convert": "^2.0.1",
|
|
||||||
"color-string": "^1.9.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@react-navigation/drawer/node_modules/color-convert": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"color-name": "~1.1.4"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@react-navigation/drawer/node_modules/color-name": {
|
|
||||||
"version": "1.1.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
|
||||||
},
|
|
||||||
"node_modules/@react-navigation/elements": {
|
"node_modules/@react-navigation/elements": {
|
||||||
"version": "1.3.18",
|
"version": "1.3.18",
|
||||||
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.18.tgz",
|
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.18.tgz",
|
||||||
|
@ -6291,6 +6264,18 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/color": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1",
|
||||||
|
"color-string": "^1.9.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
@ -6313,6 +6298,22 @@
|
||||||
"simple-swizzle": "^0.2.2"
|
"simple-swizzle": "^0.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/color/node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color/node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
|
},
|
||||||
"node_modules/colorette": {
|
"node_modules/colorette": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
|
||||||
|
@ -7101,6 +7102,15 @@
|
||||||
"expo": "*"
|
"expo": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-asset/node_modules/uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-constants": {
|
"node_modules/expo-constants": {
|
||||||
"version": "14.2.1",
|
"version": "14.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-14.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/expo-constants/-/expo-constants-14.2.1.tgz",
|
||||||
|
@ -7113,6 +7123,15 @@
|
||||||
"expo": "*"
|
"expo": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-constants/node_modules/uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-file-system": {
|
"node_modules/expo-file-system": {
|
||||||
"version": "15.2.2",
|
"version": "15.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.2.2.tgz",
|
||||||
|
@ -7124,6 +7143,15 @@
|
||||||
"expo": "*"
|
"expo": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-file-system/node_modules/uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-font": {
|
"node_modules/expo-font": {
|
||||||
"version": "11.1.1",
|
"version": "11.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-11.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/expo-font/-/expo-font-11.1.1.tgz",
|
||||||
|
@ -7269,6 +7297,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.4.4.tgz",
|
||||||
"integrity": "sha512-5DV0hIEWgatSC3UgQuAZBoQeaS9CqeWRZ3vzBR9R/+IUD87Adbi4FGhU10nymRqFXOizGsureButGZIXPs7zEA=="
|
"integrity": "sha512-5DV0hIEWgatSC3UgQuAZBoQeaS9CqeWRZ3vzBR9R/+IUD87Adbi4FGhU10nymRqFXOizGsureButGZIXPs7zEA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/expo/node_modules/uuid": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
||||||
|
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/extend-shallow": {
|
"node_modules/extend-shallow": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
|
||||||
|
@ -11931,6 +11968,15 @@
|
||||||
"react-native-pager-view": "*"
|
"react-native-pager-view": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-uuid": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-uuid/-/react-native-uuid-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-cptnoIbL53GTCrWlb/+jrDC6tvb7ypIyzbXNJcpR3Vab0mkeaaVd5qnB3f0whXYzS+SMoSQLcUUB0gEWqkPC0g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0",
|
||||||
|
"npm": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native/node_modules/promise": {
|
"node_modules/react-native/node_modules/promise": {
|
||||||
"version": "8.3.0",
|
"version": "8.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
|
||||||
|
@ -13795,15 +13841,6 @@
|
||||||
"node": ">= 0.4.0"
|
"node": ">= 0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/uuid": {
|
|
||||||
"version": "3.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
|
||||||
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
|
|
||||||
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
|
|
||||||
"bin": {
|
|
||||||
"uuid": "bin/uuid"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/valid-url": {
|
"node_modules/valid-url": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz",
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"react-native-safe-area-context": "4.5.0",
|
"react-native-safe-area-context": "4.5.0",
|
||||||
"react-native-screens": "~3.20.0",
|
"react-native-screens": "~3.20.0",
|
||||||
"react-native-tab-view": "^3.5.2",
|
"react-native-tab-view": "^3.5.2",
|
||||||
|
"react-native-uuid": "^2.0.1",
|
||||||
"reanimated-color-picker": "^2.3.1"
|
"reanimated-color-picker": "^2.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { Text, TouchableHighlight, View } from "react-native";
|
||||||
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
|
|
||||||
|
export default function MyButton({ title, style, disabled, onPress }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableHighlight
|
||||||
|
disabled={disabled}
|
||||||
|
onPress={onPress}
|
||||||
|
style={[{ borderRadius: 6 }, style]}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
backgroundColor: appContext.appTheme.colors.primary,
|
||||||
|
borderRadius: 6,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
AppStyles.Shadow,
|
||||||
|
disabled && { opacity: 0.6 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Text style={{ textAlign: "center", color: "#fff" }}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableHighlight>
|
||||||
|
);
|
||||||
|
}
|
|
@ -2,9 +2,14 @@ import { useContext } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { AppContext, AppStyles } from "../../utils";
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
|
|
||||||
export default function Card({ children }) {
|
export default function Card({ children, cardBackgroundColor }) {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const backgroundColor =
|
||||||
|
cardBackgroundColor === undefined
|
||||||
|
? appContext.appTheme.card.backgroundColor
|
||||||
|
: cardBackgroundColor;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
@ -18,7 +23,7 @@ export default function Card({ children }) {
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
borderRadius: 20,
|
borderRadius: 20,
|
||||||
backgroundColor: appContext.appTheme.card.backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
padding: 20,
|
padding: 20,
|
||||||
},
|
},
|
||||||
AppStyles.Shadow,
|
AppStyles.Shadow,
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Text, View } from "react-native";
|
||||||
|
import { TouchableOpacity } from "react-native";
|
||||||
|
import { AppContext, IsPlatformIos } from "../../utils";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import MyIcon from "../Icon";
|
||||||
|
|
||||||
|
export default function MyDropdown({ label, onPress, selectedItemLabel }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity onPress={() => onPress()}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
//IsPlatformIos() && { marginBottom: 10 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View>
|
||||||
|
<Text style={{ color: appContext.appTheme.text }}>{label}</Text>
|
||||||
|
<Text style={{ color: appContext.appTheme.colors.primary }}>
|
||||||
|
{selectedItemLabel}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<MyIcon
|
||||||
|
name="chevron-down"
|
||||||
|
size={24}
|
||||||
|
color={appContext.appTheme.icon}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext } from "../../utils";
|
||||||
|
|
||||||
export default function MyIcon({ style, name, color, size }) {
|
export default function MyIcon({ style, name, color, size }) {
|
||||||
return <Icon style={style} name={name} color={color} size={size} />;
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const iconColor = color === undefined ? appContext.appTheme.icon : color;
|
||||||
|
|
||||||
|
return <Icon style={style} name={name} color={iconColor} size={size} />;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { AppContext, AppStyles, IsPlatformIos } from "../../utils";
|
||||||
import {
|
import {
|
||||||
KeyboardAvoidingView,
|
KeyboardAvoidingView,
|
||||||
Modal,
|
Modal,
|
||||||
Platform,
|
ScrollView,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
|
@ -13,15 +13,134 @@ import { Divider } from "../Divider";
|
||||||
import MyIcon from "../Icon";
|
import MyIcon from "../Icon";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const modalIosPaddingTop = 10;
|
/*
|
||||||
|
transparent: set this to prevent modal reopening on iOS
|
||||||
|
https://github.com/facebook/react-native/issues/34018
|
||||||
|
*/
|
||||||
|
|
||||||
export default function PickerModal({
|
const modalContentStyle = { margin: 10, paddingTop: 10 };
|
||||||
|
|
||||||
|
export default function MyModal({
|
||||||
|
children,
|
||||||
isOpen,
|
isOpen,
|
||||||
setIsOpen,
|
closeModal,
|
||||||
items,
|
header,
|
||||||
searchFilter,
|
content,
|
||||||
|
disableAnimationForIos,
|
||||||
|
scrollView,
|
||||||
}) {
|
}) {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const getContent = () => {
|
||||||
|
if (scrollView) {
|
||||||
|
return (
|
||||||
|
<ScrollView>
|
||||||
|
<View style={modalContentStyle}>{content}</View>
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <View style={modalContentStyle}>{content}</View>;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View>
|
||||||
|
<Modal
|
||||||
|
visible={isOpen}
|
||||||
|
animationType={disableAnimationForIos ? "none" : "slide"}
|
||||||
|
onRequestClose={() => closeModal()}
|
||||||
|
transparent
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
|
paddingTop: IsPlatformIos() ? 30 : 15,
|
||||||
|
},
|
||||||
|
,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
|
||||||
|
{getContent()}
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyPickerDefaultHeader({ title, closeModal }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={() => closeModal()}>
|
||||||
|
<MyIcon name="chevron-left" size={24} style={{ marginLeft: 20 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ fontWeight: "bold", color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View style={{ marginRight: 40 }} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyPickerModalListItem({ onPress, itemName, itemSelected }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TouchableOpacity onPress={onPress}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginLeft: 10,
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{itemName}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{itemSelected && (
|
||||||
|
<MyIcon
|
||||||
|
name="check"
|
||||||
|
size={24}
|
||||||
|
color={appContext.appTheme.colors.primary}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MyPickerModal({ isOpen, setIsOpen, items, searchFilter }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [providedItems, setProvidedItems] = useState([]);
|
const [providedItems, setProvidedItems] = useState([]);
|
||||||
const [searchFilterInput, setSearchFilterInput] = useState("");
|
const [searchFilterInput, setSearchFilterInput] = useState("");
|
||||||
|
@ -47,7 +166,6 @@ export default function PickerModal({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: appContext.appTheme.backgroundColor,
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
},
|
},
|
||||||
IsPlatformIos() && { paddingTop: modalIosPaddingTop },
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||||
|
@ -193,7 +311,7 @@ export default function PickerModal({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TextInputModal({
|
export function MyTextInputModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
onTextInputSave,
|
onTextInputSave,
|
||||||
|
@ -217,7 +335,6 @@ export function TextInputModal({
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: appContext.appTheme.backgroundColor,
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
},
|
},
|
||||||
IsPlatformIos() && { paddingTop: modalIosPaddingTop },
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
|
@ -122,7 +122,7 @@ export default function Sidebar(props) {
|
||||||
{t("sideBar.devicesTitle")}
|
{t("sideBar.devicesTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}>
|
<DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}>
|
||||||
{["Turtle"].map((item, i) => (
|
{["Turtle", "Old Turtle"].map((item, i) => (
|
||||||
<MyDrawerItem
|
<MyDrawerItem
|
||||||
key={i}
|
key={i}
|
||||||
isDevice
|
isDevice
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { lazy, useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Image,
|
Image,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
|
@ -7,17 +7,12 @@ import {
|
||||||
Text,
|
Text,
|
||||||
TouchableHighlight,
|
TouchableHighlight,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
Dimensions,
|
|
||||||
Platform,
|
|
||||||
ImageBackground,
|
ImageBackground,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import LightView from "./light";
|
|
||||||
import { AppContext } from "../../utils";
|
import { AppContext } from "../../utils";
|
||||||
import MyIcon from "../../Components/Icon";
|
import MyIcon from "../../Components/Icon";
|
||||||
|
import SettingsView from "./settings";
|
||||||
const MotorView = lazy(() => import("./motor"));
|
import SceneView from "./scene";
|
||||||
const SettingsView = lazy(() => import("./settings"));
|
|
||||||
const ColorScenesView = lazy(() => import("./colorScenes"));
|
|
||||||
|
|
||||||
const spaceToSide = 10; // left and right
|
const spaceToSide = 10; // left and right
|
||||||
const top = 35;
|
const top = 35;
|
||||||
|
@ -27,43 +22,16 @@ const topFirst = top;
|
||||||
const topSecond = top + spaceBetweenButtons;
|
const topSecond = top + spaceBetweenButtons;
|
||||||
const topThird = top + 2 * spaceBetweenButtons;
|
const topThird = top + 2 * spaceBetweenButtons;
|
||||||
|
|
||||||
const windowDimensions = Dimensions.get("window");
|
|
||||||
|
|
||||||
let data = [];
|
|
||||||
|
|
||||||
const ledLines = 4;
|
|
||||||
const ledsPerLine = 16;
|
|
||||||
|
|
||||||
const deviceLeds = ledLines * ledsPerLine;
|
|
||||||
|
|
||||||
// setting default color for testing
|
|
||||||
for (let i = 0; i < deviceLeds; i++) {
|
|
||||||
data.push("lime");
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function DeviceScreen() {
|
export default function DeviceScreen() {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
const [selectedView, setSelectedView] = useState(0);
|
const [selectedView, setSelectedView] = useState(0);
|
||||||
const [deviceLedsColors, setDeviceLedsColor] = useState(data);
|
|
||||||
const [selectedDeviceLed, setSelectedDeviceLed] = useState(2);
|
|
||||||
|
|
||||||
const SelectedView = () => {
|
const SelectedView = () => {
|
||||||
switch (selectedView) {
|
switch (selectedView) {
|
||||||
case 0:
|
case 0:
|
||||||
return <LightView />;
|
|
||||||
case 2:
|
|
||||||
return <MotorView />;
|
|
||||||
case 3:
|
|
||||||
return <SettingsView />;
|
return <SettingsView />;
|
||||||
case 4:
|
case 2:
|
||||||
return (
|
return <SceneView />;
|
||||||
<ColorScenesView
|
|
||||||
deviceLedsColors={deviceLedsColors}
|
|
||||||
setDeviceLedsColor={setDeviceLedsColor}
|
|
||||||
selectedDeviceLed={selectedDeviceLed}
|
|
||||||
setSelectedDeviceLed={setSelectedDeviceLed}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
<Text>Not found</Text>;
|
<Text>Not found</Text>;
|
||||||
}
|
}
|
||||||
|
@ -102,59 +70,6 @@ export default function DeviceScreen() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DeviceLedsColor = () => {
|
|
||||||
let elements = [];
|
|
||||||
let test = 400;
|
|
||||||
|
|
||||||
for (let l = 0; l < ledLines; l++) {
|
|
||||||
let left = 0;
|
|
||||||
let ledsElements = [];
|
|
||||||
|
|
||||||
for (let p = 0; p < ledsPerLine; p++) {
|
|
||||||
left = left + 1.5;
|
|
||||||
|
|
||||||
const ledId = l > 0 ? l * 16 + p : p;
|
|
||||||
|
|
||||||
const deviceLedColor =
|
|
||||||
l > 0 ? deviceLedsColors[l * 16 + p] : deviceLedsColors[p];
|
|
||||||
|
|
||||||
ledsElements.push(
|
|
||||||
<View
|
|
||||||
key={`${l}-${p}`}
|
|
||||||
style={{
|
|
||||||
width: 0.1 * (test / 16),
|
|
||||||
height: 0.1 * (test / 16),
|
|
||||||
backgroundColor:
|
|
||||||
ledId === selectedDeviceLed ? "red" : deviceLedColor,
|
|
||||||
borderRadius: 0.5,
|
|
||||||
left: left,
|
|
||||||
marginRight:
|
|
||||||
windowDimensions.width > 360
|
|
||||||
? 0.27 * (test / 16)
|
|
||||||
: 0.26 * (test / 16),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.push(
|
|
||||||
<View
|
|
||||||
key={`v-${l}`}
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "center",
|
|
||||||
top: 118.5 + l,
|
|
||||||
right: "8%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{ledsElements}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>{elements}</>;
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
@ -193,49 +108,27 @@ export default function DeviceScreen() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<MyButton
|
<MyButton
|
||||||
iconName={"lightbulb-on-outline"}
|
iconName={"cog-outline"}
|
||||||
left
|
left={false}
|
||||||
selectedViewNumber={0}
|
selectedViewNumber={0}
|
||||||
space={spaceToSide}
|
space={spaceToSide}
|
||||||
top={topFirst}
|
top={topFirst}
|
||||||
/>
|
/>
|
||||||
<MyButton
|
<MyButton
|
||||||
iconName={"television-ambient-light"}
|
iconName={"rotate-3d-variant"}
|
||||||
left
|
left={false}
|
||||||
selectedViewNumber={1}
|
selectedViewNumber={1}
|
||||||
space={spaceToSide}
|
space={spaceToSide}
|
||||||
top={topSecond}
|
top={topSecond}
|
||||||
/>
|
/>
|
||||||
<MyButton
|
<MyButton
|
||||||
iconName={"axis-z-rotate-counterclockwise"}
|
iconName={"group"}
|
||||||
left
|
left={false}
|
||||||
selectedViewNumber={2}
|
selectedViewNumber={2}
|
||||||
space={spaceToSide}
|
space={spaceToSide}
|
||||||
top={topThird}
|
top={topThird}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MyButton
|
|
||||||
iconName={"cog-outline"}
|
|
||||||
left={false}
|
|
||||||
selectedViewNumber={3}
|
|
||||||
space={spaceToSide}
|
|
||||||
top={topFirst}
|
|
||||||
/>
|
|
||||||
<MyButton
|
|
||||||
iconName={"palette-outline"}
|
|
||||||
left={false}
|
|
||||||
selectedViewNumber={4}
|
|
||||||
space={spaceToSide}
|
|
||||||
top={topSecond}
|
|
||||||
/>
|
|
||||||
<MyButton
|
|
||||||
iconName={"rotate-3d-variant"}
|
|
||||||
left={false}
|
|
||||||
selectedViewNumber={5}
|
|
||||||
space={spaceToSide}
|
|
||||||
top={topThird}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ScrollView style={{ height: "100%" }}>
|
<ScrollView style={{ height: "100%" }}>
|
||||||
<SelectedView />
|
<SelectedView />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { Text } from "react-native";
|
||||||
|
|
||||||
|
export default function LayersActionEditModalContent() {
|
||||||
|
return <Text>Layers</Text>;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Text, TouchableHighlight, View } from "react-native";
|
||||||
|
import MyButton from "../../../../../Components/Button";
|
||||||
|
|
||||||
|
function Layer({ number, selected, onPress }) {
|
||||||
|
return (
|
||||||
|
<TouchableHighlight onPress={onPress} style={{ borderRadius: 10 }}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
height: 150,
|
||||||
|
width: 150,
|
||||||
|
backgroundColor: "gray",
|
||||||
|
borderRadius: 10,
|
||||||
|
},
|
||||||
|
selected && { borderColor: "#9b59b6", borderWidth: 6 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<View style={{ alignItems: "flex-end" }}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
marginTop: 6,
|
||||||
|
marginRight: 6,
|
||||||
|
backgroundColor: "#e67e22",
|
||||||
|
paddingLeft: 6,
|
||||||
|
paddingRight: 6,
|
||||||
|
borderRadius: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text>{number}</Text>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</TouchableHighlight>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function LayerSelectionModalContent({
|
||||||
|
openLayersActionEditModal,
|
||||||
|
}) {
|
||||||
|
const [selectedLayer, setSelectedLayer] = useState([]);
|
||||||
|
|
||||||
|
const handleSelectLayerClick = (layerNumber) => {
|
||||||
|
if (selectedLayer.includes(layerNumber)) {
|
||||||
|
setSelectedLayer((sLayer) =>
|
||||||
|
sLayer.filter((item) => item != layerNumber)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setSelectedLayer((sLayer) => [...sLayer, layerNumber]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: 14,
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Array.from({ length: 4 }).map((_, i) => (
|
||||||
|
<Layer
|
||||||
|
key={i}
|
||||||
|
number={i + 1}
|
||||||
|
selected={selectedLayer.includes(i + 1)}
|
||||||
|
onPress={() => handleSelectLayerClick(i + 1)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View style={{ alignItems: "center" }}>
|
||||||
|
<MyButton
|
||||||
|
title={"Hinzufügen"}
|
||||||
|
style={{ marginTop: 20, width: 180 }}
|
||||||
|
disabled={selectedLayer.length === 0}
|
||||||
|
onPress={() => openLayersActionEditModal()}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { Image, Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import { AppContext, AppStyles } from "../../../../utils";
|
||||||
|
import MyIcon from "../../../../Components/Icon";
|
||||||
|
import { Divider } from "../../../../Components/Divider";
|
||||||
|
|
||||||
|
function Action({ text, iconName, imageSource, onPress }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{ marginLeft: 10, marginRight: 10 }}
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
imageSource !== undefined && { marginBottom: 4 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<MyIcon name={iconName} size={24} />
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.text, marginLeft: 6 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
{imageSource !== undefined && (
|
||||||
|
<Image source={imageSource} style={{ height: 150, width: 150 }} />
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AddSceneActionModalContent({
|
||||||
|
openLayerSelectionModal,
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Action
|
||||||
|
text="Ebenen"
|
||||||
|
iconName="lightbulb-on-outline"
|
||||||
|
imageSource={require("../../../../../assets/layers.gif")}
|
||||||
|
onPress={openLayerSelectionModal}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Action
|
||||||
|
text="Motor"
|
||||||
|
iconName="axis-z-rotate-counterclockwise"
|
||||||
|
imageSource={require("../../../../../assets/motor.gif")}
|
||||||
|
onPress={() => console.log("pressed action")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Action
|
||||||
|
text="Ambilight"
|
||||||
|
iconName="television-ambient-light"
|
||||||
|
imageSource={require("../../../../../assets/ambilight.gif")}
|
||||||
|
onPress={() => console.log("pressed action")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Action
|
||||||
|
text="Warten"
|
||||||
|
iconName="timer-sand"
|
||||||
|
onPress={() => console.log("pressed action")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Action
|
||||||
|
text="Stop"
|
||||||
|
iconName="pause-octagon-outline"
|
||||||
|
onPress={() => console.log("pressed action")}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Action
|
||||||
|
text="Zeitsteuerung"
|
||||||
|
iconName="timer-cog"
|
||||||
|
onPress={() => console.log("pressed action")}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
import {
|
||||||
|
AppContext,
|
||||||
|
DevDeviceId,
|
||||||
|
NewEmptyDeviceScene,
|
||||||
|
} from "../../../../../utils";
|
||||||
|
import { FlatList, View } from "react-native";
|
||||||
|
import { MyPickerModalListItem } from "../../../../../Components/Modal";
|
||||||
|
|
||||||
|
export default function CreateSceneModalContent({ closeChooseSceneModals }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "Leere Szene erstellen",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Standard Szene erstellen",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Vorhandene Szene kopieren",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
data={options}
|
||||||
|
keyExtractor={(item) => item.id}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<MyPickerModalListItem
|
||||||
|
itemName={item.name}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("pressed", item);
|
||||||
|
|
||||||
|
appContext.setDevices((arr) => {
|
||||||
|
const newArr = [...arr];
|
||||||
|
|
||||||
|
newArr[arr.findIndex((d) => d.id === DevDeviceId)].scenes.push(
|
||||||
|
NewEmptyDeviceScene()
|
||||||
|
);
|
||||||
|
|
||||||
|
return newArr;
|
||||||
|
});
|
||||||
|
|
||||||
|
closeChooseSceneModals();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { useContext, useState } from "react";
|
||||||
|
import { FlatList, Text, TouchableOpacity } from "react-native";
|
||||||
|
import { AppContext, AppStyles, DevDeviceId } from "../../../../utils";
|
||||||
|
import { Divider } from "../../../../Components/Divider";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import MyIcon from "../../../../Components/Icon";
|
||||||
|
import { MyPickerModalListItem } from "../../../../Components/Modal";
|
||||||
|
|
||||||
|
export default function ChooseSceneModalContent({ openCreateSceneModal }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const device = appContext.devices.find((device) => device.id === DevDeviceId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FlatList
|
||||||
|
data={device.scenes}
|
||||||
|
keyExtractor={(item) => item.id}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<MyPickerModalListItem
|
||||||
|
itemName={item.name}
|
||||||
|
itemSelected={device.selectedScene === item.id}
|
||||||
|
onPress={() => {
|
||||||
|
appContext.setDevices((arr) => {
|
||||||
|
const newArr = [...arr];
|
||||||
|
|
||||||
|
newArr[
|
||||||
|
arr.findIndex((d) => d.id === DevDeviceId)
|
||||||
|
].selectedScene = item.id;
|
||||||
|
|
||||||
|
return newArr;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
onPress={openCreateSceneModal}
|
||||||
|
>
|
||||||
|
<MyIcon
|
||||||
|
name="plus-circle-outline"
|
||||||
|
color={appContext.appTheme.textSecondary}
|
||||||
|
size={24}
|
||||||
|
style={{ marginRight: 10 }}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.textSecondary },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
Neue Szene erstellen
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
import { FlatList, Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import Card from "../../Components/Card";
|
||||||
|
import { AppContext, AppStyles, DevDeviceId } from "../../utils";
|
||||||
|
import { useContext, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import MyDropdown from "../../Components/Dropdown";
|
||||||
|
import MyIcon from "../../Components/Icon";
|
||||||
|
import MyModal, { MyPickerDefaultHeader } 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 LayersActionEditModalContent from "./modals/ActionEdits/Layers";
|
||||||
|
|
||||||
|
function NothingSelected({ text }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 40,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MyIcon name="selection-search" size={64} />
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.text, marginTop: 10 },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function SceneView() {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
|
||||||
|
const [modalOpenStates, setModalOpenStates] = useState({
|
||||||
|
modalChooseSceneIsOpen: false,
|
||||||
|
modalCreateSceneIsOpen: false,
|
||||||
|
modalAddSceneActionIsOpen: false,
|
||||||
|
modalLayerSectionIsOpen: false,
|
||||||
|
modalLayersActionEditIsOpen: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const setModalOpen = (modalName, open) => {
|
||||||
|
console.log("setModalOpen", modalName, open);
|
||||||
|
|
||||||
|
setModalOpenStates((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
[modalName]: open,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const device = appContext.devices.find((device) => device.id === DevDeviceId);
|
||||||
|
|
||||||
|
const deviceScene = device.scenes.find(
|
||||||
|
(scene) => scene.id === device.selectedScene
|
||||||
|
);
|
||||||
|
|
||||||
|
const closeChooseSceneModals = () => {
|
||||||
|
setModalOpenStates((prevState) => ({
|
||||||
|
...prevState,
|
||||||
|
modalChooseSceneIsOpen: false,
|
||||||
|
modalCreateSceneIsOpen: false,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
const actionColor =
|
||||||
|
deviceScene === undefined || deviceScene.actions.length === 0
|
||||||
|
? appContext.appTheme.colors.primary
|
||||||
|
: appContext.appTheme.textSecondary;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card>
|
||||||
|
<MyDropdown
|
||||||
|
label={"Szene"}
|
||||||
|
onPress={() => {
|
||||||
|
console.log("pressed");
|
||||||
|
setModalOpen("modalChooseSceneIsOpen", true);
|
||||||
|
}}
|
||||||
|
selectedItemLabel={
|
||||||
|
device.selectedScene === 0
|
||||||
|
? "Keine Szene ausgewählt"
|
||||||
|
: device.scenes.find((scene) => scene.id === device.selectedScene)
|
||||||
|
.name
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
{device.selectedScene === 0 ? (
|
||||||
|
<NothingSelected text="Keine Szene ausgewählt" />
|
||||||
|
) : (
|
||||||
|
<View>
|
||||||
|
{deviceScene.actions.length === 0 ? (
|
||||||
|
<NothingSelected text="Keine Aktionen in der Szene vorhanden" />
|
||||||
|
) : (
|
||||||
|
<FlatList
|
||||||
|
scrollEnabled={false}
|
||||||
|
data={deviceScene.actions}
|
||||||
|
keyExtractor={(item) => item.id}
|
||||||
|
renderItem={({ item }) => (
|
||||||
|
<Card cardBackgroundColor={appContext.appTheme.colors.primary}>
|
||||||
|
<Text>{item.name}</Text>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => setModalOpen("modalAddSceneActionIsOpen", true)}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginTop: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MyIcon
|
||||||
|
name="plus-circle-outline"
|
||||||
|
size={24}
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
color: actionColor,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text style={{ color: actionColor }}>Aktion hinzufügen</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
<MyModal
|
||||||
|
isOpen={modalOpenStates.modalChooseSceneIsOpen}
|
||||||
|
closeModal={() => setModalOpen("modalChooseSceneIsOpen", false)}
|
||||||
|
header={
|
||||||
|
<MyPickerDefaultHeader
|
||||||
|
title={"Wähle eine Szene aus"}
|
||||||
|
closeModal={() => setModalOpen("modalChooseSceneIsOpen", false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<ChooseSceneModalContent
|
||||||
|
openCreateSceneModal={() =>
|
||||||
|
setModalOpen("modalCreateSceneIsOpen", true)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MyModal
|
||||||
|
isOpen={modalOpenStates.modalCreateSceneIsOpen}
|
||||||
|
closeModal={() => setModalOpen("modalCreateSceneIsOpen", false)}
|
||||||
|
header={
|
||||||
|
<MyPickerDefaultHeader
|
||||||
|
title={"Szene erstellen"}
|
||||||
|
closeModal={() => setModalOpen("modalCreateSceneIsOpen", false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<CreateSceneModalContent
|
||||||
|
closeChooseSceneModals={closeChooseSceneModals}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</MyModal>
|
||||||
|
|
||||||
|
<MyModal
|
||||||
|
scrollView
|
||||||
|
isOpen={modalOpenStates.modalAddSceneActionIsOpen}
|
||||||
|
closeModal={() => setModalOpen("modalAddSceneActionIsOpen", false)}
|
||||||
|
header={
|
||||||
|
<MyPickerDefaultHeader
|
||||||
|
title={"Aktion hinzufügen"}
|
||||||
|
closeModal={() => setModalOpen("modalAddSceneActionIsOpen", false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<AddSceneActionModalContent
|
||||||
|
openLayerSelectionModal={() =>
|
||||||
|
setModalOpen("modalLayerSectionIsOpen", true)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MyModal
|
||||||
|
scrollView
|
||||||
|
isOpen={modalOpenStates.modalLayerSectionIsOpen}
|
||||||
|
closeModal={() => setModalOpen("modalLayerSectionIsOpen", false)}
|
||||||
|
header={
|
||||||
|
<MyPickerDefaultHeader
|
||||||
|
title={"Layer auswahl"}
|
||||||
|
closeModal={() => setModalOpen("modalLayerSectionIsOpen", false)}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
content={
|
||||||
|
<LayerSelectionModalContent
|
||||||
|
openLayersActionEditModal={() =>
|
||||||
|
setModalOpen("modalLayersActionEditIsOpen", true)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<MyModal
|
||||||
|
scrollView
|
||||||
|
isOpen={modalOpenStates.modalLayersActionEditIsOpen}
|
||||||
|
closeModal={() =>
|
||||||
|
setModalOpen("modalLayersActionEditIsOpen", false)
|
||||||
|
}
|
||||||
|
header={
|
||||||
|
<MyPickerDefaultHeader
|
||||||
|
title={"Layer Action bearbeiten"}
|
||||||
|
closeModal={() =>
|
||||||
|
setModalOpen("modalLayersActionEditIsOpen", false)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
content={<LayersActionEditModalContent />}
|
||||||
|
/>
|
||||||
|
</MyModal>
|
||||||
|
</MyModal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ 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 MyIcon from "../../Components/Icon";
|
import MyIcon from "../../Components/Icon";
|
||||||
import { TextInputModal } from "../../Components/PickerModal";
|
import { MyTextInputModal } from "../../Components/Modal";
|
||||||
|
|
||||||
export default function SettingsView() {
|
export default function SettingsView() {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
@ -104,7 +104,7 @@ export default function SettingsView() {
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TextInputModal
|
<MyTextInputModal
|
||||||
isOpen={modalTextInputVisible}
|
isOpen={modalTextInputVisible}
|
||||||
setIsOpen={setModalTextInputVisible}
|
setIsOpen={setModalTextInputVisible}
|
||||||
onTextInputSave={() => console.log("save")}
|
onTextInputSave={() => console.log("save")}
|
||||||
|
|
|
@ -0,0 +1,261 @@
|
||||||
|
import { lazy, useContext, useState } from "react";
|
||||||
|
import {
|
||||||
|
Image,
|
||||||
|
ScrollView,
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
TouchableHighlight,
|
||||||
|
TouchableOpacity,
|
||||||
|
Dimensions,
|
||||||
|
Platform,
|
||||||
|
ImageBackground,
|
||||||
|
} from "react-native";
|
||||||
|
import LightView from "./light";
|
||||||
|
import { AppContext } from "../../utils";
|
||||||
|
import MyIcon from "../../Components/Icon";
|
||||||
|
|
||||||
|
const MotorView = lazy(() => import("./motor"));
|
||||||
|
const SettingsView = lazy(() => import("./settings"));
|
||||||
|
const ColorScenesView = lazy(() => import("./colorScenes"));
|
||||||
|
|
||||||
|
const spaceToSide = 10; // left and right
|
||||||
|
const top = 35;
|
||||||
|
const spaceBetweenButtons = 60;
|
||||||
|
|
||||||
|
const topFirst = top;
|
||||||
|
const topSecond = top + spaceBetweenButtons;
|
||||||
|
const topThird = top + 2 * spaceBetweenButtons;
|
||||||
|
|
||||||
|
const windowDimensions = Dimensions.get("window");
|
||||||
|
|
||||||
|
let data = [];
|
||||||
|
|
||||||
|
const ledLines = 4;
|
||||||
|
const ledsPerLine = 16;
|
||||||
|
|
||||||
|
const deviceLeds = ledLines * ledsPerLine;
|
||||||
|
|
||||||
|
// setting default color for testing
|
||||||
|
for (let i = 0; i < deviceLeds; i++) {
|
||||||
|
data.push("lime");
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DeviceOldScreen() {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const [selectedView, setSelectedView] = useState(0);
|
||||||
|
const [deviceLedsColors, setDeviceLedsColor] = useState(data);
|
||||||
|
const [selectedDeviceLed, setSelectedDeviceLed] = useState(2);
|
||||||
|
|
||||||
|
const SelectedView = () => {
|
||||||
|
switch (selectedView) {
|
||||||
|
case 0:
|
||||||
|
return <LightView />;
|
||||||
|
case 2:
|
||||||
|
return <MotorView />;
|
||||||
|
case 3:
|
||||||
|
return <SettingsView />;
|
||||||
|
case 4:
|
||||||
|
return (
|
||||||
|
<ColorScenesView
|
||||||
|
deviceLedsColors={deviceLedsColors}
|
||||||
|
setDeviceLedsColor={setDeviceLedsColor}
|
||||||
|
selectedDeviceLed={selectedDeviceLed}
|
||||||
|
setSelectedDeviceLed={setSelectedDeviceLed}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
<Text>Not found</Text>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const MyButton = ({ selectedViewNumber, top, left, space, iconName }) => {
|
||||||
|
const TouchComponent =
|
||||||
|
appContext.appColorScheme === "dark"
|
||||||
|
? TouchableHighlight
|
||||||
|
: TouchableOpacity;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchComponent
|
||||||
|
onPress={() => setSelectedView(selectedViewNumber)}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
position: "absolute",
|
||||||
|
backgroundColor: appContext.appTheme.card.backgroundColor,
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: 8,
|
||||||
|
},
|
||||||
|
{ top: top },
|
||||||
|
left === true ? { left: space } : { right: space },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<MyIcon
|
||||||
|
name={iconName}
|
||||||
|
size={30}
|
||||||
|
color={
|
||||||
|
selectedView === selectedViewNumber
|
||||||
|
? appContext.appTheme.colors.primary
|
||||||
|
: appContext.appTheme.icon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</TouchComponent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeviceLedsColor = () => {
|
||||||
|
let elements = [];
|
||||||
|
let test = 400;
|
||||||
|
|
||||||
|
for (let l = 0; l < ledLines; l++) {
|
||||||
|
let left = 0;
|
||||||
|
let ledsElements = [];
|
||||||
|
|
||||||
|
for (let p = 0; p < ledsPerLine; p++) {
|
||||||
|
left = left + 1.5;
|
||||||
|
|
||||||
|
const ledId = l > 0 ? l * 16 + p : p;
|
||||||
|
|
||||||
|
const deviceLedColor =
|
||||||
|
l > 0 ? deviceLedsColors[l * 16 + p] : deviceLedsColors[p];
|
||||||
|
|
||||||
|
ledsElements.push(
|
||||||
|
<View
|
||||||
|
key={`${l}-${p}`}
|
||||||
|
style={{
|
||||||
|
width: 0.1 * (test / 16),
|
||||||
|
height: 0.1 * (test / 16),
|
||||||
|
backgroundColor:
|
||||||
|
ledId === selectedDeviceLed ? "red" : deviceLedColor,
|
||||||
|
borderRadius: 0.5,
|
||||||
|
left: left,
|
||||||
|
marginRight:
|
||||||
|
windowDimensions.width > 360
|
||||||
|
? 0.27 * (test / 16)
|
||||||
|
: 0.26 * (test / 16),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.push(
|
||||||
|
<View
|
||||||
|
key={`v-${l}`}
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
top: 118.5 + l,
|
||||||
|
right: "8%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{ledsElements}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>{elements}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{selectedView === 4 && (
|
||||||
|
<View>
|
||||||
|
<ImageBackground
|
||||||
|
source={require("../../../assets/image19.png")}
|
||||||
|
resizeMode="contain"
|
||||||
|
style={{ height: 250 }}
|
||||||
|
>
|
||||||
|
<DeviceLedsColor />
|
||||||
|
</ImageBackground>
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{appContext.isUserDeveloperModeEnabled ? (
|
||||||
|
<>
|
||||||
|
{selectedView !== 4 && (
|
||||||
|
<Image
|
||||||
|
source={require("../../../assets/device.png")}
|
||||||
|
style={styles.image}
|
||||||
|
resizeMode="contain"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{selectedView !== 4 && (
|
||||||
|
<View style={[styles.image, { backgroundColor: "#ddd" }]} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<MyButton
|
||||||
|
iconName={"lightbulb-on-outline"}
|
||||||
|
left
|
||||||
|
selectedViewNumber={0}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topFirst}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
iconName={"television-ambient-light"}
|
||||||
|
left
|
||||||
|
selectedViewNumber={1}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topSecond}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
iconName={"axis-z-rotate-counterclockwise"}
|
||||||
|
left
|
||||||
|
selectedViewNumber={2}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topThird}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MyButton
|
||||||
|
iconName={"cog-outline"}
|
||||||
|
left={false}
|
||||||
|
selectedViewNumber={3}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topFirst}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
iconName={"palette-outline"}
|
||||||
|
left={false}
|
||||||
|
selectedViewNumber={4}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topSecond}
|
||||||
|
/>
|
||||||
|
<MyButton
|
||||||
|
iconName={"rotate-3d-variant"}
|
||||||
|
left={false}
|
||||||
|
selectedViewNumber={5}
|
||||||
|
space={spaceToSide}
|
||||||
|
top={topThird}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ScrollView style={{ height: "100%" }}>
|
||||||
|
<SelectedView />
|
||||||
|
</ScrollView>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backgroundColor: "#2e2e30",
|
||||||
|
},
|
||||||
|
scrollView: {
|
||||||
|
width: "100%",
|
||||||
|
padding: 20,
|
||||||
|
},
|
||||||
|
image: {
|
||||||
|
width: "100%",
|
||||||
|
height: 250,
|
||||||
|
},
|
||||||
|
});
|
|
@ -25,9 +25,9 @@ import { AppContext, AppStyles, IsPlatformIos } from "../../utils";
|
||||||
import Card from "../../Components/Card";
|
import Card from "../../Components/Card";
|
||||||
import MySwitch from "../../Components/Switch";
|
import MySwitch from "../../Components/Switch";
|
||||||
import MyIcon from "../../Components/Icon";
|
import MyIcon from "../../Components/Icon";
|
||||||
import PickerModal from "../../Components/PickerModal";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import MySlider from "../../Components/Slider";
|
import MySlider from "../../Components/Slider";
|
||||||
|
import MyPickerModal from "../../Components/Modal";
|
||||||
|
|
||||||
const colorModePickerOptions = [
|
const colorModePickerOptions = [
|
||||||
{ label: "Pulse", value: "pulse" },
|
{ label: "Pulse", value: "pulse" },
|
||||||
|
@ -198,7 +198,7 @@ export default function LightView() {
|
||||||
</View>
|
</View>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
|
|
||||||
<PickerModal
|
<MyPickerModal
|
||||||
searchFilter
|
searchFilter
|
||||||
isOpen={modalDeviceColorModeVisible}
|
isOpen={modalDeviceColorModeVisible}
|
||||||
setIsOpen={setModalDeviceColorModeVisible}
|
setIsOpen={setModalDeviceColorModeVisible}
|
|
@ -0,0 +1,174 @@
|
||||||
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import Card from "../../Components/Card";
|
||||||
|
import { useContext, useState } from "react";
|
||||||
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
|
import { Divider } from "../../Components/Divider";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import MySwitch from "../../Components/Switch";
|
||||||
|
import MyIcon from "../../Components/Icon";
|
||||||
|
import { MyTextInputModal } from "../../Components/Modal";
|
||||||
|
|
||||||
|
export default function SettingsView() {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [modalTextInputVisible, setModalTextInputVisible] = useState(false);
|
||||||
|
const [switchState, setSwitchState] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography20,
|
||||||
|
{
|
||||||
|
color: appContext.appTheme.text,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.settingsTitle")}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ width: "80%" }}>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.wifiStandByTitle")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography14,
|
||||||
|
{ color: appContext.appTheme.textSecondary },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.wifiStandByDescription")}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
<MySwitch
|
||||||
|
value={switchState}
|
||||||
|
onValueChange={(e) => setSwitchState(e)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Card>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography20,
|
||||||
|
{
|
||||||
|
color: appContext.appTheme.text,
|
||||||
|
marginBottom: 10,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.deviceInformationText")}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography16], { color: appContext.appTheme.text })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.deviceNameText")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography14],
|
||||||
|
{ color: appContext.appTheme.textSecondary })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Turtle
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={() => setModalTextInputVisible(true)}>
|
||||||
|
<MyIcon name="pencil" size={18} color={appContext.appTheme.icon} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<MyTextInputModal
|
||||||
|
isOpen={modalTextInputVisible}
|
||||||
|
setIsOpen={setModalTextInputVisible}
|
||||||
|
onTextInputSave={() => console.log("save")}
|
||||||
|
modalTitle={t("screens.device.settings.deviceNameText")}
|
||||||
|
inputTitle={t("screens.device.settings.deviceNameText")}
|
||||||
|
inputDescription={t(
|
||||||
|
"screens.device.settings.modalTextInputDeviceNameDescription"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography16], { color: appContext.appTheme.text })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.deviceModelText")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography14],
|
||||||
|
{ color: appContext.appTheme.textSecondary })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Shimmex Aurora
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography16], { color: appContext.appTheme.text })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.deviceFirmwareVersionText")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography14],
|
||||||
|
{ color: appContext.appTheme.textSecondary })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
1.0.1
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography16], { color: appContext.appTheme.text })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("screens.device.settings.deviceLastUpdatedText")}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
style={
|
||||||
|
([AppStyles.typography14],
|
||||||
|
{ color: appContext.appTheme.textSecondary })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
11.07.2023 um 20:33 Uhr
|
||||||
|
</Text>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -3,9 +3,9 @@ import { 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 } from "../../utils";
|
||||||
import { Divider } from "../../Components/Divider";
|
import { Divider } from "../../Components/Divider";
|
||||||
import PickerModal from "../../Components/PickerModal";
|
|
||||||
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";
|
||||||
|
|
||||||
export default function SettingsScreen() {
|
export default function SettingsScreen() {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
@ -139,7 +139,7 @@ export default function SettingsScreen() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<PickerModal
|
<MyPickerModal
|
||||||
isOpen={modalAppColorSchemeVisible}
|
isOpen={modalAppColorSchemeVisible}
|
||||||
setIsOpen={setAppColorSchemeModalVisible}
|
setIsOpen={setAppColorSchemeModalVisible}
|
||||||
items={[
|
items={[
|
||||||
|
@ -160,7 +160,7 @@ export default function SettingsScreen() {
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PickerModal
|
<MyPickerModal
|
||||||
isOpen={modalAppLanguageVisible}
|
isOpen={modalAppLanguageVisible}
|
||||||
setIsOpen={setModalAppLanguageVisible}
|
setIsOpen={setModalAppLanguageVisible}
|
||||||
items={Constants.languages.map((language) => {
|
items={Constants.languages.map((language) => {
|
||||||
|
|
56
src/utils.js
56
src/utils.js
|
@ -2,6 +2,7 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
import { createContext, useState } from "react";
|
import { createContext, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Appearance, Platform, StyleSheet } from "react-native";
|
import { Appearance, Platform, StyleSheet } from "react-native";
|
||||||
|
import uuid from "react-native-uuid";
|
||||||
|
|
||||||
export const Constants = {
|
export const Constants = {
|
||||||
defaultLanguage: "de",
|
defaultLanguage: "de",
|
||||||
|
@ -147,14 +148,66 @@ export function GetDataFromList(list, key) {
|
||||||
return list.find((v) => v[0] === key)[1];
|
return list.find((v) => v[0] === key)[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function GetUuid() {
|
||||||
|
return uuid.v4();
|
||||||
|
}
|
||||||
|
|
||||||
const appContextPreview = {
|
const appContextPreview = {
|
||||||
appColorScheme: "",
|
appColorScheme: "",
|
||||||
appLanguage: "",
|
appLanguage: "",
|
||||||
isUserExpertModeEnabled: "",
|
isUserExpertModeEnabled: "",
|
||||||
isUserDeveloperModeEnabled: "",
|
isUserDeveloperModeEnabled: "",
|
||||||
appTheme: DarkAppTheme,
|
appTheme: DarkAppTheme,
|
||||||
|
devices: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DevDeviceId = 0;
|
||||||
|
|
||||||
|
const devData = [
|
||||||
|
{
|
||||||
|
id: 0, // deviceId
|
||||||
|
selectedScene: 0,
|
||||||
|
scenes: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Szene 1",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "Test",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Test1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Szene 2",
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: "Haha",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Haha 1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function NewEmptyDeviceScene() {
|
||||||
|
return {
|
||||||
|
id: GetUuid(),
|
||||||
|
name: "Leere Szene",
|
||||||
|
actions: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const AppContext = createContext(appContextPreview);
|
export const AppContext = createContext(appContextPreview);
|
||||||
|
|
||||||
export function AppProvider({ children }) {
|
export function AppProvider({ children }) {
|
||||||
|
@ -165,6 +218,7 @@ export function AppProvider({ children }) {
|
||||||
// TODO: only while development
|
// TODO: only while development
|
||||||
const [isUserDeveloperModeEnabled, setIsUserDeveloperModeEnabled] =
|
const [isUserDeveloperModeEnabled, setIsUserDeveloperModeEnabled] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const [devices, setDevices] = useState(devData);
|
||||||
const { i18n } = useTranslation();
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
const saveAppColorScheme = async (value) => {
|
const saveAppColorScheme = async (value) => {
|
||||||
|
@ -207,6 +261,8 @@ export function AppProvider({ children }) {
|
||||||
setIsUserExpertModeEnabled: saveUserExpertMode,
|
setIsUserExpertModeEnabled: saveUserExpertMode,
|
||||||
isUserDeveloperModeEnabled: isUserDeveloperModeEnabled,
|
isUserDeveloperModeEnabled: isUserDeveloperModeEnabled,
|
||||||
setUserIsDeveloperModeEnabled: saveUserDeveloperMode,
|
setUserIsDeveloperModeEnabled: saveUserDeveloperMode,
|
||||||
|
devices: devices,
|
||||||
|
setDevices: setDevices,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
Loading…
Reference in New Issue