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