Lots of changes
- internationalization - new logo - connection screen improved - always try provisioning IP for connection
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
@@ -8,37 +8,59 @@ import {
|
||||
} from "react-native";
|
||||
|
||||
import SetupView from '../components/SetupView';
|
||||
import EvilIcon from "react-native-vector-icons/EvilIcons";
|
||||
import { connect } from 'react-redux';
|
||||
import { changeSwimTrackerHostname } from '../state/Reducer';
|
||||
import i18n from 'i18n-js';
|
||||
|
||||
const validHostnameRegex = /((^\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\s*$)|(^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$))|(^\s*((?=.{1,255}$)(?=.*[A-Za-z].*)[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|\b-){0,61}[0-9A-Za-z])?)*)\s*$)/;
|
||||
|
||||
function isValidHostname(hostname) {
|
||||
return validHostnameRegex.test(hostname);
|
||||
}
|
||||
|
||||
function ConnectingView(props) {
|
||||
|
||||
const [isHostnameValid, setIsHostnameValid] = useState(isValidHostname(props.swimTrackerHost));
|
||||
const [hostnameTextInput, setHostnameTextInput] = useState(props.swimTrackerHost);
|
||||
const [advancedMode, setAdvancedMode] = useState(false);
|
||||
|
||||
|
||||
let onHostnameChange = newHostName => {
|
||||
props.dispatch(changeSwimTrackerHostname(newHostName));
|
||||
setHostnameTextInput(newHostName);
|
||||
const newHostnameValid = isValidHostname(newHostName);
|
||||
setIsHostnameValid(newHostnameValid);
|
||||
if (newHostnameValid) {
|
||||
props.dispatch(changeSwimTrackerHostname(newHostName));
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const hiddenStyle = advancedMode ? {} : {"display": "none"};
|
||||
|
||||
return (
|
||||
<SetupView
|
||||
headerText="Connecting..."
|
||||
lowerLeftButtonText="Advanced Setup"
|
||||
lowerRightButtonText="Need help?"
|
||||
headerText={i18n.t("connecting") + "..."}
|
||||
lowerLeftButtonText={ i18n.t(advancedMode ? 'simpleMode' : 'advancedMode') }
|
||||
onLowerLeftButtonPress={() => { setAdvancedMode(!advancedMode); }}
|
||||
lowerRightButtonText={i18n.t('help')}
|
||||
>
|
||||
<View style={{flexDirection: "row", alignItems: "center"}}>
|
||||
<ActivityIndicator size="large" color="#ffffff" />
|
||||
<Text style={styles.subtext}>
|
||||
Please connect your phone to the WiFi of your SwimTracker
|
||||
{i18n.t('connectSubtext')}
|
||||
</Text>
|
||||
<View style={styles.row}>
|
||||
<EvilIcon name="archive" style={styles.hostIcon}></EvilIcon>
|
||||
<TextInput
|
||||
onChangeText={onHostnameChange}
|
||||
value={props.swimTrackerHost}
|
||||
style={styles.hostnameInput}
|
||||
placeholder="Hostname/IP"
|
||||
placeholderTextColor="rgba(255,255,255,0.5)"
|
||||
></TextInput>
|
||||
</View>
|
||||
{true &&
|
||||
<View style={StyleSheet.flatten([styles.row, hiddenStyle])}>
|
||||
<Text style={styles.label}>Host:</Text>
|
||||
<TextInput
|
||||
onChangeText={onHostnameChange}
|
||||
value={hostnameTextInput}
|
||||
style={{ ...styles.hostnameInput, color: isHostnameValid ? "rgb(255, 255, 255)" : "rgb(255, 150, 150)" }}
|
||||
placeholderTextColor="rgba(255,255,255,0.5)"
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
</SetupView>
|
||||
)
|
||||
}
|
||||
@@ -46,32 +68,33 @@ function ConnectingView(props) {
|
||||
const styles = StyleSheet.create({
|
||||
subtext: {
|
||||
color: "rgba(255,255,255,1)",
|
||||
textAlign: "center",
|
||||
fontSize: 18,
|
||||
textAlign: "left",
|
||||
fontSize: 16,
|
||||
lineHeight: 25,
|
||||
width: "80%",
|
||||
width: "100%",
|
||||
//paddingTop: 50,
|
||||
paddingLeft: 30,
|
||||
},
|
||||
row: {
|
||||
backgroundColor: "rgba(255,255,255,0.4)",
|
||||
borderRadius: 5,
|
||||
width: "80%",
|
||||
width: "100%",
|
||||
height: 50,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
marginTop: 60,
|
||||
marginBottom: 5,
|
||||
},
|
||||
hostIcon: {
|
||||
fontSize: 25,
|
||||
color: "rgba(255,255,255,1)",
|
||||
marginLeft: 15,
|
||||
marginRight: 15,
|
||||
},
|
||||
hostnameInput: {
|
||||
height: 30,
|
||||
color: "rgba(255,255,255,1)",
|
||||
width: "80%",
|
||||
fontSize: 18,
|
||||
},
|
||||
label : {
|
||||
color: "rgb(80, 80, 80)",
|
||||
marginLeft: 15,
|
||||
marginRight: 10,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ class LastSessionsView extends React.Component {
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<StatusBar hidden={true} />
|
||||
<StatusBar barStyle="light-content" backgroundColor="rgba(0,0,0,0.4)" translucent={true} />
|
||||
<View style={{ flex: 1 }}>
|
||||
<ImageHeader
|
||||
text="LETZTE SESSIONS"
|
||||
|
||||
@@ -12,10 +12,8 @@ import MaterialIcon from "react-native-vector-icons/MaterialIcons";
|
||||
import MaterialCommIcon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
|
||||
import EntypoIcon from "react-native-vector-icons/Entypo";
|
||||
import FeatherIcon from "react-native-vector-icons/Feather";
|
||||
|
||||
//import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||
|
||||
import i18n from 'i18n-js';
|
||||
|
||||
import { ConnState, startSession } from '../state/DeviceReduxCoupling';
|
||||
import { connect } from 'react-redux';
|
||||
@@ -41,7 +39,6 @@ const largeHeaderStyles = StyleSheet.create({
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
paddingBottom: 10,
|
||||
//alignContent: "space-between"
|
||||
},
|
||||
titleText: {
|
||||
color: "rgba(255,255,255,1)",
|
||||
@@ -72,17 +69,18 @@ function ButtonGrid(props) {
|
||||
activeOpacity={0.6}
|
||||
>
|
||||
<MaterialCommIcon name="swim" style={buttonGridStyles.icon}></MaterialCommIcon>
|
||||
<Text style={buttonGridStyles.buttonText}>{"LETZTE\nSESSIONS"}</Text>
|
||||
<Text style={buttonGridStyles.buttonText}>{ i18n.t('mainMenu_lastSessions').toUpperCase().split(" ").join("\n") }</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<View style={buttonGridStyles.columnContainer}>
|
||||
<TouchableOpacity
|
||||
onPress={props.onSocialPress}
|
||||
style={[{ backgroundColor: themeColors["MIDNIGHT BLUE"] }, buttonGridStyles.button]}
|
||||
style={[{ backgroundColor: "#444" }, buttonGridStyles.button]}
|
||||
activeOpacity={0.6}
|
||||
disabled={true}
|
||||
>
|
||||
<MaterialCommIcon name="account-group" style={buttonGridStyles.icon}></MaterialCommIcon>
|
||||
<Text style={buttonGridStyles.buttonText}>SOCIAL</Text>
|
||||
<Text style={buttonGridStyles.buttonText}>{ i18n.t('mainMenu_social').toUpperCase()}</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
onPress={props.onSettingsPress}
|
||||
@@ -90,7 +88,7 @@ function ButtonGrid(props) {
|
||||
activeOpacity={0.6}
|
||||
>
|
||||
<MaterialIcon name="settings" style={buttonGridStyles.icon}></MaterialIcon>
|
||||
<Text style={buttonGridStyles.buttonText}>EINSTELLUNGEN</Text>
|
||||
<Text style={buttonGridStyles.buttonText}>{ i18n.t('settings').toUpperCase()}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
@@ -193,7 +191,7 @@ const fullWidthButtonStyles = StyleSheet.create({
|
||||
|
||||
function MainMenuView(props) {
|
||||
const s = props.connState;
|
||||
let startButtonText = "JETZT SCHWIMMEN";
|
||||
let startButtonText = i18n.t('mainMenu_swimNow').toUpperCase();
|
||||
let startButtonDisabled = false;
|
||||
if (s === ConnState.DISCONNECTED) {
|
||||
startButtonText = "NICHT VERBUNDEN";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
@@ -12,6 +12,9 @@ import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import EntypoIcon from "react-native-vector-icons/Entypo";
|
||||
import ImageHeader from "../components/ImageHeader";
|
||||
import { connect } from 'react-redux';
|
||||
import { TouchableOpacity } from "react-native-gesture-handler";
|
||||
import request from '../utility/PromiseRequest';
|
||||
import i18n from 'i18n-js';
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
@@ -51,6 +54,29 @@ function SettingsSwitch(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function SettingsButton(props) {
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Text style={settingsGroupStyles.label}>{props.label}</Text>
|
||||
<TouchableOpacity style={settingsGroupStyles.buttonTouchable} onPress={props.onPress}>
|
||||
<Text style={settingsGroupStyles.buttonText}>{props.buttonText}</Text>
|
||||
</TouchableOpacity>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
function SettingsText(props) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Text style={settingsGroupStyles.label}>{props.label}</Text>
|
||||
<Text style={settingsGroupStyles.text}>{props.text}</Text>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
function SettingsSlider(props) {
|
||||
/*
|
||||
<Slider
|
||||
@@ -136,20 +162,65 @@ const settingsGroupStyles = StyleSheet.create({
|
||||
switch: {
|
||||
//minHeight: 50,
|
||||
//minWidth: 80,
|
||||
},
|
||||
buttonText: {
|
||||
color: "rgba(255,255,255,1)",
|
||||
width: "100%",
|
||||
textAlign: "center",
|
||||
},
|
||||
text : {
|
||||
color: "rgba(255,255,255,1)",
|
||||
width: "100%",
|
||||
textAlign: "right",
|
||||
},
|
||||
buttonTouchable: {
|
||||
backgroundColor: themeColors["CARROT"],
|
||||
width: 128,
|
||||
padding: 10,
|
||||
justifyContent: "center",
|
||||
borderRadius: 4,
|
||||
}
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
async function queryDeviceFirmwareVersion(swimTrackerHost) {
|
||||
const result = await request({ url: "http://" + swimTrackerHost + "/api/status", responseType: "json" });
|
||||
return result["firmware"]["version"];
|
||||
}
|
||||
|
||||
async function queryNewestFirmwareVersion() {
|
||||
const QUERY_URL = "https://swimtracker-update.bauer.tech/VERSION";
|
||||
const result = await request({ url: QUERY_URL, responseType: "text" });
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function SettingsView(props) {
|
||||
console.log("settings props", props);
|
||||
|
||||
const [deviceFirmwareVersion, setDeviceFirmwareVersion] = useState("");
|
||||
const [newestFirmwareVersion, setNewestFirmwareVersion] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([queryDeviceFirmwareVersion(props.settings.swimTrackerHost), queryNewestFirmwareVersion()]).then(
|
||||
(values) => {
|
||||
setDeviceFirmwareVersion(values[0]);
|
||||
setNewestFirmwareVersion(values[1]);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
const doFirmwareUpdate = () => {
|
||||
request({ url: "http://" + props.settings.swimTrackerHost + "/api/firmwareupdate", responseType: "text"});
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1 }}>
|
||||
<StatusBar hidden={true} />
|
||||
<StatusBar barStyle="light-content" backgroundColor="rgba(0,0,0,0.4)" translucent={true} />
|
||||
<View style={{ flex: 1 }}>
|
||||
<ImageHeader
|
||||
text="EINSTELLUNGEN"
|
||||
text={i18n.t('settings').toUpperCase()}
|
||||
navigation={props.navigation}
|
||||
image={require("../assets/infinity_pool2.jpg")}
|
||||
/>
|
||||
@@ -163,6 +234,11 @@ function SettingsView(props) {
|
||||
/>
|
||||
<SettingsSwitch label="Start automatically" />
|
||||
<SettingsSwitch label="Stop automatically" />
|
||||
<SettingsButton label="Tare" buttonText="GO" onPress={props.device.conn.sendTareCommand} />
|
||||
<SettingsButton label="WiFi config" buttonText="Reset" onPress={props.device.conn.wifiResetToProvisioning} />
|
||||
<SettingsText label="Firmware version" text={deviceFirmwareVersion}></SettingsText>
|
||||
<SettingsText label="Newest Firmware" text={newestFirmwareVersion}></SettingsText>
|
||||
<SettingsButton label="Update Firmware" buttonText="GO" onPress={doFirmwareUpdate}></SettingsButton>
|
||||
</SettingsGroup>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -9,6 +9,8 @@ import {
|
||||
} from "react-native";
|
||||
import SetupView from '../components/SetupView';
|
||||
import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { connect } from 'react-redux';
|
||||
import { changeSwimTrackerHostname } from '../state/Reducer';
|
||||
|
||||
|
||||
function WifiListElement(props) {
|
||||
@@ -129,7 +131,11 @@ class WifiSelectionView extends React.Component {
|
||||
buttonText: "OK",
|
||||
subText: "Please enter the password for your home WiFi",
|
||||
onSubmit: (ssid, pw) => {
|
||||
console.log("1");
|
||||
this.props.device.conn.wifiSetModeSTA(ssid, pw);
|
||||
console.log("2", this.props.deviceReportedHostname, changeSwimTrackerHostname, this.props);
|
||||
this.props.dispatch(changeSwimTrackerHostname(this.props.deviceReportedHostname));
|
||||
console.log("3");
|
||||
},
|
||||
});
|
||||
}}>
|
||||
@@ -181,4 +187,8 @@ const styles = StyleSheet.create({
|
||||
}
|
||||
});
|
||||
|
||||
export default WifiSelectionView;
|
||||
const mapStateToProps = (state) => {
|
||||
return { deviceReportedHostname: state.deviceState.deviceReportedHostname };
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(WifiSelectionView);
|
||||
Reference in New Issue
Block a user