i18n
parent
1a2f47bf7c
commit
835c97a20f
26
App.js
26
App.js
|
@ -1,6 +1,6 @@
|
||||||
import "react-native-gesture-handler";
|
import "react-native-gesture-handler";
|
||||||
import { StatusBar } from "expo-status-bar";
|
import { StatusBar } from "expo-status-bar";
|
||||||
import { Appearance, StyleSheet } from "react-native";
|
import { Appearance, StyleSheet, Text, View } from "react-native";
|
||||||
import { createDrawerNavigator } from "@react-navigation/drawer";
|
import { createDrawerNavigator } from "@react-navigation/drawer";
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
import { NavigationContainer } from "@react-navigation/native";
|
||||||
import SideBar from "./src/Components/SideBar";
|
import SideBar from "./src/Components/SideBar";
|
||||||
|
@ -16,8 +16,9 @@ import {
|
||||||
} from "./src/utils";
|
} from "./src/utils";
|
||||||
import DeviceScreen from "./src/Screens/Device";
|
import DeviceScreen from "./src/Screens/Device";
|
||||||
import SettingsScreen from "./src/Screens/Settings";
|
import SettingsScreen from "./src/Screens/Settings";
|
||||||
import { useContext, useEffect } from "react";
|
import { Suspense, useContext, useEffect } from "react";
|
||||||
import { SafeAreaView } from "react-native-safe-area-context";
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import "./i18n";
|
||||||
|
|
||||||
const Drawer = createDrawerNavigator();
|
const Drawer = createDrawerNavigator();
|
||||||
|
|
||||||
|
@ -42,7 +43,7 @@ export function MyApp() {
|
||||||
appLanguage === null ? Constants.defaultLanguage : appLanguage
|
appLanguage === null ? Constants.defaultLanguage : appLanguage
|
||||||
);
|
);
|
||||||
appContext.setAppColorScheme(
|
appContext.setAppColorScheme(
|
||||||
appColorScheme === null ? Appearance.getColorScheme() : appColorScheme
|
appColorScheme === null ? "auto" : appColorScheme
|
||||||
);
|
);
|
||||||
|
|
||||||
appContext.setIsUserExpertModeEnabled(
|
appContext.setIsUserExpertModeEnabled(
|
||||||
|
@ -88,17 +89,18 @@ export function MyApp() {
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<View
|
||||||
|
style={{ flex: 1, justifyContent: "center", alignItems: "center" }}
|
||||||
|
>
|
||||||
|
<Text>Loading...</Text>
|
||||||
|
</View>
|
||||||
|
}
|
||||||
|
>
|
||||||
<AppProvider>
|
<AppProvider>
|
||||||
<MyApp />
|
<MyApp />
|
||||||
</AppProvider>
|
</AppProvider>
|
||||||
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flex: 1,
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
|
@ -9,3 +9,7 @@ https://pictogrammers.com/library/mdi/
|
||||||
# RNUILib
|
# RNUILib
|
||||||
|
|
||||||
https://wix.github.io/react-native-ui-lib/docs/getting-started/setup
|
https://wix.github.io/react-native-ui-lib/docs/getting-started/setup
|
||||||
|
|
||||||
|
https://stackoverflow.com/questions/68243384/dark-mode-usecolorscheme-always-returns-light-on-android
|
||||||
|
|
||||||
|
https://stackoverflow.com/questions/70493788/i18nextpluralresolver-your-environment-seems-not-to-be-intl-api-compatible-u
|
||||||
|
|
12
app.json
12
app.json
|
@ -5,23 +5,23 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"userInterfaceStyle": "light",
|
"userInterfaceStyle": "automatic",
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash.png",
|
"image": "./assets/splash.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"assetBundlePatterns": [
|
"assetBundlePatterns": ["**/*"],
|
||||||
"**/*"
|
|
||||||
],
|
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true
|
"supportsTablet": true,
|
||||||
|
"userInterfaceStyle": "automatic"
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
}
|
},
|
||||||
|
"userInterfaceStyle": "automatic"
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"favicon": "./assets/favicon.png"
|
"favicon": "./assets/favicon.png"
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import i18n from "i18next";
|
||||||
|
import { initReactI18next } from "react-i18next";
|
||||||
|
|
||||||
|
import de from "./locales/de.json";
|
||||||
|
import en from "./locales/en.json";
|
||||||
|
|
||||||
|
const resources = {
|
||||||
|
de: {
|
||||||
|
translation: de,
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
translation: en,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
i18n
|
||||||
|
.use(initReactI18next) // passes i18n down to react-i18next
|
||||||
|
.init({
|
||||||
|
compatibilityJSON: "v3",
|
||||||
|
resources,
|
||||||
|
lng: "en", // language to use, more information here: https://www.i18next.com/overview/configuration-options#languages-namespaces-resources
|
||||||
|
// you can use the i18n.changeLanguage function to change the language manually: https://www.i18next.com/overview/api#changelanguage
|
||||||
|
// if you're using a language detector, do not define the lng option
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false, // react already safes from xss
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"test": "Einstellungen",
|
||||||
|
"sideBar": {
|
||||||
|
"devicesTitle": "Geräte",
|
||||||
|
"settings": "Einstellungen",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"feedback": "Feedback geben"
|
||||||
|
},
|
||||||
|
"screens": {
|
||||||
|
"device": {
|
||||||
|
"settings": {
|
||||||
|
"settingsTitle": "Einstellungen",
|
||||||
|
"wifiStandByTitle": "WLAN im Standby",
|
||||||
|
"wifiStandByDescription": "Die WLAN-Verbindung bleibt bestehen, auch wenn das Gerät ausgeschaltet ist. Bitte beachten Sie, dass dies zu einem erhöhten Stromverbrauch führen kann.",
|
||||||
|
"deviceInformationTitle": "Geräteinformationen",
|
||||||
|
"deviceModelTitle": "Gerätemodell",
|
||||||
|
"deviceFirmwareVersionTitle": "Firmware Version",
|
||||||
|
"deviceLastUpdated": "Letzte Aktualisierung"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"settingsCardTitle": "Einstellungen",
|
||||||
|
"languageText": "Sprache",
|
||||||
|
"appColorSchemeText": "Anzeigemodus",
|
||||||
|
"appColorSchemePicker": {
|
||||||
|
"auto": "Systemvoreinstellung",
|
||||||
|
"dark": "Dunkel",
|
||||||
|
"light": "Hell"
|
||||||
|
},
|
||||||
|
"expertModeTitle": "Experten Modus",
|
||||||
|
"expertModeDescription": "Durch das Einschalten werden zusätzliche Funktionen in der App freigeschaltet, wie beispielsweise die Möglichkeit, benutzerdefinierte Farbcodes anzugeben."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"test": "Settings",
|
||||||
|
"sideBar": {
|
||||||
|
"devicesTitle": "Devices",
|
||||||
|
"settings": "Settings",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"feedback": "Give feedback"
|
||||||
|
},
|
||||||
|
"screens": {
|
||||||
|
"device": {
|
||||||
|
"settings": {
|
||||||
|
"settingsTitle": "Settings",
|
||||||
|
"wifiStandByTitle": "WLAN in standby",
|
||||||
|
"wifiStandByDescription": "The WLAN connection remains established even if the device is switched off. Please note that this can lead to increased power consumption.",
|
||||||
|
"deviceInformationTitle": "Device information",
|
||||||
|
"deviceModelTitle": "Device model",
|
||||||
|
"deviceFirmwareVersionTitle": "Firmware Version",
|
||||||
|
"deviceLastUpdated": "Last updated"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"settingsCardTitle": "Settings",
|
||||||
|
"languageText": "Language",
|
||||||
|
"appColorSchemeText": "Appearance",
|
||||||
|
"appColorSchemePicker": {
|
||||||
|
"auto": "System default",
|
||||||
|
"dark": "Dark",
|
||||||
|
"light": "Light"
|
||||||
|
},
|
||||||
|
"expertModeTitle": "Expert mode",
|
||||||
|
"expertModeDescription": "Turning it on unlocks additional features in the app, such as the ability to specify custom color codes."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,10 @@
|
||||||
"@react-navigation/native-stack": "^6.9.13",
|
"@react-navigation/native-stack": "^6.9.13",
|
||||||
"expo": "~48.0.18",
|
"expo": "~48.0.18",
|
||||||
"expo-status-bar": "~1.4.4",
|
"expo-status-bar": "~1.4.4",
|
||||||
|
"i18next": "^23.2.11",
|
||||||
|
"i18next-browser-languagedetector": "^7.1.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
"react-i18next": "^13.0.2",
|
||||||
"react-native": "0.71.8",
|
"react-native": "0.71.8",
|
||||||
"react-native-gesture-handler": "~2.9.0",
|
"react-native-gesture-handler": "~2.9.0",
|
||||||
"react-native-pager-view": "6.1.2",
|
"react-native-pager-view": "6.1.2",
|
||||||
|
@ -8091,6 +8094,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/html-parse-stringify": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
|
||||||
|
"dependencies": {
|
||||||
|
"void-elements": "3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/http-errors": {
|
"node_modules/http-errors": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||||
|
@ -8126,6 +8137,36 @@
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/i18next": {
|
||||||
|
"version": "23.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.2.11.tgz",
|
||||||
|
"integrity": "sha512-MA4FsxOjyCaOZtRDB4yuwjCvqYEioD4G4LlXOn7SO3rnQUlxTufyLsOqfL9MKakeLRBkefe8bqcs0D6Z/xFk1w==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://locize.com/i18next.html"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.22.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/i18next-browser-languagedetector": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-cr2k7u1XJJ4HTOjM9GyOMtbOA47RtUoWRAtt52z43r3AoMs2StYKyjS3URPhzHaf+mn10hY9dZWamga5WPQjhA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.19.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.4.24",
|
"version": "0.4.24",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||||
|
@ -12105,6 +12146,27 @@
|
||||||
"react": ">=17.0.0"
|
"react": ">=17.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-i18next": {
|
||||||
|
"version": "13.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-13.0.2.tgz",
|
||||||
|
"integrity": "sha512-NEVxC32v0oR4egwYM0QM0WE93AiJG5r0NTXTL8mhQfAhsMfDS2fSO6jpluyfsfypP988KzUQrAXncspcJ7+GHA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.22.5",
|
||||||
|
"html-parse-stringify": "^3.0.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"i18next": ">= 23.2.3",
|
||||||
|
"react": ">= 16.8.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "17.0.2",
|
"version": "17.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||||
|
@ -14351,6 +14413,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz",
|
||||||
"integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="
|
"integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/void-elements": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/walker": {
|
"node_modules/walker": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
"@react-navigation/native-stack": "^6.9.13",
|
"@react-navigation/native-stack": "^6.9.13",
|
||||||
"expo": "~48.0.18",
|
"expo": "~48.0.18",
|
||||||
"expo-status-bar": "~1.4.4",
|
"expo-status-bar": "~1.4.4",
|
||||||
|
"i18next": "^23.2.11",
|
||||||
|
"i18next-browser-languagedetector": "^7.1.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
"react-i18next": "^13.0.2",
|
||||||
"react-native": "0.71.8",
|
"react-native": "0.71.8",
|
||||||
"react-native-gesture-handler": "~2.9.0",
|
"react-native-gesture-handler": "~2.9.0",
|
||||||
"react-native-pager-view": "6.1.2",
|
"react-native-pager-view": "6.1.2",
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { useContext } from "react";
|
||||||
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
|
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
||||||
|
import { Modal, Text, TouchableOpacity, View } from "react-native";
|
||||||
|
import { Divider } from "../Divider";
|
||||||
|
|
||||||
|
export default function PickerModal({ isOpen, setIsOpen, items }) {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const closeModal = () => setIsOpen(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
visible={isOpen}
|
||||||
|
animationType="slide"
|
||||||
|
onRequestClose={() => closeModal()}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: appContext.appTheme.backgroundColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
console.log("press");
|
||||||
|
setIsOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name="window-close"
|
||||||
|
size={24}
|
||||||
|
style={{ marginLeft: 10, marginTop: 20, marginBottom: 20 }}
|
||||||
|
color={appContext.appTheme.icon}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
{items.map((item, i) => {
|
||||||
|
return item.selected ? (
|
||||||
|
<View key={i}>
|
||||||
|
<TouchableOpacity onPress={() => closeModal()}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginLeft: 20,
|
||||||
|
marginRight: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Text>
|
||||||
|
<Icon
|
||||||
|
name="check"
|
||||||
|
size={24}
|
||||||
|
color={appContext.appTheme.colors.primary}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View key={i}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
closeModal();
|
||||||
|
item.onPress();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography16,
|
||||||
|
{ marginLeft: 20, color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Divider />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
|
@ -4,10 +4,11 @@ import { Image, Text, TouchableOpacity, View } from "react-native";
|
||||||
import { AppContext, AppStyles } from "../../utils";
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
import { Divider } from "../Divider";
|
import { Divider } from "../Divider";
|
||||||
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
||||||
import { useIsFocused } from "@react-navigation/native";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function Sidebar(props) {
|
export default function Sidebar(props) {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const MyDrawerItem = ({
|
const MyDrawerItem = ({
|
||||||
label,
|
label,
|
||||||
|
@ -53,7 +54,7 @@ export default function Sidebar(props) {
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={() => console.log("Pressed")}
|
onPress={() => console.log("Pressed power")}
|
||||||
style={{ right: -30 }}
|
style={{ right: -30 }}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
|
@ -118,7 +119,7 @@ export default function Sidebar(props) {
|
||||||
{ marginLeft: 10, marginTop: 10, color: appContext.appTheme.text },
|
{ marginLeft: 10, marginTop: 10, color: appContext.appTheme.text },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Geräte
|
{t("sideBar.devicesTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}>
|
<DrawerContentScrollView contentContainerStyle={{ paddingTop: 0 }}>
|
||||||
{["Turtle"].map((item, i) => (
|
{["Turtle"].map((item, i) => (
|
||||||
|
@ -137,19 +138,19 @@ export default function Sidebar(props) {
|
||||||
<View style={{ justifyContent: "flex-end" }}>
|
<View style={{ justifyContent: "flex-end" }}>
|
||||||
<Divider style={{ marginLeft: 10, marginRight: 10 }} />
|
<Divider style={{ marginLeft: 10, marginRight: 10 }} />
|
||||||
<MyDrawerItem
|
<MyDrawerItem
|
||||||
label={"FAQ"}
|
label={t("sideBar.faq")}
|
||||||
onPress={() => props.navigation.navigate("FAQ")}
|
onPress={() => props.navigation.navigate("FAQ")}
|
||||||
iconName="frequently-asked-questions"
|
iconName="frequently-asked-questions"
|
||||||
routeName="FAQ"
|
routeName="FAQ"
|
||||||
/>
|
/>
|
||||||
<MyDrawerItem
|
<MyDrawerItem
|
||||||
label={"Feedback geben"}
|
label={t("sideBar.feedback")}
|
||||||
onPress={() => props.navigation.navigate("Feedback")}
|
onPress={() => props.navigation.navigate("Feedback")}
|
||||||
iconName="comment-quote"
|
iconName="comment-quote"
|
||||||
routeName="Feedback"
|
routeName="Feedback"
|
||||||
/>
|
/>
|
||||||
<MyDrawerItem
|
<MyDrawerItem
|
||||||
label={"Einstellungen"}
|
label={t("sideBar.settings")}
|
||||||
onPress={() => props.navigation.navigate("Settings")}
|
onPress={() => props.navigation.navigate("Settings")}
|
||||||
iconName="cog"
|
iconName="cog"
|
||||||
routeName="Settings"
|
routeName="Settings"
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { Text, View } from "react-native";
|
import { Text, View } from "react-native";
|
||||||
import Card from "../../Components/Card";
|
import Card from "../../Components/Card";
|
||||||
import { Incubator, Switch } from "react-native-ui-lib";
|
import { Incubator, Switch } from "react-native-ui-lib";
|
||||||
import { useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
import { AppStyles } from "../../utils";
|
import { AppContext, AppStyles } from "../../utils";
|
||||||
import { Divider } from "../../Components/Divider";
|
import { Divider } from "../../Components/Divider";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function SettingsView() {
|
export default function SettingsView() {
|
||||||
|
const appContext = useContext(AppContext);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [switchState, setSwitchState] = useState(false);
|
const [switchState, setSwitchState] = useState(false);
|
||||||
const [sliderValue, setSliderValue] = useState(0);
|
const [sliderValue, setSliderValue] = useState(0);
|
||||||
|
|
||||||
|
@ -16,12 +20,12 @@ export default function SettingsView() {
|
||||||
style={[
|
style={[
|
||||||
AppStyles.typography20,
|
AppStyles.typography20,
|
||||||
{
|
{
|
||||||
color: "#fff",
|
color: appContext.appTheme.text,
|
||||||
marginBottom: 10,
|
marginBottom: 10,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Einstellungen
|
{t("screens.device.settings.settingsTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -33,12 +37,10 @@ export default function SettingsView() {
|
||||||
>
|
>
|
||||||
<View style={{ width: "80%" }}>
|
<View style={{ width: "80%" }}>
|
||||||
<Text style={[AppStyles.typography16, { color: "#fff" }]}>
|
<Text style={[AppStyles.typography16, { color: "#fff" }]}>
|
||||||
WLAN im Standby
|
{t("screens.device.settings.wifiStandByTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={[AppStyles.typography14, { color: "#ddd" }]}>
|
<Text style={[AppStyles.typography14, { color: "#ddd" }]}>
|
||||||
Die WLAN-Verbindung bleibt bestehen, auch wenn das Gerät
|
{t("screens.device.settings.wifiStandByDescription")}
|
||||||
ausgeschaltet ist. Bitte beachten Sie, dass dies zu einem erhöhten
|
|
||||||
Stromverbrauch führen kann.
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Switch
|
<Switch
|
||||||
|
@ -58,22 +60,22 @@ export default function SettingsView() {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Geräteinformationen
|
{t("screens.device.settings.deviceInformationTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
||||||
Gerätemodell
|
{t("screens.device.settings.deviceModelTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={([AppStyles.typography14], { color: "#ddd" })}>
|
<Text style={([AppStyles.typography14], { color: "#ddd" })}>
|
||||||
Shimmex Aurora
|
Shimmex Aurora
|
||||||
</Text>
|
</Text>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
||||||
Firmware Version
|
{t("screens.device.settings.deviceFirmwareVersionTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={([AppStyles.typography14], { color: "#ddd" })}>1.0.1</Text>
|
<Text style={([AppStyles.typography14], { color: "#ddd" })}>1.0.1</Text>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
<Text style={([AppStyles.typography16], { color: "#fff" })}>
|
||||||
Letzte Aktualisierung
|
{t("screens.device.settings.deviceLastUpdated")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text style={([AppStyles.typography14], { color: "#ddd" })}>
|
<Text style={([AppStyles.typography14], { color: "#ddd" })}>
|
||||||
11.07.2023 um 20:33 Uhr
|
11.07.2023 um 20:33 Uhr
|
||||||
|
|
|
@ -2,13 +2,17 @@ import { useContext, useState } from "react";
|
||||||
import { Modal, Text, TouchableOpacity, View } from "react-native";
|
import { Modal, Text, TouchableOpacity, View } from "react-native";
|
||||||
import { Picker, Switch } from "react-native-ui-lib";
|
import { Picker, Switch } from "react-native-ui-lib";
|
||||||
import Card from "../../Components/Card";
|
import Card from "../../Components/Card";
|
||||||
import { AppContext, AppStyles } from "../../utils";
|
import { AppContext, AppStyles, Constants } from "../../utils";
|
||||||
import { Divider } from "../../Components/Divider";
|
import { Divider } from "../../Components/Divider";
|
||||||
import Icon from "@expo/vector-icons/MaterialCommunityIcons";
|
import PickerModal from "../../Components/PickerModal";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
export default function SettingsScreen() {
|
export default function SettingsScreen() {
|
||||||
const appContext = useContext(AppContext);
|
const appContext = useContext(AppContext);
|
||||||
const [modalVisible, setModalVisible] = useState(false);
|
const { t } = useTranslation();
|
||||||
|
const [modalAppColorSchemeVisible, setAppColorSchemeModalVisible] =
|
||||||
|
useState(false);
|
||||||
|
const [modalAppLanguageVisible, setModalAppLanguageVisible] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
|
@ -27,33 +31,64 @@ export default function SettingsScreen() {
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Einstellungen
|
{t("screens.settings.settingsCardTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Picker
|
<TouchableOpacity
|
||||||
label="Sprache"
|
onPress={() => setModalAppLanguageVisible(true)}
|
||||||
value={appContext.appLanguage}
|
style={{ marginBottom: 6 }}
|
||||||
onChange={(v) => appContext.setAppLanguage(v)}
|
|
||||||
fieldType={Picker.fieldTypes.settings}
|
|
||||||
showSearch
|
|
||||||
searchPlaceholder="Search a language"
|
|
||||||
searchStyle={{ color: "#fff", placeholderTextColor: "#fff" }}
|
|
||||||
>
|
>
|
||||||
<Picker.Item key={1} label="System default" value={"auto"} />
|
<View
|
||||||
<Picker.Item key={2} label="Deutsch" value={"de"} />
|
style={{
|
||||||
<Picker.Item key={3} label="English" value={"en"} />
|
flexDirection: "row",
|
||||||
</Picker>
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
style={[
|
||||||
|
AppStyles.typography14,
|
||||||
|
{ color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.settings.languageText")}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: appContext.appTheme.colors.primary }}>
|
||||||
|
{
|
||||||
|
Constants.languages.find(
|
||||||
|
(language) => language.name === appContext.appLanguage
|
||||||
|
).label
|
||||||
|
}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
<Picker
|
<TouchableOpacity onPress={() => setAppColorSchemeModalVisible(true)}>
|
||||||
label="Anzeigemodus"
|
<View
|
||||||
value={appContext.appColorScheme}
|
style={{
|
||||||
onChange={(v) => appContext.setAppColorScheme(v)}
|
flexDirection: "row",
|
||||||
fieldType={Picker.fieldTypes.settings}
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Picker.Item key={1} label="System default" value={"auto"} />
|
<Text
|
||||||
<Picker.Item key={2} label="Dark" value={"dark"} />
|
style={[
|
||||||
<Picker.Item key={3} label="Light" value={"light"} />
|
AppStyles.typography14,
|
||||||
</Picker>
|
{ color: appContext.appTheme.text },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("screens.settings.appColorSchemeText")}
|
||||||
|
</Text>
|
||||||
|
<Text style={{ color: appContext.appTheme.colors.primary }}>
|
||||||
|
{appContext.appColorScheme === "auto"
|
||||||
|
? t("screens.settings.appColorSchemePicker.auto")
|
||||||
|
: appContext.appColorScheme === "dark"
|
||||||
|
? t("screens.settings.appColorSchemePicker.dark")
|
||||||
|
: t("screens.settings.appColorSchemePicker.light")}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
|
@ -69,7 +104,7 @@ export default function SettingsScreen() {
|
||||||
{ color: appContext.appTheme.text },
|
{ color: appContext.appTheme.text },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Experten Modus
|
{t("screens.settings.expertModeTitle")}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={[
|
style={[
|
||||||
|
@ -77,9 +112,7 @@ export default function SettingsScreen() {
|
||||||
{ color: appContext.appTheme.textSecondary },
|
{ color: appContext.appTheme.textSecondary },
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
Durch das Einschalten werden zusätzliche Funktionen in der App
|
{t("screens.settings.expertModeDescription")}
|
||||||
freigeschaltet, wie beispielsweise die Möglichkeit,
|
|
||||||
benutzerdefinierte Farbcodes anzugeben.
|
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
<Switch
|
<Switch
|
||||||
|
@ -106,108 +139,38 @@ export default function SettingsScreen() {
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<TouchableOpacity onPress={() => setModalVisible(true)}>
|
<PickerModal
|
||||||
<View
|
isOpen={modalAppColorSchemeVisible}
|
||||||
style={{
|
setIsOpen={setAppColorSchemeModalVisible}
|
||||||
flexDirection: "row",
|
items={[
|
||||||
alignItems: "center",
|
{
|
||||||
justifyContent: "space-between",
|
label: t("screens.settings.appColorSchemePicker.auto"),
|
||||||
}}
|
onPress: () => appContext.setAppColorScheme("auto"),
|
||||||
>
|
},
|
||||||
<Text style={{ color: appContext.appTheme.text }}>
|
{
|
||||||
Anzeigemodus
|
label: t("screens.settings.appColorSchemePicker.dark"),
|
||||||
</Text>
|
onPress: () => appContext.setAppColorScheme("dark"),
|
||||||
<Text style={{ color: appContext.appTheme.colors.primary }}>
|
selected: appContext.appColorScheme === "dark",
|
||||||
{appContext.appColorScheme}
|
},
|
||||||
</Text>
|
{
|
||||||
</View>
|
label: t("screens.settings.appColorSchemePicker.light"),
|
||||||
</TouchableOpacity>
|
onPress: () => appContext.setAppColorScheme("light"),
|
||||||
|
selected: appContext.appColorScheme === "light",
|
||||||
<Modal
|
},
|
||||||
visible={modalVisible}
|
]}
|
||||||
animationType="slide"
|
|
||||||
onRequestClose={() => {
|
|
||||||
setModalVisible(!modalVisible);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TouchableOpacity onPress={() => setModalVisible(false)}>
|
|
||||||
<Icon
|
|
||||||
name="window-close"
|
|
||||||
size={24}
|
|
||||||
style={{ marginLeft: 10, marginTop: 20, marginBottom: 20 }}
|
|
||||||
/>
|
/>
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<Text style={[AppStyles.typography16, { marginLeft: 20 }]}>
|
<PickerModal
|
||||||
System default
|
isOpen={modalAppLanguageVisible}
|
||||||
</Text>
|
setIsOpen={setModalAppLanguageVisible}
|
||||||
|
items={Constants.languages.map((language) => {
|
||||||
<Divider />
|
return {
|
||||||
|
label: language.label,
|
||||||
{appContext.appColorScheme === "dark" ? (
|
onPress: () => appContext.setAppLanguage(language.name),
|
||||||
<TouchableOpacity onPress={() => setModalVisible(false)}>
|
selected: appContext.appLanguage === language.name,
|
||||||
<View
|
};
|
||||||
style={{
|
})}
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginLeft: 20,
|
|
||||||
marginRight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text style={[AppStyles.typography16]}>Dark</Text>
|
|
||||||
<Icon
|
|
||||||
name="check"
|
|
||||||
size={24}
|
|
||||||
color={appContext.appTheme.colors.primary}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
) : (
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => {
|
|
||||||
setModalVisible(false);
|
|
||||||
appContext.setAppColorScheme("dark");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text style={[AppStyles.typography16, { marginLeft: 20 }]}>
|
|
||||||
Dark
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Divider />
|
|
||||||
|
|
||||||
{appContext.appColorScheme === "light" ? (
|
|
||||||
<TouchableOpacity onPress={() => setModalVisible(false)}>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginLeft: 20,
|
|
||||||
marginRight: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text style={[AppStyles.typography16]}>Light</Text>
|
|
||||||
<Icon
|
|
||||||
name="check"
|
|
||||||
size={24}
|
|
||||||
color={appContext.appTheme.colors.primary}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
) : (
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => {
|
|
||||||
setModalVisible(false);
|
|
||||||
appContext.setAppColorScheme("light");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text style={[AppStyles.typography16, { marginLeft: 20 }]}>
|
|
||||||
Light
|
|
||||||
</Text>
|
|
||||||
</TouchableOpacity>
|
|
||||||
)}
|
|
||||||
</Modal>
|
|
||||||
</Card>
|
</Card>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
30
src/utils.js
30
src/utils.js
|
@ -1,10 +1,20 @@
|
||||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||||
import { createContext, useState } from "react";
|
import { createContext, useState } from "react";
|
||||||
import { StyleSheet } from "react-native";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Colors } from "react-native-ui-lib";
|
import { Appearance, StyleSheet } from "react-native";
|
||||||
|
|
||||||
export const Constants = {
|
export const Constants = {
|
||||||
defaultLanguage: "de",
|
defaultLanguage: "de",
|
||||||
|
languages: [
|
||||||
|
{
|
||||||
|
name: "de",
|
||||||
|
label: "Deutsch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "en",
|
||||||
|
label: "English",
|
||||||
|
},
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AppStyles = StyleSheet.create({
|
export const AppStyles = StyleSheet.create({
|
||||||
|
@ -45,7 +55,7 @@ const DarkAppTheme = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
divider: "#ddd",
|
divider: "#ddd",
|
||||||
icon: "#fff",
|
icon: "#ddd",
|
||||||
};
|
};
|
||||||
|
|
||||||
const LightAppTheme = {
|
const LightAppTheme = {
|
||||||
|
@ -122,23 +132,23 @@ export function AppProvider({ children }) {
|
||||||
// TODO: only while development
|
// TODO: only while development
|
||||||
const [isUserDeveloperModeEnabled, setIsUserDeveloperModeEnabled] =
|
const [isUserDeveloperModeEnabled, setIsUserDeveloperModeEnabled] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const { i18n } = useTranslation();
|
||||||
|
|
||||||
const saveAppColorScheme = async (value) => {
|
const saveAppColorScheme = async (value) => {
|
||||||
StoreData("appColorScheme", value);
|
StoreData("appColorScheme", value);
|
||||||
setAppColorScheme(value);
|
setAppColorScheme(value);
|
||||||
|
|
||||||
if (value === "dark") {
|
let colorScheme;
|
||||||
setAppTheme(DarkAppTheme);
|
|
||||||
console.log("dark");
|
colorScheme = value === "auto" ? Appearance.getColorScheme() : value;
|
||||||
} else {
|
|
||||||
setAppTheme(LightAppTheme);
|
setAppTheme(colorScheme === "light" ? LightAppTheme : DarkAppTheme);
|
||||||
console.log("light");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveAppLanguage = async (value) => {
|
const saveAppLanguage = async (value) => {
|
||||||
StoreData("appLanguage", value);
|
StoreData("appLanguage", value);
|
||||||
setAppLanguage(value);
|
setAppLanguage(value);
|
||||||
|
i18n.changeLanguage(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveUserExpertMode = async (value) => {
|
const saveUserExpertMode = async (value) => {
|
||||||
|
|
Loading…
Reference in New Issue