New views
This commit is contained in:
parent
aee89d799c
commit
4544f19938
11
App.js
11
App.js
|
@ -10,11 +10,9 @@ import { DeviceReduxCoupling } from './state/DeviceReduxCoupling';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import ThemedStackNavigation from './components/ThemedStackNavigation';
|
import ThemedStackNavigation from './components/ThemedStackNavigation';
|
||||||
|
import NewAppMain from "./components/NewAppMain";
|
||||||
|
|
||||||
const store = createStore(swimtrackerReducer);
|
const store = createStore(swimtrackerReducer);
|
||||||
//const deviceReduxCoupling = new DeviceReduxCoupling(store);
|
|
||||||
|
|
||||||
|
|
||||||
export default class App extends React.Component {
|
export default class App extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -38,11 +36,16 @@ export default class App extends React.Component {
|
||||||
if (!this.state.isReady) {
|
if (!this.state.isReady) {
|
||||||
return <AppLoading />;
|
return <AppLoading />;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
return (
|
return (
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ThemedStackNavigation />
|
<ThemedStackNavigation />
|
||||||
</Provider>
|
</Provider>
|
||||||
|
);*/
|
||||||
|
return (
|
||||||
|
<Provider store={store}>
|
||||||
|
<NewAppMain />
|
||||||
|
</Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 253 KiB |
Binary file not shown.
After Width: | Height: | Size: 340 KiB |
Binary file not shown.
After Width: | Height: | Size: 740 KiB |
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { NavigationContainer } from '@react-navigation/native';
|
||||||
|
import { createStackNavigator } from '@react-navigation/stack';
|
||||||
|
|
||||||
|
// Own views
|
||||||
|
import MainMenuView from "../views/MainMenuView";
|
||||||
|
import SettingsView from "../views/SettingsView";
|
||||||
|
import TrainingView from "../views/TrainingView";
|
||||||
|
|
||||||
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
|
function NewAppMain(props) {
|
||||||
|
|
||||||
|
const screenOptions = {
|
||||||
|
headerShown: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavigationContainer>
|
||||||
|
<Stack.Navigator initialRouteName="Home">
|
||||||
|
<Stack.Screen
|
||||||
|
name="Home"
|
||||||
|
component={MainMenuView}
|
||||||
|
options={screenOptions}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Settings"
|
||||||
|
component={SettingsView}
|
||||||
|
options={screenOptions}
|
||||||
|
/>
|
||||||
|
<Stack.Screen
|
||||||
|
name="Training"
|
||||||
|
component={TrainingView}
|
||||||
|
options={screenOptions}
|
||||||
|
/>
|
||||||
|
</Stack.Navigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewAppMain;
|
|
@ -33,7 +33,6 @@ export default class DataAnalysis {
|
||||||
this.activeMeasurements += newAverages.reduce((n, val) => {
|
this.activeMeasurements += newAverages.reduce((n, val) => {
|
||||||
return n + ((val >= analysisParameters.activeTimeThreshold) ? 1 : 0);
|
return n + ((val >= analysisParameters.activeTimeThreshold) ? 1 : 0);
|
||||||
}, 0);
|
}, 0);
|
||||||
console.log("data", newDataArr, "newAverages", newAverages, "reduction", this.activeMeasurements);
|
|
||||||
|
|
||||||
// peaks
|
// peaks
|
||||||
const newPeaks = this.peakDetectorSimple.addVector(newDataArr);
|
const newPeaks = this.peakDetectorSimple.addVector(newDataArr);
|
||||||
|
@ -63,7 +62,6 @@ export default class DataAnalysis {
|
||||||
peakMaxWindow: peakMaxWindow,
|
peakMaxWindow: peakMaxWindow,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_resetCache(analysisParameters, sessionId) {
|
_resetCache(analysisParameters, sessionId) {
|
||||||
this.movingAverage = analysisParameters ? new MovingAverage(analysisParameters.movingAverageWindowSize) : null;
|
this.movingAverage = analysisParameters ? new MovingAverage(analysisParameters.movingAverageWindowSize) : null;
|
||||||
|
|
|
@ -27,6 +27,7 @@ export const stopSession = () => ({
|
||||||
const INITIAL_SETTINGS = {
|
const INITIAL_SETTINGS = {
|
||||||
theme: "hot",
|
theme: "hot",
|
||||||
username: "",
|
username: "",
|
||||||
|
//swimTrackerHost: "192.168.178.107",
|
||||||
swimTrackerHost: "192.168.178.110",
|
swimTrackerHost: "192.168.178.110",
|
||||||
|
|
||||||
analysis: {
|
analysis: {
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
StatusBar,
|
||||||
|
ImageBackground,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from "react-native";
|
||||||
|
import themeColors from './themeColors';
|
||||||
|
import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
|
import EntypoIcon from "react-native-vector-icons/Entypo";
|
||||||
|
|
||||||
|
import { ConnState, startSession } from '../state/DeviceReduxCoupling';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function LargeHeaderView(props) {
|
||||||
|
return (
|
||||||
|
<View style={largeHeaderStyles.container}>
|
||||||
|
<Text style={largeHeaderStyles.titleText}>swimtracker</Text>
|
||||||
|
<View style={largeHeaderStyles.separator}></View>
|
||||||
|
<Text style={largeHeaderStyles.subText}>bauer.tech</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const largeHeaderStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
height: 160,
|
||||||
|
maxHeight: 160,
|
||||||
|
flex: 1,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
paddingBottom: 10,
|
||||||
|
//alignContent: "space-between"
|
||||||
|
},
|
||||||
|
titleText: {
|
||||||
|
color: "rgba(255,255,255,1)",
|
||||||
|
fontSize: 48,
|
||||||
|
},
|
||||||
|
subText: {
|
||||||
|
color: "rgba(255,255,255, 0.8)",
|
||||||
|
marginTop: 15,
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
separator: {
|
||||||
|
height: 7,
|
||||||
|
backgroundColor: "rgba(255,255,255,1)",
|
||||||
|
opacity: 0.5,
|
||||||
|
width: 230
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function ButtonGrid(props) {
|
||||||
|
return (
|
||||||
|
<View style={buttonGridStyles.rowContainer}>
|
||||||
|
<View style={buttonGridStyles.columnContainer}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={props.onLastSessionsPress}
|
||||||
|
style={[{ backgroundColor: themeColors["GREEN SEA"] }, buttonGridStyles.button]}
|
||||||
|
activeOpacity={0.6}
|
||||||
|
>
|
||||||
|
<MaterialIcon name="swim" style={buttonGridStyles.icon}></MaterialIcon>
|
||||||
|
<Text style={buttonGridStyles.buttonText}>{"LETZTE\nSESSIONS"}</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
<View style={buttonGridStyles.columnContainer}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={props.onSocialPress}
|
||||||
|
style={[{ backgroundColor: themeColors["MIDNIGHT BLUE"] }, buttonGridStyles.button]}
|
||||||
|
activeOpacity={0.6}
|
||||||
|
>
|
||||||
|
<MaterialIcon name="account-group" style={buttonGridStyles.icon}></MaterialIcon>
|
||||||
|
<Text style={buttonGridStyles.buttonText}>SOCIAL</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={props.onSettingsPress}
|
||||||
|
style={[{ backgroundColor: themeColors["MIDNIGHT BLUE"] }, buttonGridStyles.button]}
|
||||||
|
activeOpacity={0.6}
|
||||||
|
>
|
||||||
|
<MaterialIcon name="settings-outline" style={buttonGridStyles.icon}></MaterialIcon>
|
||||||
|
<Text style={buttonGridStyles.buttonText}>EINSTELLUNGEN</Text>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonGridStyles = StyleSheet.create({
|
||||||
|
rowContainer: {
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "column",
|
||||||
|
justifyContent: "space-around",
|
||||||
|
alignItems: "center",
|
||||||
|
paddingTop: 20,
|
||||||
|
paddingBottom: 50,
|
||||||
|
},
|
||||||
|
columnContainer: {
|
||||||
|
flex: 1,
|
||||||
|
width: "100%",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-around",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
flex: 1,
|
||||||
|
margin: 20,
|
||||||
|
padding: 20,
|
||||||
|
width: 120,
|
||||||
|
height: 130,
|
||||||
|
borderRadius: 10,
|
||||||
|
opacity: 0.95,
|
||||||
|
justifyContent: "space-around",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
color: "rgba(255,255,255,1)",
|
||||||
|
textAlign: "center",
|
||||||
|
fontSize: 16,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
color: "rgba(255,255,255,1)",
|
||||||
|
fontSize: 60,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function FullWidthButton(props) {
|
||||||
|
let textStyle = [fullWidthButtonStyles.buttonText];
|
||||||
|
let iconStyle = [fullWidthButtonStyles.icon];
|
||||||
|
if (props.disabled) {
|
||||||
|
textStyle.push(fullWidthButtonStyles.buttonTextDisabled);
|
||||||
|
iconStyle.push(fullWidthButtonStyles.iconDisabled);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={props.onPress}
|
||||||
|
style={fullWidthButtonStyles.container}
|
||||||
|
disabled={props.disabled}
|
||||||
|
activeOpacity={0.6}>
|
||||||
|
<View style={{ flex: 1, flexDirection: "row", justifyContent: "center" }}>
|
||||||
|
<EntypoIcon name="air" style={iconStyle}></EntypoIcon>
|
||||||
|
<Text style={textStyle}>{props.text}</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fullWidthButtonStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
maxHeight: 70,
|
||||||
|
backgroundColor: themeColors["WET ASPHALT"],
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
//paddingBottom: 10,
|
||||||
|
justifyContent: "center",
|
||||||
|
},
|
||||||
|
buttonText: {
|
||||||
|
padding: 10,
|
||||||
|
color: "rgba(255,255,255,1)",
|
||||||
|
fontSize: 25,
|
||||||
|
fontWeight: "600",
|
||||||
|
textAlign: "center",
|
||||||
|
},
|
||||||
|
buttonTextDisabled: {
|
||||||
|
opacity: 0.3,
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
fontSize: 40,
|
||||||
|
padding: 10,
|
||||||
|
color: themeColors["GREEN SEA"],
|
||||||
|
},
|
||||||
|
iconDisabled: {
|
||||||
|
color: themeColors["POMEGRANATE"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function MainMenuView(props) {
|
||||||
|
const s = props.connState;
|
||||||
|
let startButtonText = "JETZT SCHWIMMEN";
|
||||||
|
let startButtonDisabled = false;
|
||||||
|
if (s === ConnState.DISCONNECTED) {
|
||||||
|
startButtonText = "NICHT VERBUNDEN";
|
||||||
|
startButtonDisabled = true;
|
||||||
|
} else if (s === ConnState.CONNECTED_RUNNING || s === ConnState.CONNECTED_STARTING) {
|
||||||
|
startButtonText = "TRAINING LÄUFT";
|
||||||
|
} else if (s === ConnState.CONNECTED_STOPPING) {
|
||||||
|
startButtonDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onStartButtonPress = () => {
|
||||||
|
if (!props.connState !== ConnState.CONNECTED_RUNNING) {
|
||||||
|
props.dispatch(startSession());
|
||||||
|
}
|
||||||
|
props.navigation.navigate('Training')
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<StatusBar barStyle="light-content" backgroundColor="rgba(0,0,0,0.4)" translucent={true} />
|
||||||
|
<ImageBackground
|
||||||
|
source={require("../assets/pool_sky_background_blurred.jpg")}
|
||||||
|
resizeMode="cover"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
>
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<LargeHeaderView />
|
||||||
|
<ButtonGrid onSettingsPress={() => props.navigation.navigate('Settings')} />
|
||||||
|
<FullWidthButton
|
||||||
|
onPress={onStartButtonPress}
|
||||||
|
text={startButtonText}
|
||||||
|
disabled={startButtonDisabled} />
|
||||||
|
</View>
|
||||||
|
</ImageBackground>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return { connState: state.deviceState.connState };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(MainMenuView);
|
|
@ -0,0 +1,207 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
StatusBar,
|
||||||
|
TextInput,
|
||||||
|
ImageBackground,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
SafeAreaView,
|
||||||
|
Slider,
|
||||||
|
Switch,
|
||||||
|
} from "react-native";
|
||||||
|
import themeColors from './themeColors';
|
||||||
|
import MaterialIcon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
|
import EntypoIcon from "react-native-vector-icons/Entypo";
|
||||||
|
|
||||||
|
|
||||||
|
function ImageHeader(props) {
|
||||||
|
return (
|
||||||
|
<View style={imageHeaderStyles.container}>
|
||||||
|
<ImageBackground
|
||||||
|
source={require("../assets/infinity_pool2.jpg")}
|
||||||
|
resizeMode="cover"
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
>
|
||||||
|
<View style={imageHeaderStyles.row}>
|
||||||
|
<TouchableOpacity onPress={() => props.navigation.goBack()}>
|
||||||
|
<EntypoIcon name="chevron-left" style={imageHeaderStyles.icon}></EntypoIcon>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={imageHeaderStyles.text}>{props.text}</Text>
|
||||||
|
</View>
|
||||||
|
</ImageBackground>
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageHeaderStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
minHeight: 175,
|
||||||
|
maxHeight: 175,
|
||||||
|
height: 175,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
paddingTop: 30,
|
||||||
|
flexDirection: "row",
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 40,
|
||||||
|
paddingRight: 10,
|
||||||
|
paddingLeft: 10,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 30,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function SettingsTextInput(props) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Text style={settingsGroupStyles.label}>{props.label}</Text>
|
||||||
|
<TextInput
|
||||||
|
style={settingsGroupStyles.textInput}
|
||||||
|
placeholder={props.placeholder}
|
||||||
|
placeholderTextColor="rgba(167,167,167,1)"
|
||||||
|
selectionColor='rgb(120,120,120)'
|
||||||
|
></TextInput>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function SettingsSwitch(props) {
|
||||||
|
const [isEnabled, setIsEnabled] = useState(false);
|
||||||
|
const toggleSwitch = () => setIsEnabled(previousState => !previousState);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Text style={settingsGroupStyles.label}>{props.label}</Text>
|
||||||
|
<Switch
|
||||||
|
value={isEnabled}
|
||||||
|
//thumbColor={themeColors["WET ASPHALT"]}
|
||||||
|
onValueChange={toggleSwitch}
|
||||||
|
trackColor={{ false: "#767577", true: themeColors["NEPHRITIS"] }}
|
||||||
|
//thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
|
||||||
|
ios_backgroundColor="grey"
|
||||||
|
style={settingsGroupStyles.switch}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SettingsSlider(props) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Text style={settingsGroupStyles.label}>{props.label}</Text>
|
||||||
|
<Slider
|
||||||
|
value={props.value}
|
||||||
|
disabled={props.disabled}
|
||||||
|
thumbTintColor={themeColors["WET ASPHALT"]}
|
||||||
|
minimumTrackTintColor={themeColors["CLOUDS"]}
|
||||||
|
maximumTrackTintColor={themeColors["CLOUDS"]}
|
||||||
|
style={settingsGroupStyles.slider}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function SettingsCombo(props) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function SettingsGroup(props) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={settingsGroupStyles.container}>
|
||||||
|
<Text style={settingsGroupStyles.title}>{props.title}</Text>
|
||||||
|
<View style={settingsGroupStyles.subsettings}>
|
||||||
|
{React.Children.map(props.children, (child, idx) =>
|
||||||
|
<View style={idx == 0 ? [settingsGroupStyles.row, settingsGroupStyles.firstRow] : settingsGroupStyles.row}>
|
||||||
|
{child}
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const settingsGroupStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
padding: 20,
|
||||||
|
paddingRight: 30,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: "600",
|
||||||
|
},
|
||||||
|
subsettings: {
|
||||||
|
padding: 10,
|
||||||
|
paddingLeft: 30,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
borderTopColor: "rgba(255, 255,255, 0.6)",
|
||||||
|
paddingTop: 5,
|
||||||
|
paddingBottom: 5,
|
||||||
|
borderTopWidth: 0.5,
|
||||||
|
minHeight: 40,
|
||||||
|
},
|
||||||
|
firstRow: {
|
||||||
|
paddingTop: 0,
|
||||||
|
borderTopWidth: 0,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 17,
|
||||||
|
},
|
||||||
|
textInput: {
|
||||||
|
color: "rgba(255,255,255,1)",
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
slider: {
|
||||||
|
minWidth: 100,
|
||||||
|
width: 150,
|
||||||
|
//minHeight: 50,
|
||||||
|
},
|
||||||
|
switch: {
|
||||||
|
//minHeight: 50,
|
||||||
|
//minWidth: 80,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
function SettingsView(props) {
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<StatusBar hidden={true} />
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<ImageHeader text="EINSTELLUNGEN" navigation={props.navigation} />
|
||||||
|
<View style={{ flex: 1, backgroundColor: themeColors["BELIZE HOLE"] }}>
|
||||||
|
<SettingsGroup title="swimtracker Device">
|
||||||
|
<SettingsTextInput
|
||||||
|
label="URL/IP"
|
||||||
|
placeholder="192.168.178.??"
|
||||||
|
/>
|
||||||
|
<SettingsSwitch
|
||||||
|
label="SomeSwitch"
|
||||||
|
/>
|
||||||
|
</SettingsGroup>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SettingsView;
|
|
@ -0,0 +1,132 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import {
|
||||||
|
StyleSheet,
|
||||||
|
View,
|
||||||
|
StatusBar,
|
||||||
|
Text,
|
||||||
|
TouchableOpacity,
|
||||||
|
SafeAreaView
|
||||||
|
} from "react-native";
|
||||||
|
import themeColors from './themeColors';
|
||||||
|
import EntypoIcon from "react-native-vector-icons/Entypo";
|
||||||
|
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { useKeepAwake } from 'expo-keep-awake';
|
||||||
|
import { stopSession } from '../state/DeviceReduxCoupling';
|
||||||
|
import CycleView from '../components/CycleView';
|
||||||
|
import IconCard from '../components/IconCard';
|
||||||
|
import Graph from '../components/Graph';
|
||||||
|
|
||||||
|
|
||||||
|
function SmallHeaderView(props) {
|
||||||
|
return (
|
||||||
|
<View style={smallHeaderStyles.container}>
|
||||||
|
<View style={smallHeaderStyles.row}>
|
||||||
|
<TouchableOpacity onPress={() => props.navigation.goBack()}>
|
||||||
|
<EntypoIcon name="chevron-left" style={smallHeaderStyles.backIcon}></EntypoIcon>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<Text style={smallHeaderStyles.text}>{props.text}</Text>
|
||||||
|
<TouchableOpacity onPress={props.onStopPressed}>
|
||||||
|
<EntypoIcon name="controller-stop" style={smallHeaderStyles.stopIcon}></EntypoIcon>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const smallHeaderStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
minHeight: 80,
|
||||||
|
maxHeight: 80,
|
||||||
|
height: 80,
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: themeColors["WET ASPHALT"],
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
paddingTop: 30,
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
},
|
||||||
|
backIcon: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 40,
|
||||||
|
},
|
||||||
|
stopIcon: {
|
||||||
|
color: themeColors["ALIZARIN"],
|
||||||
|
fontSize: 40,
|
||||||
|
paddingRight: 10,
|
||||||
|
paddingLeft: 10,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
color: "white",
|
||||||
|
fontSize: 30,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const toTimeStr = seconds => {
|
||||||
|
let minuteStr = String(Math.floor(seconds / 60));
|
||||||
|
if (minuteStr.length < 2)
|
||||||
|
minuteStr = "0" + minuteStr;
|
||||||
|
let secondStr = String(Math.floor(seconds % 60));
|
||||||
|
if (secondStr.length < 2)
|
||||||
|
secondStr = "0" + secondStr;
|
||||||
|
return minuteStr + ":" + secondStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function TrainingView(props) {
|
||||||
|
useKeepAwake();
|
||||||
|
|
||||||
|
const analysis = props.session.analysis;
|
||||||
|
const laps = (analysis.peaks.size / props.peaksPerLap).toFixed(1);
|
||||||
|
const totalMomentum = Math.trunc(analysis.totalMomentum * props.kgFactor / 10 / 60);
|
||||||
|
|
||||||
|
const onStopPressed = () => {
|
||||||
|
props.dispatch(stopSession());
|
||||||
|
props.navigation.navigate('Home');
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<StatusBar hidden={true} />
|
||||||
|
<View style={{ flex: 1 }}>
|
||||||
|
<SmallHeaderView text="TRAINING" navigation={props.navigation} onStopPressed={onStopPressed} />
|
||||||
|
<View style={trainingViewStyles.container}>
|
||||||
|
<CycleView>
|
||||||
|
<IconCard label="BAHNEN" value={laps} iconName="retweet" iconType="AntDesign" />
|
||||||
|
<IconCard label="ZÜGE" value={analysis.peaks.size} iconName="dashboard" iconType="AntDesign" />
|
||||||
|
</CycleView>
|
||||||
|
|
||||||
|
<CycleView>
|
||||||
|
<IconCard label="DAUER" value={toTimeStr(analysis.totalTime)} iconName="clock" iconType="FontAwesome5" />
|
||||||
|
<IconCard label="AKTIVE DAUER" value={toTimeStr(analysis.activeTime)} iconName="stopwatch" iconType="FontAwesome5" />
|
||||||
|
</CycleView>
|
||||||
|
<IconCard label="KRAFT" value={totalMomentum} iconName="ruler" iconType="Entypo" />
|
||||||
|
|
||||||
|
<Graph></Graph>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const trainingViewStyles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: themeColors["BELIZE HOLE"],
|
||||||
|
padding: 20,
|
||||||
|
justifyContent: "space-around",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
session: state.deviceState,
|
||||||
|
peaksPerLap: state.settings.analysis.peaksPerLap,
|
||||||
|
theme: state.settings.theme,
|
||||||
|
kgFactor: state.settings.analysis.kgFactor,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default connect(mapStateToProps)(TrainingView);
|
|
@ -0,0 +1,26 @@
|
||||||
|
// https://flatuicolors.com/palette/defo
|
||||||
|
|
||||||
|
const themeColors = {
|
||||||
|
'TURQUOISE': "rgb(26, 188, 156)",
|
||||||
|
"EMERALD": "rgb(46, 204, 113)",
|
||||||
|
"PETER RIVER" : "rgb(52, 152, 219)",
|
||||||
|
"AMETHYST" : "rgb(155, 89, 182)",
|
||||||
|
"WET ASPHALT" : "rgb(52, 73, 94)",
|
||||||
|
"GREEN SEA" : "rgb(22, 160, 133)",
|
||||||
|
"NEPHRITIS" : "rgb(39, 174, 96)",
|
||||||
|
"BELIZE HOLE" : "rgb(41, 128, 185)",
|
||||||
|
"WISTERIA" : "rgb(142, 68, 173)",
|
||||||
|
"MIDNIGHT BLUE" : "rgb(44, 62, 80)",
|
||||||
|
"SUN FLOWER" : "rgb(241, 196, 15)",
|
||||||
|
"CARROT" : "rgb(230, 126, 34)",
|
||||||
|
"ALIZARIN" : "rgb(231, 76, 60)",
|
||||||
|
"CLOUDS" : "rgb(236, 240, 241)",
|
||||||
|
"CONCRETE" : "rgb(149, 165, 166)",
|
||||||
|
"ORANGE" : "rgb(243, 156, 18)",
|
||||||
|
"PUMPKIN" : "rgb(211, 84, 0)",
|
||||||
|
"POMEGRANATE" : "rgb(192, 57, 43)",
|
||||||
|
"SILVER" : "rgb(189, 195, 199)",
|
||||||
|
"ASBESTOS" : "rgb(127, 140, 141)",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default themeColors;
|
Loading…
Reference in New Issue