From 618c9112842720e5200807ad636c78f376e0b084 Mon Sep 17 00:00:00 2001 From: Bhuvneshwar Garg Date: Fri, 1 May 2020 11:27:13 +0530 Subject: [PATCH 1/9] progress timer and installed vector icons and Timer components and worked on suggestions --- android/app/build.gradle | 7 ++ app/components/TimerButton.js | 90 ++++++++++++++++ app/components/TimerComponent.js | 47 --------- app/components/index.js | 4 +- app/config/index.js | 4 +- app/config/vectorIcons.js | 9 ++ app/screens/HomeScreen.js | 21 +++- app/screens/TimerScreen.js | 14 ++- ios/HandWashTimer.xcodeproj/project.pbxproj | 107 ++++++++++++++++++++ ios/HandWashTimer/Info.plist | 4 +- package.json | 3 + 11 files changed, 253 insertions(+), 57 deletions(-) create mode 100644 app/components/TimerButton.js delete mode 100644 app/components/TimerComponent.js create mode 100644 app/config/vectorIcons.js diff --git a/android/app/build.gradle b/android/app/build.gradle index f95f500..183feed 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -77,6 +77,13 @@ import com.android.build.OutputFile * ] */ +project.ext.vectoricons = [ + iconFontNames: ['FontAwesome5_Brands.ttf', + 'FontAwesome5_Regular.ttf', 'FontAwesome5_Solid.ttf', 'Ionicons.ttf'] +] + +apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" + project.ext.react = [ enableHermes: false, // clean and rebuild if changing ] diff --git a/app/components/TimerButton.js b/app/components/TimerButton.js new file mode 100644 index 0000000..3f4a694 --- /dev/null +++ b/app/components/TimerButton.js @@ -0,0 +1,90 @@ +import React, { useState, useEffect } from 'react' +import { View, Text, StyleSheet } from 'react-native' +import config, { colors, vectorIcons } from '../config' +import { AnimatedCircularProgress } from 'react-native-circular-progress' +import { useDispatch } from 'react-redux' +import { addWashTime } from '../state/WashTimeHistory' + +const TimerButton = ({ navigation }) => { + const dispatch = useDispatch() + const timerDefault = config.timerDefault + const [timer, setCounter] = useState(timerDefault) + const [text, setText] = useState('Seconds') + + const timerCounter = () => setCounter(timer - 1) + + useEffect(() => { + if (timer <= 0) { + setText('Well Done') + dispatch(addWashTime({ datetime: Date.now() })) + return + } + const id = setInterval(timerCounter, 1000) + return () => { + clearInterval(id) + } + }, [timer]) + + const fill = 100 - timer * 5 + + const { FontAwesome5 } = vectorIcons + const { white } = colors + const { + container, + textSeconds, + textSecondName, + viewStyle, + progressStyle, + } = styles + + const renderTimer = () => { + return ( + + {timer === 0 ? ( + + ) : ( + {timer} + )} + + ) + } + + return ( + + + {() => ( + + {renderTimer()} + {text} + + )} + + + ) +} + +export default TimerButton + +const { white, circleBackground } = colors +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + textSeconds: { fontSize: 30, color: white }, + textSecondName: { color: white, marginTop: 15, fontSize: 18 }, + viewStyle: { alignItems: 'center', justifyContent: 'center' }, + progressStyle: { + backgroundColor: circleBackground, + borderRadius: 100, + }, +}) diff --git a/app/components/TimerComponent.js b/app/components/TimerComponent.js deleted file mode 100644 index db6bb91..0000000 --- a/app/components/TimerComponent.js +++ /dev/null @@ -1,47 +0,0 @@ -import React, { useState, useEffect } from 'react' -import { View, Text, StyleSheet } from 'react-native' -import { colors } from '../config' - -const TimerComponent = ({ navigation }) => { - const [timer, setCounter] = useState(20) - - const timerCounter = () => setCounter(timer - 1) - - useEffect(() => { - if (timer <= 0) { - return - } - const id = setInterval(timerCounter, 1000) - return () => clearInterval(id) - }, [timer]) - - console.log('timer new : ', timer) - return ( - - - {timer} - Seconds - - - ) -} - -export default TimerComponent - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - circleView: { - width: 150, - height: 150, - backgroundColor: colors.circleBackground, - borderRadius: 100, - alignSelf: 'center', - marginTop: 20, - alignItems: 'center', - justifyContent: 'center', - }, - textSeconds: { fontSize: 25, color: colors.white }, - textSecondName: { color: colors.white, marginTop: 15, fontSize: 20 }, -}) diff --git a/app/components/index.js b/app/components/index.js index d6dc8f0..740a6ad 100644 --- a/app/components/index.js +++ b/app/components/index.js @@ -1,3 +1,3 @@ -import TimerComponent from './TimerComponent' +import TimerButton from './TimerButton' -export { TimerComponent } +export { TimerButton } diff --git a/app/config/index.js b/app/config/index.js index eff9091..5408963 100644 --- a/app/config/index.js +++ b/app/config/index.js @@ -4,9 +4,11 @@ import production from './production' import colors from './colors' import store from './store' import routes from './routes' +import vectorIcons from './vectorIcons' let config = { colors, + timerDefault: 20, } if (__DEV__) { @@ -23,5 +25,5 @@ if (__DEV__) { } } -export { colors, routes, store } +export { colors, routes, store, vectorIcons } export default config diff --git a/app/config/vectorIcons.js b/app/config/vectorIcons.js new file mode 100644 index 0000000..dedf466 --- /dev/null +++ b/app/config/vectorIcons.js @@ -0,0 +1,9 @@ +import FontAwesome5 from 'react-native-vector-icons/FontAwesome5' +import Ionicons from 'react-native-vector-icons/Ionicons' + +const vectorIcons = { + FontAwesome5, + Ionicons, +} + +export default vectorIcons diff --git a/app/screens/HomeScreen.js b/app/screens/HomeScreen.js index 56ec5b9..97fdb3c 100644 --- a/app/screens/HomeScreen.js +++ b/app/screens/HomeScreen.js @@ -9,7 +9,7 @@ import { FlatList, } from 'react-native' import WashTimeCell from '../components/WashTimeCell' -import { colors, routes } from '../config' +import { colors, routes, vectorIcons } from '../config' import logo from '../assets/images/logo.png' import ShiftView from '../components/ShiftView' import { startShift } from '../state/Shift' @@ -18,6 +18,24 @@ import { selectShiftStarted } from 'app/state/Shift' import { getWashTimes } from '../state/WashTimeHistory' export const HomeScreen = ({ navigation }) => { + const { Ionicons } = vectorIcons + const { white } = colors + const { settingButtonStyle } = styles + navigation.setOptions({ + headerRight: () => ( + + {}}> + + + + ), + }) + const dispatch = useDispatch() const started = useSelector(selectShiftStarted) const washTimes = useSelector(getWashTimes) @@ -109,4 +127,5 @@ const styles = StyleSheet.create({ marginTop: 15, color: colors.white, }, + settingButtonStyle: { marginRight: 15 }, }) diff --git a/app/screens/TimerScreen.js b/app/screens/TimerScreen.js index 3515fb7..515c437 100644 --- a/app/screens/TimerScreen.js +++ b/app/screens/TimerScreen.js @@ -1,21 +1,25 @@ import React from 'react' import { View, SafeAreaView, StyleSheet } from 'react-native' -import { TimerComponent } from '../components' +import { TimerButton } from '../components' +import { colors } from '../config' const TimerScreen = ({ navigation }) => { + const { container, safeAreaStyle } = styles return ( - - - + + + ) } - export default TimerScreen +const { white } = colors const styles = StyleSheet.create({ container: { flex: 1, + backgroundColor: white, }, + safeAreaStyle: { flex: 1 }, }) diff --git a/ios/HandWashTimer.xcodeproj/project.pbxproj b/ios/HandWashTimer.xcodeproj/project.pbxproj index 3bcd92d..e535f75 100644 --- a/ios/HandWashTimer.xcodeproj/project.pbxproj +++ b/ios/HandWashTimer.xcodeproj/project.pbxproj @@ -165,6 +165,7 @@ 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, CC978C4B58B4BDE357267E06 /* Pods */, + C0E11174777C47A7812291F7 /* Resources */, ); indentWidth = 2; sourceTree = ""; @@ -198,6 +199,14 @@ path = Pods; sourceTree = ""; }; + C0E11174777C47A7812291F7 /* Resources */ = { + isa = "PBXGroup"; + children = ( + ); + name = Resources; + sourceTree = ""; + path = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -209,6 +218,7 @@ 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, + 9A4681B036DDCC954CC92DC6 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -230,6 +240,7 @@ 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + CB3F8E685B769FA20E94370F /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -433,6 +444,54 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9A4681B036DDCC954CC92DC6 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-HandWashTimer-HandWashTimerTests/Pods-HandWashTimer-HandWashTimerTests-resources.sh", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HandWashTimer-HandWashTimerTests/Pods-HandWashTimer-HandWashTimerTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; C3B76650BCB885D278B51FC8 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -455,6 +514,54 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + CB3F8E685B769FA20E94370F /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; DF228B8E9BFEB12E7C8E7828 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/ios/HandWashTimer/Info.plist b/ios/HandWashTimer/Info.plist index 8feb5e6..0a6dc89 100644 --- a/ios/HandWashTimer/Info.plist +++ b/ios/HandWashTimer/Info.plist @@ -38,7 +38,7 @@ NSLocationWhenInUseUsageDescription - + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -53,5 +53,7 @@ UIViewControllerBasedStatusBarAppearance + UIAppFonts + diff --git a/package.json b/package.json index 700df30..d0bcec1 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,13 @@ "moment": "^2.24.0", "react": "16.11.0", "react-native": "0.62.2", + "react-native-circular-progress": "^1.3.6", "react-native-gesture-handler": "^1.6.1", "react-native-reanimated": "^1.8.0", "react-native-safe-area-context": "^0.7.3", "react-native-screens": "^2.7.0", + "react-native-svg": "^12.1.0", + "react-native-vector-icons": "^6.6.0", "react-redux": "^7.2.0", "reactotron-react-native": "^5.0.0", "redux": "^4.0.5", From b34aee7d36b9fd87d5282c92e50ccafdb8441948 Mon Sep 17 00:00:00 2001 From: Bhuvneshwar Garg Date: Fri, 1 May 2020 13:15:00 +0530 Subject: [PATCH 2/9] Use only FontAwesome for icons --- android/app/build.gradle | 3 +-- app/components/TimerButton.js | 4 ++-- app/config/vectorIcons.js | 6 ++---- app/screens/HomeScreen.js | 6 +++--- ios/Podfile | 2 ++ 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 183feed..5da5bd0 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -78,8 +78,7 @@ import com.android.build.OutputFile */ project.ext.vectoricons = [ - iconFontNames: ['FontAwesome5_Brands.ttf', - 'FontAwesome5_Regular.ttf', 'FontAwesome5_Solid.ttf', 'Ionicons.ttf'] + iconFontNames: ['FontAwesome.ttf'] ] apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" diff --git a/app/components/TimerButton.js b/app/components/TimerButton.js index 3f4a694..ab092a1 100644 --- a/app/components/TimerButton.js +++ b/app/components/TimerButton.js @@ -27,7 +27,7 @@ const TimerButton = ({ navigation }) => { const fill = 100 - timer * 5 - const { FontAwesome5 } = vectorIcons + const { FontAwesome } = vectorIcons const { white } = colors const { container, @@ -41,7 +41,7 @@ const TimerButton = ({ navigation }) => { return ( {timer === 0 ? ( - + ) : ( {timer} )} diff --git a/app/config/vectorIcons.js b/app/config/vectorIcons.js index dedf466..1501bce 100644 --- a/app/config/vectorIcons.js +++ b/app/config/vectorIcons.js @@ -1,9 +1,7 @@ -import FontAwesome5 from 'react-native-vector-icons/FontAwesome5' -import Ionicons from 'react-native-vector-icons/Ionicons' +import FontAwesome from 'react-native-vector-icons/FontAwesome' const vectorIcons = { - FontAwesome5, - Ionicons, + FontAwesome, } export default vectorIcons diff --git a/app/screens/HomeScreen.js b/app/screens/HomeScreen.js index 97fdb3c..c163432 100644 --- a/app/screens/HomeScreen.js +++ b/app/screens/HomeScreen.js @@ -18,16 +18,16 @@ import { selectShiftStarted } from 'app/state/Shift' import { getWashTimes } from '../state/WashTimeHistory' export const HomeScreen = ({ navigation }) => { - const { Ionicons } = vectorIcons + const { FontAwesome } = vectorIcons const { white } = colors const { settingButtonStyle } = styles navigation.setOptions({ headerRight: () => ( {}}> - diff --git a/ios/Podfile b/ios/Podfile index 397ab44..7d344e2 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -77,6 +77,8 @@ target 'HandWashTimer' do pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' + pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons' + target 'HandWashTimerTests' do inherit! :complete # Pods for testing From 0c557750e98c6c818231122fe3beef1538a30371 Mon Sep 17 00:00:00 2001 From: Bhuvneshwar Garg Date: Fri, 1 May 2020 14:07:08 +0530 Subject: [PATCH 3/9] Add FontAwesome in Info.plist --- ios/HandWashTimer/Info.plist | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ios/HandWashTimer/Info.plist b/ios/HandWashTimer/Info.plist index 0a6dc89..e20a391 100644 --- a/ios/HandWashTimer/Info.plist +++ b/ios/HandWashTimer/Info.plist @@ -54,6 +54,8 @@ UIViewControllerBasedStatusBarAppearance UIAppFonts - + + FontAwesome.ttf + From e7f04015c3aea74b9ca3e01bfa88ebd29969738d Mon Sep 17 00:00:00 2001 From: Bhuvneshwar Garg Date: Fri, 1 May 2020 15:42:04 +0530 Subject: [PATCH 4/9] use same Button Component for Home Screen and Timer screen --- app/components/TimerButton.js | 76 +++++++++++++++++++++-------------- app/screens/HomeScreen.js | 5 +-- app/screens/TimerScreen.js | 2 +- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/app/components/TimerButton.js b/app/components/TimerButton.js index ab092a1..cc118ed 100644 --- a/app/components/TimerButton.js +++ b/app/components/TimerButton.js @@ -5,68 +5,76 @@ import { AnimatedCircularProgress } from 'react-native-circular-progress' import { useDispatch } from 'react-redux' import { addWashTime } from '../state/WashTimeHistory' -const TimerButton = ({ navigation }) => { +const TimerButton = ({ timerStart, image, text }) => { const dispatch = useDispatch() const timerDefault = config.timerDefault const [timer, setCounter] = useState(timerDefault) - const [text, setText] = useState('Seconds') + const [bottomText, setBottomText] = useState(text) + const [timerStartNew, setTimerStart] = useState(timerStart) const timerCounter = () => setCounter(timer - 1) useEffect(() => { - if (timer <= 0) { - setText('Well Done') - dispatch(addWashTime({ datetime: Date.now() })) - return - } - const id = setInterval(timerCounter, 1000) - return () => { - clearInterval(id) + if (timerStartNew) { + if (timer <= 0) { + setBottomText('Well Done') + setTimerStart(false) + dispatch(addWashTime({ datetime: Date.now() })) + return + } + const id = setInterval(timerCounter, 1000) + return () => { + clearInterval(id) + } } }, [timer]) - const fill = 100 - timer * 5 + const fill = 100 - (timer * 100) / timerDefault const { FontAwesome } = vectorIcons - const { white } = colors + const { white, green } = colors const { container, textSeconds, textSecondName, viewStyle, progressStyle, + circularView, } = styles - const renderTimer = () => { + const renderCircularProgress = () => { return ( - - {timer === 0 ? ( - - ) : ( - {timer} - )} - - ) - } - - return ( - {() => ( - {renderTimer()} - {text} + {timer} + {bottomText} )} + ) + } + + const renderCircularView = () => { + return ( + + + {bottomText} + + ) + } + + return ( + + {timerStartNew ? renderCircularProgress() : renderCircularView()} ) } @@ -81,10 +89,18 @@ const styles = StyleSheet.create({ justifyContent: 'center', }, textSeconds: { fontSize: 30, color: white }, - textSecondName: { color: white, marginTop: 15, fontSize: 18 }, + textSecondName: { color: white, marginTop: 25, fontSize: 18 }, viewStyle: { alignItems: 'center', justifyContent: 'center' }, progressStyle: { backgroundColor: circleBackground, borderRadius: 100, }, + circularView: { + height: 190, + width: 190, + borderRadius: 100, + backgroundColor: circleBackground, + alignItems: 'center', + justifyContent: 'center', + }, }) diff --git a/app/screens/HomeScreen.js b/app/screens/HomeScreen.js index c163432..e6a693c 100644 --- a/app/screens/HomeScreen.js +++ b/app/screens/HomeScreen.js @@ -5,17 +5,16 @@ import { StyleSheet, Text, TouchableOpacity, - Image, FlatList, } from 'react-native' import WashTimeCell from '../components/WashTimeCell' import { colors, routes, vectorIcons } from '../config' -import logo from '../assets/images/logo.png' import ShiftView from '../components/ShiftView' import { startShift } from '../state/Shift' import { useSelector, useDispatch } from 'react-redux' import { selectShiftStarted } from 'app/state/Shift' import { getWashTimes } from '../state/WashTimeHistory' +import { TimerButton } from '../components' export const HomeScreen = ({ navigation }) => { const { FontAwesome } = vectorIcons @@ -72,7 +71,7 @@ export const HomeScreen = ({ navigation }) => { style={washButtonViewStyle} onPress={washButtonClicked} > - + HISTORY diff --git a/app/screens/TimerScreen.js b/app/screens/TimerScreen.js index 515c437..5e9e54b 100644 --- a/app/screens/TimerScreen.js +++ b/app/screens/TimerScreen.js @@ -8,7 +8,7 @@ const TimerScreen = ({ navigation }) => { return ( - + ) From ceeed9dd0e3a58e7e526108110c65f256193529f Mon Sep 17 00:00:00 2001 From: Bhuvneshwar Garg Date: Fri, 1 May 2020 16:03:30 +0530 Subject: [PATCH 5/9] conflict problem --- .vscode/settings.json | 3 + app/App.js | 11 +-- app/components/Divider.js | 16 +++++ app/components/SettingsCell.js | 59 ++++++++++++++++ app/components/ShiftView.js | 2 +- app/config/colors.js | 2 + app/config/index.js | 4 +- app/config/store.js | 17 ++++- ios/HandWashTimer.xcodeproj/project.pbxproj | 53 +++++++++++++- ios/HandWashTimer/Base.lproj/LaunchScreen.xib | 65 +++++++++++------- .../medicbleep.imageset/Contents.json | 21 ++++++ .../medicbleep.imageset/medicBleep.png | Bin 0 -> 23845 bytes ios/HandWashTimer/Info.plist | 4 ++ 13 files changed, 223 insertions(+), 34 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 app/components/Divider.js create mode 100644 app/components/SettingsCell.js create mode 100644 ios/HandWashTimer/Images.xcassets/medicbleep.imageset/Contents.json create mode 100644 ios/HandWashTimer/Images.xcassets/medicbleep.imageset/medicBleep.png diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..335f886 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode" +} \ No newline at end of file diff --git a/app/App.js b/app/App.js index 2714b50..7a20d5b 100644 --- a/app/App.js +++ b/app/App.js @@ -1,6 +1,7 @@ import React from 'react' import { Provider } from 'react-redux' -import config, { store } from './config' +import config, { store, persistor } from './config' +import { PersistGate } from 'redux-persist/lib/integration/react' import { NavigationContainer } from '@react-navigation/native' import RootNavigator from './navigations' import Storybook from '../storybook' @@ -11,9 +12,11 @@ export default () => { } return ( - - - + + + + + ) } diff --git a/app/components/Divider.js b/app/components/Divider.js new file mode 100644 index 0000000..befbbe4 --- /dev/null +++ b/app/components/Divider.js @@ -0,0 +1,16 @@ +import React from 'react' +import { View, StyleSheet } from 'react-native' +import { colors } from '../config' + +const { cellDivider } = colors + +const Divider = () => { + const { divider } = styles + return +} + +export default Divider + +const styles = StyleSheet.create({ + divider: { height: 1, backgroundColor: cellDivider, marginLeft: 13 }, +}) diff --git a/app/components/SettingsCell.js b/app/components/SettingsCell.js new file mode 100644 index 0000000..071e554 --- /dev/null +++ b/app/components/SettingsCell.js @@ -0,0 +1,59 @@ +import React from 'react' +import { View, Text, StyleSheet, TouchableOpacity, Switch } from 'react-native' +import { colors } from '../config' +import Icon from 'react-native-vector-icons/FontAwesome' +import Divider from './Divider' + +const { cellTitle, dateText } = colors + +const SettingsCell = ({ + title, + onCellPress, + onSwitchValueChange, + titleNumLines, + iconName, +}) => { + const cellPressed = () => (onCellPress ? onCellPress() : null) + const switchValueChanged = (value) => + onSwitchValueChange ? onSwitchValueChange(value) : null + + const { titleText, wrapper, innerContent, icon } = styles + return ( + + + + {title} + + + {onCellPress == null ? ( + + ) : ( + + )} + + + + + ) +} + +export default SettingsCell + +const styles = StyleSheet.create({ + titleText: { + flex: 1, + fontSize: 17, + fontWeight: '400', + color: cellTitle, + marginTop: 12, + marginBottom: 12, + marginLeft: 21, + marginRight: 10, + }, + wrapper: { flexDirection: 'row' }, + innerContent: { justifyContent: 'center', marginRight: 27 }, + icon: { color: dateText, fontWeight: '400', fontSize: 17 }, +}) diff --git a/app/components/ShiftView.js b/app/components/ShiftView.js index 9fdd7b9..c3b3a86 100644 --- a/app/components/ShiftView.js +++ b/app/components/ShiftView.js @@ -16,7 +16,7 @@ const ShiftView = ({ started }) => { return } -export default ShiftView +export default React.memo(ShiftView) const styles = StyleSheet.create({ onShiftViewStyle: { diff --git a/app/config/colors.js b/app/config/colors.js index ad195ab..d81338f 100644 --- a/app/config/colors.js +++ b/app/config/colors.js @@ -1,5 +1,7 @@ export default { blue: '#0000FF', + cellTitle: '#4A4A4A', + cellDivider: '#E8E8E8', black: '#000000', green: '#00A778', navigationHeader: '#18a679', diff --git a/app/config/index.js b/app/config/index.js index 5408963..b19130e 100644 --- a/app/config/index.js +++ b/app/config/index.js @@ -2,7 +2,7 @@ import local from './local' import development from './development' import production from './production' import colors from './colors' -import store from './store' +import { store, persistor } from './store' import routes from './routes' import vectorIcons from './vectorIcons' @@ -25,5 +25,5 @@ if (__DEV__) { } } -export { colors, routes, store, vectorIcons } +export { colors, routes, store, vectorIcons, persistor } export default config diff --git a/app/config/store.js b/app/config/store.js index 19781ff..8a63ab1 100644 --- a/app/config/store.js +++ b/app/config/store.js @@ -2,10 +2,23 @@ import { createStore, applyMiddleware } from 'redux' import createSagaMiddleware from 'redux-saga' import rootReducer from '../state' import rootSaga from '../sagas' +import { persistStore, persistReducer } from 'redux-persist' +import AsyncStorage from '@react-native-community/async-storage' +import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2' + +const persistConfig = { + key: 'root', + storage: AsyncStorage, + stateReconciler: autoMergeLevel2, +} + +const persistedReducer = persistReducer(persistConfig, rootReducer) const sagaMiddleware = createSagaMiddleware() -const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)) +const store = createStore(persistedReducer, applyMiddleware(sagaMiddleware)) sagaMiddleware.run(rootSaga) -export default store +const persistor = persistStore(store) + +export { store, persistor } diff --git a/ios/HandWashTimer.xcodeproj/project.pbxproj b/ios/HandWashTimer.xcodeproj/project.pbxproj index e535f75..7ef3fa8 100644 --- a/ios/HandWashTimer.xcodeproj/project.pbxproj +++ b/ios/HandWashTimer.xcodeproj/project.pbxproj @@ -195,7 +195,6 @@ 4C31BFEF18B8509695493EF4 /* Pods-HandWashTimer-tvOSTests.debug.xcconfig */, 1CDF964D5E2D725C52EB528B /* Pods-HandWashTimer-tvOSTests.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -218,7 +217,7 @@ 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, - 9A4681B036DDCC954CC92DC6 /* [CP] Copy Pods Resources */, + 59D01FF18081654DFD522724 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -241,6 +240,7 @@ 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, CB3F8E685B769FA20E94370F /* [CP] Copy Pods Resources */, + 2A3B982739F5250D98C3BE9C /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -408,6 +408,54 @@ shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; + 2A3B982739F5250D98C3BE9C /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/AntDesign.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Entypo.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Feather.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Regular.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Fontisto.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Foundation.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf", + "${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf", + ); + name = "[CP] Copy Pods Resources"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AntDesign.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Entypo.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EvilIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Feather.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Brands.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Regular.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/FontAwesome5_Solid.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Fontisto.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Foundation.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Ionicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialCommunityIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/MaterialIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -445,6 +493,7 @@ showEnvVarsInLog = 0; }; 9A4681B036DDCC954CC92DC6 /* [CP] Copy Pods Resources */ = { + 59D01FF18081654DFD522724 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( diff --git a/ios/HandWashTimer/Base.lproj/LaunchScreen.xib b/ios/HandWashTimer/Base.lproj/LaunchScreen.xib index 3586a40..efe80ca 100644 --- a/ios/HandWashTimer/Base.lproj/LaunchScreen.xib +++ b/ios/HandWashTimer/Base.lproj/LaunchScreen.xib @@ -1,42 +1,61 @@ - - + + + + + - - + + - + - - - + - - - - - - + + + + + + + - + + + + + diff --git a/ios/HandWashTimer/Images.xcassets/medicbleep.imageset/Contents.json b/ios/HandWashTimer/Images.xcassets/medicbleep.imageset/Contents.json new file mode 100644 index 0000000..efe0834 --- /dev/null +++ b/ios/HandWashTimer/Images.xcassets/medicbleep.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "medicBleep.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ios/HandWashTimer/Images.xcassets/medicbleep.imageset/medicBleep.png b/ios/HandWashTimer/Images.xcassets/medicbleep.imageset/medicBleep.png new file mode 100644 index 0000000000000000000000000000000000000000..fa6f552c44c07783bd6fa371931c6d60b4df5b18 GIT binary patch literal 23845 zcmce+byQuw@&Jk!cXul;=ip9pcZX6qxVyW%ySsZ^tT+^RcbDSs&ZGB!_uk)n@Bg>g z%AV{blbMVpnPi76%1a=@$DU8L*!|-c5%N<6vNja^@l;ic%sX zq>2uA>b%Ng7UUY zlIS#>!UD9XD#FB$!HVQprIl7&xfIK1x4VLeU0L(yeRl4%H_kimCz|(jJjaK;&({$A zbdmI^MnrDG2UD?!cPNB4F;r$WizL9nX-FZ71a}ZHS>$ze*!)=B-do$6KUL@JxTrin znZEmCLFP-6fq{hwX3?s`UXh(cf&tJ5cZ0!DmlSPz+Z9W;od(4na7m5QBkI_7Dz;^j zG|H{fcbel|Ap}bf|;W`U5m3Dt~^-AC=oSd)+{dbPIgb z!->RDAyonIDicfC#T{&ki^gn*Q^F@0Ezul}#;cE~-%-0<5i*G^LL}Bv_*{#sm$8fBI0-iVv%teB~p|(^$H28P!pL?v3cTGu}jdvdA>ze@Ap~z zJSy!3p8R(^>;7~-lPF%nTwOOSMh$`{I@kHm zAxD}(fJIG1;V%`%VW2dy@9;Rjg{ehXL{}B-^`}6FCTnQLFwxPYhtC;~Gxl%K*@cuv zVJm0ktdA%^U7yG|Xyqx9lS0k=CS5Tpf6AK1+WgKd2BxCm!~PU*tt>W<>` zb{6UIV6hQlZ+~8Nv9}rI(61E?UB6y1b9EfNUmLu?VllnUhn}6UYE*JE8 zVB{v5IJ&u!;B)VdC0OJnH661->9P}y-wXM{%!D0Ttgn?um>HRDn5@Y-@7K`f z`@}LIehWIcCm-+9`bD7A6Yqx3)P-=-{9xck)Int1tFW1R`RoRGOBbY0!_a~Afg;u? zC(8t8D~gwWwxT?t&I(dc!P!EJmo!2r3KzIAm!;f8HATb0Sio>ai$&)RLkai(j6RgK zD-BQDm+(*|tc+*QXij|ydx%~hc@tA5(n#(Z*E3{pMB5ysBegChAlo78BYakRpmIX% zlcX6D$CCIn>1Xh?aI@fH!Ho)1Sk9XRd;7H*&TQX^*opF~LpPT5txNK+8rM@?A>1uqVV(k)UT4k>f`RJ6>h;q%$-TjY zcuI;)aRCxzPCDz^E2UBiZw(yi?X|4+fw(4_gVW( zCyxeE$GB5zNQO3U%x(Ri-urV$w?iufU(ePy*G>)h6Sq`$9J8%^V+;W%xtEj=ArIr% z{0GnL6Dzfowy_(zZ#HkuZ@e$LG0uea_^rk#Jz$w&K3ye#Baqq~BP8FaR%!~1dxrC=kG(|}a#1eEm zykz4(>VgoQ^ifd@Jt7*DZSz zqZ=K5Eu^m9wUlR+^wPS%iC1zmEj9cR8fmHpYAUsDZw+74 z6KMQUPp)@u2BzFJ+EM{)l$87X}5bV zM(QTO=g_vQT71}o8A9RY5VNwVaxSZ0m0i`Tf4ofDWi0hIde>~4v$E`)S6C@p;b|JM z{i3w5qS4gjH8AZ_udB7u&g#A2mn-aRVPj{xSRdJ3X~4Nyz54n*f%ipk1*4(V8Q^K# zBk=6a{*3oLLJ;4d9^EdtT{6BmyB7nwgIwSE&~)-{ybD-C)+VVEF!C}x)IZvq?tzqu zh`k|7COYL#@jlT%o}FJApeF8gF!&vQm#9QNkp=(7`Gsx&CY}}C6glUX*K?EbS!c%m z{5slN*ZSG__Q~0|)zxzcIu~IK#~aY-6m`nwMSC#)VAVcz%r!0;>Nef=-L82izL&gPKl0AFu58qOxO?2ymel)AY*DOQZq}Cuub3w< zQ&L}$V1MfM+*fc!4mNrOztk15ywcz8Jz{RMX+_-o<+>*5~B9SOeRaf?2^i1bdHAMr(mv8I%XoE#Y4M;;ao z3LGB{`XdMakp#dA{+kyErvZcfS2+Y2Sg1J|)IV+HKj7ad?j!xh`8R}22myon_(K0k zZg~*@X$=9)gZxh(EaRgNOh`pUO6miu7&;gm+c=upIuUT^?tc`(*-2_Sf`MUE{!QRg z%AYSj`kyyf)pXL7ljSkAwPw;cvNbSfatIaE&cwz9Bo}}uB_-u^Ff!p$78U;o{o{+D+|0?z zjt2m6b#-NOWo5E;FaMxK;`>e%A;uR zW^AP?YHs}@vkw{q>>NP8f3^Sr)clX)zcJMujU7a6tv?W*1pX)Ve~|xg<^LP;UnI5u zN0OPH?f;VeKQ;eg@&W#i{QpSe-(vn(>4%&J;Q0Xm)tLZ%crR4ehZ+gZMHN&(;D?d@ z>yi6-(|n}A@FUTJt~&1zJ|KgXsF11~_{leDw>c9W0j?zF2wu#Hw?Vs**4Ain0v0R8 z5JUptDxSzEf+*$?#3t~bkmrkSz$m(4fe;^H(*+jj zZ{I4@4{7orL|kwxpcl%&YX8;9Z-uN2s{fP;4<+q?y{C0u@c+}rUtkjohJoAEYQzWn zKP*7>-2azO7wj)0h!1wo5-$Dz$If47Apd`2W~bM4^Un&W9peG>s_!cVM33+$G}Fy} z&y{xltA2KjLdHkzBERh~bLESJA{lsGj;@kk&u6WyAQ_5)@E>WRE}()S45zSsanYgn zb2e~N>fYblF$iJLFLPOg!{p;W z$cii4Cku&<{9t9{5b-4h5yxDEE+eX^8p!+6f2$MpSI8%zM=El{#*I!W%NK?2@#oa; zZ<3MA=9FPLBy`53NY>smLe&h=q)IPP7NPcd{~g=T2a|>N;Y{srP%vRm&@N+m zYDgi>0Ke)Vq;v*=5D7gek|v`5Z9b$NANKUAmP!txT1;*v7U!-jIu-oK;S)Yj>M-85 z;D+#Ao-7ZE$nC>_ZK-Pxw$~k^?$4P!?s1b^;;*<6a;bozI4%K3l6fhWYn~UzprBA8 zn&m;R6}9C#PUxi}L?&f|h?1eBqnhR~|IvaV4upM5*DAcvryhA5(d{ctFFqBKm@-Nv zBe^pq^F%jz|D6-OmJo_`I9Md?l!1J}mXstA*7wH=98;`_F8s=DE-xO~K%m>?>^=pq zdOg$1;K38^rO-bbs}UuY$G|10+fCnrhx5ci#>x2-G&6Cw?V#}B`KQm26aq7`k5vg> zh+u|nVgU7vZd)3kDlx&og)c}bOgfI9mSz{Nw}m-7Mg3-n8n{K|fz{n$Y|DS<4QFK93wbc5Ry_?$VcF(us=?~ph~fVu=bK^Dd0T|{Ewe2 zihUr^F))|L@nz90Ob1lHcOge9VW?P{wCvZyZshv|R{DCgJcA{E|202Boxe6q@a@#I z7E=E$x##=t6LX$X!W3ilPaOYrW z1N4CA#so)+Uw;?lr$}~%!pHZ?#J6pS1@U+>~q+8)^?p9>ux?Bj~JWVry_`0T-{YJ(wz)&PW!y+FL~^yNY%a zX~}&?*7Ef=Z)2*#?E6W}A=@yZ;ion=O{zeurydP4|33~AB}OWaf%{Wm%j=YzL1bI_ zQ}Yj{X)3ueCF}OB>(z27NPW|+op8UEi@vunK~;<6W_s0QQA2GYjkWbSy716t8z#g5 zEN`-8s1$Ic=4@Tr-iNeSLe&U#da?+#Tr89_P@>pviJ$#c4;Ygo-st8r;Ej#IWP%Re zahYy7E%<3k;7jG< zq1zJ;q7ojEo6IW>NE5Q^CWM(2*_aNXoj)zu!i1)ivm0HkG%51X9Ft}O+ng;57sgA?ZnT*LOHr>jvTHE< z%9ni3DMQ{-dd+`=MDF;_Cv{Do!euA9LQ^SAWnBbbr+C8y*15m_q`D6gL3(oZ<28jG zJ7xXruc)D@cHI7CnelHDXFc<+0Ouar{O2K=QY5Au@>nEtH_dO}AyDLsK*V`Zc{zuo zAh=={EfzWP&n5d?Sl`d)&D+;_y;f&g#`2wO5|9`6BmT3R`{9D8qNmXV)&)boU7;v6 zE=lX>X)%3WZ-&Xv39qKZqtOH4C^bmK(>)KsOj!3-R=r zSCYn_9+ge}*31wvP~Lw4A;i%Z+nzBQmh1$T$5uuleema`l=}(JV!Q4gIsG=oe22o5 z0P!RpPgN;JQJfzPpy6il96CP`xAmS(+y$+Mb<$=bTNI#K>bS237jhVljp3we@d)C? zUy5s7aAW-xhGx^|pzl7&o^=}_EN#`St(k|8uHyccy>yI)b3E~_1G0Zyo1XjDsl0u& zHzYiP#gpLt()EstfiQu}-sZEF=g#KqGHm_vJI2Z5e%r2JNrQAx)E3cax zPOKcu>Q1TISX@?v*K|wAynsxyS}_QQDAenpiB5)gPB2 z>y1=N3@4Q*Q8EQsA3NJA_|C7+XQ~h)IbswF0zr=&IZIH%eAYaBa!8PoMKG~JCpI#m z_|SRSUYply(#*xFaRFS`5)zB5(S(k6lv?3T{!U)T#0H7qy>^XLn}R!y8@2d?TOCf!;saCUB#r?Ik_=iPF5a+=i`!?R0(HQ1vLeP{M~L^Bd1vti}Eo zBsf78#t6dA+mEDL%8n#7vY_qWQ?nr{p5QK2_d}n9oH+Qdd76D(sshnPVJax3_BI4~0O=AI(^3vRsbQ*AJx+TG5*TA|NV*mWc z_Y6+hh}{YO5&{wD!;xGzu*M*`C`Ko+QS`K@Y^vW&BTZP@viP&u+MEovG_ldpGW<4QAkk1<(pRw6;d#c+=UAmnPSwG86@&xz|ZjsVg9BWMJC80 zwljt6fs8Mte_pRn&hvEq<1Zb3|4(I;q+*zmpI4%F*!SMM%hCqwf$==epebogsW8OIZdsu z!+%u(ukZWHH&X~h9CCq8JtziBpvr`Re|cJzlFXo>tNde?B4b_YJef`nr2obgO$MS@ z_@voT8af_yk6HEW-7rZAlu&cD3hC$V>UI&NbJr50sH`qGPs&h1tevI9o@J4`Wn;wH zHM3v^5BWgfmm2Ac^5}55C@Av25G@E1q_ZzBX!BP5@ToN$flq3YBG)a(q>fL&uE~nU zKzEEJ(8NRar|QBRZNa7f-4_fOlziUAQO5vi1*VqT+NUp24sr_#I!n_%DI1}oC_SRK%JkrLbOxr1EF$S*L&I;6Vs=KJNPFr>q2kkQ#-&t6huS)n zysEvQQ)7m4I~gyo`@Cb+7pfLI?T`*M%3Ah(Sb2A$N~F`@yLq({05pbRhgwRz>ND*HciDofH zNujd&Mc;DNNR9&d85yp)4~)Z~VX~@BL>QbIL358_)|a+TL#*xTAuO-aDs5I^zTtZo zb?i(ha)3~21Ie3dwnIfd**6p|xk+B!F%iHCXw66sSFfgVnexB93~)##7J4)V-I_(( zU%kjlasQihDj>WhB90ka+DvAL#Ddwt7bi2)=NR1}CJ`U-pN|O$OFbvw1eA5Fn#Z8T zG4R*PM7r4g;dI{^(rZDrlpIkmZY_62hP9{Q&m4)-dU+ugMr`d;;m9IR)>0)kLxgKreCbLWs~B z{?~=(GD`R?^~Ogcy=9VBjTHEMo6);`ok^lj7vfmM6R^cd4~#=15xGpMA?f#s6OYXQZ2R3 zj+nd+7_EfPnId!_*T^>lO*bAP(3Nar+M? zkg*f$vSPQOWWr>+R4|LaE^yMujyy2_TgMW!VgEIc=MZJg` z=E~xaR+z723Q^eGYZi{}Po^x_2~A%#5Vir@8OMkyiTYK^>aWx_0F4iuMh;BM`Y}IG zAZV{QYXl}ffBFqrz0AZ^hYBv-dFJUYIP2==>Gmw#CeV` z9tPc=oLgiUDnxashl}f%&_K zq9CIHr&kE^D+$S5!lT8F(jvU39Ej#@wE8&>_eK}&&6`}58rkhl*-goKA`9EWNDAhL zlb{7XGdc_3Ie|lcJ*Yjn6(whz%Z?A1c8O%b<$Oy8(Io|whSqR-mNw7N7Mtc)$>u^a zd{^2%YS%?pJb}AId?kt$u^52;Gw`SMwczQePUPU{*c^oW#aD@mpj*#}`#+Va;P+K{ zGlD5m<=!J&g)IC^o&StvM;`ei=_j^_lBDyL! zUmwn!gzk;Nf;!+Zd@#6w7QNov@(f0Gel;~S`vW#r7jTw5xB;^z83|Kj9`;f_{mWs~ zc0S@z;OPBw2IoS)$m`xbq%839l#hU#A4MBZQJ4 z_v<@IIrCB%0!<}TAYLY^`tZo9fj0?P8=MFS=Sg~;zhe=aBwOUtfZ&8$yz*}0(k^L> zY3)Y5vT5z|)55tix0{*rNI@*Q()^!Mkm>3px^!-R!4iG6YA4?$KT#}82BBouF3$(l z}5d;Q}fH#Smf&3QxCO5AUTREPXQq0;RD1!;>3mQCpSq8H5{%S5C^Q_cV*hSjoBK=CFq5?|x%+b7p6ZLDk{LRzr>60t0%o%%{Ij-c1PYjO0oL1VUK5UUO< zq~oph?GA@QvmIv8Z?SAL(8H(}d$LSis!)wRmO8T#ZAJr5&m#lI{Djm%>hs>Qi*t}= zDF-y}8dQiuq1P8zepGIB-yw^v1QTZO+ovry>Ud7m2yFj+kWUA96m;ecK6QNaQEs%- z3DuSSXWdvX5lBZEz22UZ8ozI$6Nh*K+i3yrb=^h&*0PD8?0bx;IjxrAgZZ-_aI2l4 zNT2J4xN)!4RPu_7V#2bzX8S~&I-`#1*u*B7rF~h>N*e^1WeO9Rvzzkl9bL9{LSaXR zW;^PqCp$0|G7;w&Mh~%7Bs%r@5k+EbC!MW7fld-^voKpl7r>l|F>$fM|8VMxSP%Km z;KZv*A=DwT8#cE`S?Y7Fal>SzFoatT&+6&bI@#sDah5DkR#b_Dm~3*fZ`t!wW@CS6 zpZ^Z!;>R2vo|;+66N@cRFd0rAg&8Ti#~#)VZu5s=PrfuAMa7M=hFrFCR#4)FcFZ2h$2kHRH#??TdYXnJ@i`2+kzsJP^303mss_CM=XKXhh%=x1}EO-)gX{lNz zZ=r0%zh1;bcmiD-O=xH4njxP&Ws$xg3sm}mKJE1~ht%?c0R@3^7?T3CYBF<7TOR;7wXbUKD z!m`M{ESc?_WUr2;2ok&{PsJ63Wct_1*xFpwWZTdZq6l`}GA=aW6kcgxoi6#CTj`}fw>*t4(>VMO$f>lDdgj4%`B#RJB^jbub&U>7QQF)cca zpDM<*5$0$j(pxHZq#*oNp*~A{9C5+rLm;)k9ZV_nePJoG`|)JEq>8J=LUgJQNrOu@ z%?vs4=Bm)Mw@T5%UtLc@V^u*su~b_O6t>EF!lIRImH_TqnxdAE?g2fFA+HQ&9g);- zH>NwJYWG>dXyu3XmSXoL=TF&ly^Ou=w`Y^No=P7bRPC*L#U%rGN`Gi6L&uXF=f%c% zw#oBIw$Bb^jOWwl?TF^_f1pB^tJG^yPk26Oo6u|U0cNX}5hV#SHaP2gvBL(}(b~>h zk#j?nGm$G}qL;J7@%#I+hwESabtSEAu|$|aIHOHY*TguZLNL$ax9+g=V_8$1ss2a|L=UAo{QL_VamM%8l|sVspp%@XHt z-Z_qR;xRI*dLYUcR=Sa<6R6Swg&uO)4-2^jGk3@(Bvf`FP{PH{KD>gmFIY|>DdMn~ zaMO0M9Y3E`U+N(i-4%8`eKY&(t=fP3#{t?C*rUY*pIDrHh0Jn(I~Tuk!$2V!gvh1% zu=Ou^S6x~>(3Yx{K0-*fD|Pr7)ZS7iEKS23e4Ek`tKjFv!4jqXli8%=<*Ju}WgM0W zmw!doJGOo(Uz=qK7w2bRTy|;_w`QSzrRp;GQ9^{xz;J2R(bA5ah=t`omQy5`ubd13 zzQL%)YeHVfZ(+y`x#~w@dSy4t^Ylian^CW~2ZQUsCU(BcUj3o^BHkfqR3>+hXNQIX zun4b&8~sCYpD!PJ86eZ)CVS(T%ikDzMvHF$O{2yVEzP;^StR^-%$L^K-1ZplrsA~4 zOaE=BkUO(aYjHqaG6H%F;Glx- zokQaFi(^3%U9+NQ3SM6B@ch{Nk1fIB9aX&;NHX!)Q>iT?0qo2G0{_>cIc+9&9vRU_ z>#(jYcWj7TptWBH*OOZ9d`ji80job5q9<_+OcFqf$!Jt&MpArjH5O(yBxJ>OB$Ktx zyJ$;r@GO1Uj-Mav1{K$$)aBVeBGr)j1^!#CUSSMu`)ZhCSTQK4N|;L5K3xrJZ$!Tn z0*^W(SamDuaRJR1dzvu*lN1By#8%hvRLkBx2_JG0e02zY2b1}c>FvY@E;%6HkhIXq zVF+trCVW-G_nRDO&_(D>K7-SgiZtP9coD|{F{;WE4c9{{x&MLJBS?~oQlc1VcF2)a z|2jv-?rfMSI3!@XfOb%eq628vWuDSCnIuDb!;v)LRd8}G3W|dF{ycliMSQ@?gxzvy z1XjIoxHTC*azTsk(9C7=E}F)9z^AnJDxOiiPINTXs(t`aNwE?FJF1GP@dc}AeuR>_1MM|q54yH@{0Cdgz3H5b6*Z7|YO;kN zU#Aidx`FlRh!_mXgR8T z)nxF#y!1-wgQ{$3q#$zrX0iQo6y$=YwnD=k8&y-q(UGQJA_kf+l?n$W2XTZF5Tp6` zSKDr~Ght#*r%Xm>>lWNrV&gz?F7v2c=W0O|Vqb?^{r)(np~TIrxHYehI#Fmrd=s-@ zBvI)MkuFA{8U6!}nVoi$(@XC16+89#n}*B^>7uH>4n4o_7j38z#Nlww^mvmsU$E)X zA>*g-$dgqr=I%dwKBOjlP4s356<9n}>|vsysma~i#?@~-;PSCY;)twjN9@Ke)?ga* zR{kCJQ){=6qiMr%STYx@#~)&ao9^QVygO-njIi3KDMuGV1UySxpAGb+jUltIJ_mYO zVC)rhStyU5#!XYmBKAX6kA3CV)fX{<_E(~i!CbZYQ`O-zU~vp~MNAH0{GqtJD1uu) zH?KkEou6XE0|haOEX-gWu@|CNH`+WhQ!g4lF;L;N)tb;1Cx;BZi-F)?9e#|5m6Z5SpD3m>uUlh+YX?D)h4t5B3dTNyHysqSN=lXgUS5$z*rVw z{8gBQP}HZ-g)Iohn*nXfQ8kPdRVi*HVCZ13qz79jvWp@8j$M_(I5%nN8Ot`&C9S^K zA>XCkyHb?X-#ros_zuwK`s9B(}*X=gBru97EqT?RBbIv~`VH42pzkbwUR;nRW|gj(w$MRVy>n=H&yv_;Yah>VSN+2{WM? zKq(DhTp5zaheuu}S-)i)NCyP?Olj1&hSk9$ipid>mtcG8FvL>Q!hP(T8w5QtC9f`y z>_ZU4=W5EALm~MA@&%DxxA~M7ITGq|o-KewEzuHJfsJA!s> z4UIZl*f_AGt1=4uH{}u)-*YT;P}-2>pVd~`uxg-bOVQML+Tm&eF`LPd)85ev534?$MU; zm6ZvRi}ewB)0<~n)y8jzh=B@$2_ zDbGb7i|x16!A3n~4L)2adKd>Ul8Eyy_FAWr0okIZ?h7?P&d9-i$5_8uSKs9efBY%P z2@g?9>8wQIL~O0zD_joN;-f91vpd<6@eP|BDehYezY+y-7fP_xmA+^qEm)9NaM$2- zS$pW%6|`{mraSn9+j8Qq zDWJp^5t>9Bfa3002=2)YzelG$f{s!KIC_cs*iIen{)F~MUvZ40<2JxJ5$DQ&zmCZeLYtTmQc(X6Y+d%RLkz*zW|c$zOSR4L{Z=%t<~v580t177&m zluH`(#X%?DRb>r@Y9)W*<}1Cw9c&cmtFw#zX@MKXWLwXU5pQ##4OVhpn7fF_kyyF= zIA6vMchRfARUm2_S3@sJF(t=Pp|7)>#H&LRvdYa-cug=WRJN^z3?L5^I7Up>+gAD|o`p~+w&HAQ}( zNeSea7!O6_jgjD>e!(iGi#xFc6@s#TBFZ|F9D`T$8iMLMu4t>f*D?iNWzo%p<9K*T zO7!A9DVig?%G}N3BXU%4{|d1GU?d5GL%GD!m(7YQHnH zRw}D8PN5w4a`cBY{~VjW(@XvNvSt5Oe%TnKC*4pGe|2=Veb~Lywz@PFZR+5Q?Ulo2 zBfdYg2Ow-Eu{Lo&yk5b9Y{zEW;VW4Soa{Trz5ZjgpjhtikT5YLvshXeO)V4}Zo{f1 zWJFQuI`j-3{UVJ$8@_FERI|R=oIHniqe-d~gou(AeZh0BW}q;|RH9eRQQR@m*eV(` zgIB;WoS@DCm4=;J286F)h1ZGjmQXSTT3i_sQQkY~-zgPBHx#ibReN=~cm-KQBo-Q= zh!K6&D~^e(CbVeoykd$$7^47k*LO5bwSW5=A7zOql9QKzAQRa{hX9yR?kD+A$&)%Y!sR z_IKl?u1Qqw`*d)aSeXV@QNggVMHUm4NY}p?e`La?^X2K3z}+KRt%h&3cMcTBwRuj> z^;bfY`xPb{5WJyoNdCl!{53=kOHJ}i0GONJS}1ONw;Kfm++LOgmu2K*yz zn2n&I6hS8TM>4@-sxfa+)Odcb&XOpGq_9Agm)o7$x&!|>;>F-lrMuC(V6=nY2 z_m5vE-`_7N(}cmmK9~IcZ}RjTOxmpKg1}7&gS8gOyw#6h&f|QVSJIX|01HZV7ej1# zI(|IVE21DwI-ZJD5)k0W7Ej*ZGp#kur1pL-9_q^?Wx~QbbONz|fhZ+!Gs4R|l zJp+Lp-b|_5VHOH@^;7gZ9$$}E@rf_z7Ey&NopPZoO$*9Xf{#vnkA0a{DdLfEv}KC& zN81{mPBBXSTSs-;=bR@8Rhoqt5gy+m-WMWg@3lrtopAAvjq&duHPW``RK2432NK`n9!_=kPKv+isDI{#XsGG>vQA5P+`eyD>ouJcP8>npOI+RDe(iN2S|)rPH4iPHPmD%WB4 zweV;a8maAGn`gItA-xvjLZ1@Alb#-(5>4%j$9fiG?Q%A;fbu&dCR1FZ&(js8Z3Z(# z<{*Q=yZM;ZvJ0*HjH2q0qDQfyc(gzVrZA{}u(Lj+vvp+oyhhCph{1RcE8E-VkNJGj z(TD*lM=mWYW7#Q1$?}JdM!$L)2g31w9g=SC1~Q_#xF1#&Do9k}qDLb88HHFtfQT?D z#OEtp)&+WI&~5SLI~v79cpMg!->!Uh^N@FRXD}hxPeWqh1&aFOrYA> zoRa5$GC2Wp20Ln6r!g~0i|}&N{e0Aco<^B_Ux<@4aq1oViTz5|J@f5JhF?PYryUn# z)?JPe()nx&oGbzr@T)WIC@K~3TToY-qJkMKa4fycYJm(`o!%978_=cGi6aAzBU)ZF zHzO3u*JtkVsGbv{<)V8Ies2EhQ?_p}=UO@w=QmU|RCH7fjdW&PBBU%Xh2papWp@1O zmDh$R8PLV2XqfoAdUH*G?dt(1a3wp=%mPlxI`eVRaCQ$5gi6C0DUbbK!Vx;880e^- zCF_oayYk5Mx{YQyopEcFukw?r9V!ikBhwSUniad?^=5_6llzm47fRsNYv-~CL}0qc z%iA}~qqX^Nw&SQhcNh5! z`SGW;t3N+t(n2+kg-}QYl%oq3-+?WF*ZZ%Z|qERN98Z?bZr(QVNE<_+vJ>}JB!~b2t5MUf652rk1yYE7kU&n z>U9qRj9Y-oTkG@PqV3JP%k@ltZj!nDDTTDA$`Zm@n4uz;@OnUvUX_MH*nMjFOcyJ$Zj*`$^HiZGIJYO1D~GJx-zTSF5332BK2%b=7OCbR&q08xnHJHPSH_so2L*gt&Q>pvI2q-tnZ|h|+ za=j+wwb^NE@nlFbHKltJGU`AkyPFl4Ny|a}agO|z_qVX4FXi54PE)WlEj-?D@M;#f zKT4{v`Vc0whT7RY^e{`{M*Xs<*mf@1sbV`8BV*md^2BAnsu)Y<|WSct!rQ>ZnkYl47#Ka=)p&RhLi1Z48^J?E2rTIHeV z;myZI=GFT`@U!m~|Cn~Ylp3;(gr@M-=Qs4U8WP#U_kxAJR%Kq+Io4R+_ARjGW@db` zQ?-d9`u)H-_I3>OawHQx6t2U)G zO}>Edji*vClt7Hmr|^Dxy^5nx>z{ZR38+=R|0qqa2H#i+~8}wP4q!_>M^thZp-TdT3SuD z<>Uar_CdG4E6AX2uSh$)L(Bhft~lqv*z?AlIuVLS_HyD zKyH&#ZCNczZjU_1oqC4VW_1zWAk2rUWk1KL)Nu;fTc?DubRYGK(hC?(FN_=}PNbH# z)Touycr#xiC66ya7IHQVqNRO%R#2Q-7$^%NNucGo{>n94SXoh_%t!L!hN|YQaq>B8 zp{$al6A^`$)JoGuXL?YtWIz?uS6PZu^R*Nqkf71F$W2PgPNFI|aFPP(A+r~AwQh5p z(mK`uTfzOYA&fnd_`~BK7hzOQF45L3)AU$TlE=0mPgR;6_~>$>Ap*5nM{}B`9Z)Ay z;`u6#V%*00TB4s`8wVTkdUnLv_4Yf%`9k(jdA0!lOTS)8o!wl2nz+T3&#A8s%*^v2 zZTK(YGMUZlK|rSV!ZQj?_XhaycO9ie!lHx=BIrbIS)4FvZfrC-)l(k7glzs19KKLq4+R&*WAV>D|nsWAbX^!1TqtI0>Zz%Zky}0v*uQi zE{7J2vE14xq-bvWu>NqHd1j+GQ5qzOx(NZVp=c_USF7}Ht}wTZtiDFrvzUCB$}J*` z0pkmY*w6MhVmv(H{{M7yo&RvPU6(N!-4KjUL??(AHM;1D65WhW5JZ&dLxeDh-a8S! zMT<6iqDGG{M(@#k-btR^&;9%j@2B(S{MNP4y7pds{r0)e@%^49bU^Xkh`Um0Y(u{t zu?rhA)wRUww17aaSn4hJx!R{*ERNg~p_>itTAuBf%-DLVo+&N<6HQH?tsoGw zG>BUvt+h-7mz{O;(aax|ASwE+lE}l!>=E7Mf>Df5$$)W&e|_cR&i=NF2VsL!I|dQ< zjJD{QdjG2J@h4In)+8mWbJk8#I(FLDpB+kQxywIapPr{!Xpz3neT6+uY-0_m4jv)= zCiC+XIb5i}B_r2{YE{q?yLFNP7~ri^(>*@U?%bM)Fi65089+RL0LQ*eU_Cnvan68+SilhUi7mJ6~c>UDjbCSIV*7>4zI z6)D|oSQ^%_d7spP36Id?8&h(o!;|}6!m_?`?6PPB20J@^pgihcdx0Sxb_0hnWp+UU zmR1iV7Wb3#7LLbTc-OB8vs8}!XNv75TFu1yNm&5FA6JdnNKRg#9xo?Ay011C{L0q3 z?;aRY$Mtdpjym5#wrWq(*VFfeZ{l)T6BxfiQ|bBhCiU*AdjG-Pl=-*czQ%1 z`&Q9JVyVw+lZRQtW#|&& z7XZuoV=8@~&|d!roorK&%T7dT%2*S9L{pp>gx9n_!rP;KzdU&>-3;`40N*@?)!87d zxU>+9G-pcsS{*gNV#4udNzeH@Z0>-&3^M|LLj zu95cI1=$IX3J#~tPS|ibk}C@i4@Vo!gK%W_2=TVo*d@V?Xf7dV>^El({3m_vUuZY&+4#R0hg|DIguO?a9MI=uU?#?18EvNfDxU=v z4V1RVo4H!%b41!B`r?qh*HiP#c4N-C6r#E-^c}&tnDqnr2ovxjqX+j8pnkgbT4^fB z-de{@BF&R-S%}DO^WYu9(4gHZmIjO;BQJ$-MUiH@o<4y$QA<#h1sibpZmW7(xFVi& zp-037aBXw~vZ~>;a9H;0*y_`d19rlV0l{Ev!r`XO${=L621`evTNv4V28%(xlkV5} z8=72brxb0L#&u&yz&8KVDH|(Bkd(-lh!Ob&H44t;%Hz-8O|bSfYW^m)VBki1hyykK zrEQwtCz`uPg4ht>MWei0i1zw5bqk%`HAO%wo;sDsYv|YVeeVZ_N-v6&Cyoxmj%LNT zLhz{h=F%yI@qG3&(ZB0k+X+0`g zk_e?W?K%SsIXc?+xJ$k<^#KRMLB8VE;aU+}N+%^$`lf00xJp1AOk8*Ydt+zUol|{% zv23Q>sH(0)+wJAKA!GWjZvhK-%cX}6&J=K2%9T1PcDq~-2@(tiMnQS83r{d*>bvR? ztEKI5y;kmC&$nd@en?|Lu)pjvjXP~Y71RxZ7a*S^n6HC~q(|YarlrbIX7mQPu}-aW zd_uQw*=M^U-1QP~^Bi3(I`>5a7M?_vXPCaLq)!xPx%nDX<$3Ljc+{Iv=3wKX%n}wI zat9kE1*`Safb9t$1xuVHG?55fe$5o8z8U3UY*#!}d0&`-L~eh)@58uBy}zcBlrADN zV9O<4UQxq$zPHF}5P4)Zfp?w-M^^(DBmWCxzZO{Vo^bNXN0%~3VK_X(`Io>VZRHc69AG%`R?nj=#^4s-nEP9|C;nk_N@FF zBIzG$*K7NI&-VswNZPJ8F!fBt6NhSWWBJIS)Qx5L_^&QB8qJcxpOc&?^Ezs)CxAG+ zDBklX#(4qt#G6Lha&m3=W*~l{Gi74|vw<0- zbv+lH?%Kn$Z=}sD@~U?HR!Ve-p9Qv-oQ79S_?6qT!rPf-&^9z3`_X|l^t#v3+Ix{0 zfZCwb86dae$!qNQXI0O-;sVJ{ZFFmoe|U=BMn-uzh?mgE^rxU;`DeXw*H=F#i|uWJ z5QS{n&@Og(J4A*qVCCbW*Tc^}L@yB|1E)1VD!}DaFWMKCQ*3UWHgWn1chhvWW7)hN zDtE=1O7IYQe&6ZLzfK5G1frU!c@Ze%Nj@znnr8>x<%Bj`0y<*15!TU36EXwfc0HX$e=K%TBmy=Aqw}==Kb4wHy&BT13t9=FI!ZUtHoP>ieCn4IYK&sfRkD&8pUB z{LUD~_DB^tPi2EZN5q#5*8&}i?)wGik+FS{aEbw^6l4Auqy3Y6x%){kK0se@&CMg! zXM{M5WNXR#JLRI%15tM$-`k@;FI$rM`Ro{k*d`pB_aTY*!P{f^ zVs>SJJZf0++?BQ9-Nb^D(#@qhY)RYH{44nLiOeqzXYbW?T~VHlr)|0QnDCr*5m>6` z492SjG1kS>X=%>L&}pg_@#kNkdWu3N_ohHPtSU;qMnuG3BG1)#AH7PU?xKxL5T$Di z#B;G$sBCe$_-ugz>NIT*VPD4;Wyoeu35s{3T(DUZwQFL`P44TRoimL3PH+W=5L>2z zM4`U#8GDTLHZVFjt0W{5FxcxKqwYO7j4Yd1XN-qwcH-C$@9!@W0S-!UHN1fWGT8jV z9+4{a{^TRSZk6ssn+m+!P_E?rsf->a9h}W@;T(DITF{-}i2HX|@^vffXs|n`-4|{#(FDV_=Jx3z=-*0f+jM& zN{#jpy5t~8@(73n-ODU-9e*{UGQZLM5GtW8ewm&WmzjO;0XZdSVd5QpmX)6;S_}4c z1*=RK(5ui!@V|3qKM;Rj`I3vi0lZtDtiS#?!BO25KmM#Z>JB9kh$$;WTFHpX%>T^RiP%u)X^9&IgNVh{#=bA<&$;adh2|>!)qi^tE*Pkt8BdpH%+2-IiV4 zR6pOsyj0fNQ*gm%+=D@0do>#HUr^#dpmBFm&iI}qE_NZ>9!ShnSJL!?nrhIzWFSVbNlKuunG63HoAO4_m z`vn%ZkU*g7k4?RvesWUakL1aiM`2AA8BR~gVi*KB@4ON`isg2CY1E^p9Cov;DPk(A zv^zD-bkFINQS3ccbzCzV8QHIMd{D#ricjq5T|?8m#DI?V{&~99;b{D>!0{;I!*G!= z)CzGAmDKSC!d+#SCr*8Lu(rP737=G}OVFqeGr%IAujX9Ka?){i?iRZRXh)a1ajdn9 zV`iCS^JxuyoQs*?B=9y=3n%yu&jkAZE|3&L|LV-FNv&)uQwTv4%w=7j&(`(sHCgV- zmWf4k(WzNPp8i7>RQE#^hFj6Y;0@0Sx2N_!-%Hb5{W2CV-9?5s(nXBBUo{e6^nFVn z9aK+B3i>DQSeSr47$|yuiz2LHvN;jZ%h2Zr%jc!qkoIoh!8i*1vmtNEoxqa*i+w$i@`6V&&+tUUS4y%L)H z2283`YWitS6x*x=1dpLXUd=|w(Gt-oxqTT*$4dtGC}jM+Mj0NDSf!FI(GyNPTj_2z zZ+Ln(Es}L=BC%b1>hLR+X8xnaq)Xe(`@X-SPcoxJ$4b1aSk$wzxW6cDb|^#c=CJYs z-*C*!Zg*P3FUTp}`-Rl{qz28$e6_@68{Mypt8xQ;w2ksd;Nc!$KP%eETgw90IsvB+ zwbAox-Z^*9^*=dH3Iv3qIVXo@t#MQ(zY|d94`YM57;)7IlR(MkRSy(Ne|XUp+9!AY zbf4p;{vlWWK~+_-WKBDl!Pw7SAAJ@h#z%kjtk=^e91u*0%_gpqAtbhIKa=$?(KgS5 zd{709uAAS9`3Ou3up~p$HY1KN`E12xm+0qd9JZC8z>g1IuoMlvFWDlOvjYz{4)0+H z>x}B_xoMw{pRT3N1fT$lyJniSxzS!Uu|FK)5L5=8H}wM+ zH@HhfAF$(7fPASw#o>2JmxgVf$?nqZqpU>*gVYzvr|IW)JnRLXQg~|wEW>jmt`pjl|4M$9Bzxi-T+Q+~-vt43u;#!$WMq@B&xPweO|OyEFZG^~#;XnI z)PUu;7TG>sOi3}^urRB+8W&3Mq(|v%97~6yHyYex9s>=24tD#sZe}OH+6mk@GJ+oJ*#^%Cv~D8FwfQfdz8H`QB$PYR{hjR@B$U)ngIQ zCU=K0Pvx$6jkf+)mLv)UL?C?wc5qJS{mrmMbGyqO4p#W32eFfNk&v@O!Fs#BpR~u@ z1rm;T9IEe9bt9iOR&~KcZ`DK- zde1uey#=+7t7OW!uJk>kgudAD#X~GLyZ6jAnAdgCD7|Wh{Z<+^CZkqRbM+zLXWd%d53qayM2DHfK#SDpYF4?B!`&d18|s?Ckj0i2G*l0g(i7SVItON z6A!x`HZXjMne7&T8lQbpZaqA|j4{el&Kc0<tKtw1>UEh#&;XlbvcCw$t6(Bz8ckh|EYxE()@eL zM7`8f@f;uerZkFd9?tn*95Fh#Xm4jJtu{B2wL+DkX{LJgTUWjUtL)~@*hd;kY*Tmt z3lNS57+4Q2A6+t~5~d>Sc+uYUFf1d6DPNi}fZZ*y{%WCN7b2XDaU3?U4R?CAq^Fyd z^p2n9-hUB5fCXk!Qoxw|81-pKV*#}xeH2>+VV`$(CaQ;Uj$&6NG}f%;%||Rn&R7A~ z3ESW~w#G3X&4?WrvgO*oJ@&yeWA{Ek|nw~QYl4c zkNzA}P&>s*N&J9ppiZrd4$7KH+&y=~)f1i~?aN8tj?;DU_HsQgm4EhsW1IX9dyygK zPE$HwA7E(0&Br{12OP2Q-EC5j(CSV;T!AM&t>{RZwqz#|tLQ*(P}&pFWy*ek)FmPm z_SGU3=D|ubTY>cX2nxWj;TEl<*1p#q=;mS4_KEW!3cGLtb>zt^j%^Q8TS85+W!F!I z1EMtN{jwWZ5ON%d+0GKJvCscR%nKAG|S%@_9Vuu%$hMD`vef-gSxR*Tg8G7a)t*RDnU=bJe zHHI_3tv&Vh7ZLAy8ZBlIeJA zaP!Ii^boo3lk?5%lDHDG{}?V(;I#sh5)kY-Qk%$l#N~ZIOl?e3c06J}_eUbn|KwUw zAQ+HH4)MBEYvLAL2c7h0*dzj61kM~H)C#YuS>?(YWOB*>fdpa_p>IxpM|Wn8(43=M z&jgDW;MhW6^q8MGtUgxeOlKJpql)+Y+YJ9)UXfPDBOMW~^7K<#qmkP|thwG|W9X6G z#FxaxAg?t=g@36+3o9x5`(!2xByHNTHceC|ZK61Jh-*g&-7o(RZFc=r)}v}ZXw3Lu zOZj^%^npAq{N+UbRev1!Un)I*+lc#C1*ZSTQAvchbak@aM1T9lZ$UE!f#6jHhW7gZ zM&S6n%Q}5i?fhp`0-0b`=;pX1_iTpZUlL}~UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIAppFonts + + FontAwesome.ttf + UIViewControllerBasedStatusBarAppearance UIAppFonts From eb1ef510871d107aecb7f4c318a13a5cee0bc652 Mon Sep 17 00:00:00 2001 From: Vinod Chauhan Date: Fri, 1 May 2020 16:44:28 +0530 Subject: [PATCH 6/9] Linking and action reducers completed --- app/components/SettingsCell.js | 3 +- app/navigations/MainNavigation.js | 4 +- .../{Settings.js => SettingsScreen.js} | 28 ++++++++++---- app/screens/index.js | 4 +- app/state/Settings.js | 37 +++++++++++++++++++ app/state/index.js | 2 + ios/HandWashTimer/AppDelegate.m | 8 ++++ 7 files changed, 74 insertions(+), 12 deletions(-) rename app/screens/{Settings.js => SettingsScreen.js} (55%) create mode 100644 app/state/Settings.js diff --git a/app/components/SettingsCell.js b/app/components/SettingsCell.js index 071e554..dad73fd 100644 --- a/app/components/SettingsCell.js +++ b/app/components/SettingsCell.js @@ -10,6 +10,7 @@ const SettingsCell = ({ title, onCellPress, onSwitchValueChange, + switchValue, titleNumLines, iconName, }) => { @@ -29,7 +30,7 @@ const SettingsCell = ({ {onCellPress == null ? ( - + ) : ( )} diff --git a/app/navigations/MainNavigation.js b/app/navigations/MainNavigation.js index 8446500..fa38f39 100644 --- a/app/navigations/MainNavigation.js +++ b/app/navigations/MainNavigation.js @@ -1,6 +1,6 @@ import { createStackNavigator } from '@react-navigation/stack' import React from 'react' -import { HomeScreen, Settings } from '../screens' +import { HomeScreen, SettingsScreen } from '../screens' import { routes, colors } from '../config' const { HOME_SCREEN, SETTINGS_SCREEN } = routes @@ -22,7 +22,7 @@ const MainNavigation = () => ( > { - const storeHistoryValueChanged = (value) => {} - const shiftReminderValueChanged = (value) => {} - const aboutMbCellPressed = () => {} - const followCellPressed = () => {} +const medicBleepAboutUsUrl = 'https://www.medicbleep.com/about.html' +const medicBleepFollowTwitterUrl = 'https://twitter.com/MedicBleep' + +const SettingsScreen = ({}) => { + const dispatch = useDispatch() + const isStoreHistory = useSelector(selectStoreHistory) + const isShiftRemindersAllow = useSelector(selectShiftReminders) + + const storeHistoryValueChanged = (value) => + isStoreHistory !== value ? dispatch(storeHistory(value)) : null + const shiftReminderValueChanged = (value) => + isShiftRemindersAllow !== value ? dispatch(shiftReminders(value)) : null + const aboutMbCellPressed = () => Linking.openURL(medicBleepAboutUsUrl) + const followCellPressed = () => Linking.openURL(medicBleepFollowTwitterUrl) const { container, contentWrapper } = styles return ( @@ -20,6 +32,7 @@ const Settings = ({ started }) => { title={'Store History'} onCellPress={null} onSwitchValueChange={storeHistoryValueChanged} + switchValue={isStoreHistory} titleNumLines={1} iconName={null} /> @@ -27,6 +40,7 @@ const Settings = ({ started }) => { title={'Two Hour On Shift Reminders'} onCellPress={null} onSwitchValueChange={shiftReminderValueChanged} + switchValue={isShiftRemindersAllow} titleNumLines={2} iconName={null} /> @@ -50,7 +64,7 @@ const Settings = ({ started }) => { ) } -export default Settings +export default SettingsScreen const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: white }, diff --git a/app/screens/index.js b/app/screens/index.js index 802d758..c8768d4 100644 --- a/app/screens/index.js +++ b/app/screens/index.js @@ -1,4 +1,4 @@ import HomeScreen from './HomeScreen' -import Settings from './Settings' +import SettingsScreen from './SettingsScreen' -export { HomeScreen, Settings } +export { HomeScreen, SettingsScreen } diff --git a/app/state/Settings.js b/app/state/Settings.js new file mode 100644 index 0000000..80f5e97 --- /dev/null +++ b/app/state/Settings.js @@ -0,0 +1,37 @@ +const initialState = { + isToStoreHistory: false, + isToAllowShiftReminders: false, +} + +// Types +export const STORE_HISTORY = 'store_history' +export const SHIFT_REMINDERS = 'shift_reminders' + +// Reducer +export default (state = initialState, action = {}) => { + switch (action.type) { + case STORE_HISTORY: + return { ...state, isToStoreHistory: action.payload } + case SHIFT_REMINDERS: + return { ...state, isToAllowShiftReminders: action.payload } + default: + return state + } +} + +// Action creators +export const storeHistory = (isStoreHistory) => ({ + type: STORE_HISTORY, + payload: isStoreHistory, +}) + +export const shiftReminders = (isShiftRemindersAllowed) => ({ + type: SHIFT_REMINDERS, + payload: isShiftRemindersAllowed, +}) + +// Selectors +export const selectStoreHistory = (state) => + state.settingsReducer.isToStoreHistory +export const selectShiftReminders = (state) => + state.settingsReducer.isToAllowShiftReminders diff --git a/app/state/index.js b/app/state/index.js index 6dee145..1f815a9 100644 --- a/app/state/index.js +++ b/app/state/index.js @@ -1,9 +1,11 @@ import { combineReducers } from 'redux' import Shift from './Shift' import WashTimeHistory from './WashTimeHistory' +import Settings from './Settings' const rootReducer = combineReducers({ shiftReducer: Shift, washTimeHistory: WashTimeHistory, + settingsReducer: Settings, }) export default rootReducer diff --git a/ios/HandWashTimer/AppDelegate.m b/ios/HandWashTimer/AppDelegate.m index 94b0575..866f806 100644 --- a/ios/HandWashTimer/AppDelegate.m +++ b/ios/HandWashTimer/AppDelegate.m @@ -3,6 +3,7 @@ #import #import #import +#import #if DEBUG #import @@ -55,4 +56,11 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge #endif } +- (BOOL)application:(UIApplication *)application + openURL:(NSURL *)url + options:(NSDictionary *)options +{ + return [RCTLinkingManager application:application openURL:url options:options]; +} + @end From 880c56247bba7da485da5d42c9658a9b8344c3b7 Mon Sep 17 00:00:00 2001 From: Mohit Date: Fri, 1 May 2020 16:57:19 +0530 Subject: [PATCH 7/9] changes in project.pbxproj file --- ios/HandWashTimer.xcodeproj/project.pbxproj | 13 +++++++++++++ ios/HandWashTimer/HandWashTimer.entitlements | 5 +++++ ios/HandWashTimer/Info.plist | 8 ++++---- 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 ios/HandWashTimer/HandWashTimer.entitlements diff --git a/ios/HandWashTimer.xcodeproj/project.pbxproj b/ios/HandWashTimer.xcodeproj/project.pbxproj index 92d21cf..c490251 100644 --- a/ios/HandWashTimer.xcodeproj/project.pbxproj +++ b/ios/HandWashTimer.xcodeproj/project.pbxproj @@ -64,6 +64,7 @@ 57C09C416E0FF2A08CB7AC92 /* libPods-HandWashTimer-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HandWashTimer-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 922260DECAA65BA22DDACD82 /* Pods-HandWashTimer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HandWashTimer.debug.xcconfig"; path = "Target Support Files/Pods-HandWashTimer/Pods-HandWashTimer.debug.xcconfig"; sourceTree = ""; }; C41B589A18BEDE76BEABFBCB /* Pods-HandWashTimer-HandWashTimerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-HandWashTimer-HandWashTimerTests.release.xcconfig"; path = "Target Support Files/Pods-HandWashTimer-HandWashTimerTests/Pods-HandWashTimer-HandWashTimerTests.release.xcconfig"; sourceTree = ""; }; + E4AA7778245C36E1006AB0F2 /* HandWashTimer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = HandWashTimer.entitlements; path = HandWashTimer/HandWashTimer.entitlements; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; F3783A3EA9B39535FE1B8BB3 /* libPods-HandWashTimer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-HandWashTimer.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -125,6 +126,7 @@ 13B07FAE1A68108700A75B9A /* HandWashTimer */ = { isa = PBXGroup; children = ( + E4AA7778245C36E1006AB0F2 /* HandWashTimer.entitlements */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -293,7 +295,16 @@ TestTargetID = 13B07F861A680F5B00A75B9A; }; 13B07F861A680F5B00A75B9A = { + DevelopmentTeam = 3G3Z8YL4CF; LastSwiftMigration = 1120; + SystemCapabilities = { + com.apple.BackgroundModes = { + enabled = 0; + }; + com.apple.Push = { + enabled = 0; + }; + }; }; 2D02E47A1E0B4A5D006451C7 = { CreatedOnToolsVersion = 8.2.1; @@ -727,6 +738,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 3G3Z8YL4CF; ENABLE_BITCODE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", @@ -754,6 +766,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 3G3Z8YL4CF; INFOPLIST_FILE = HandWashTimer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( diff --git a/ios/HandWashTimer/HandWashTimer.entitlements b/ios/HandWashTimer/HandWashTimer.entitlements new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/ios/HandWashTimer/HandWashTimer.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/HandWashTimer/Info.plist b/ios/HandWashTimer/Info.plist index 01f31f8..a7e1bda 100644 --- a/ios/HandWashTimer/Info.plist +++ b/ios/HandWashTimer/Info.plist @@ -39,6 +39,10 @@ NSLocationWhenInUseUsageDescription + UIAppFonts + + FontAwesome.ttf + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities @@ -51,10 +55,6 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UIAppFonts - - FontAwesome.ttf - UIViewControllerBasedStatusBarAppearance From 6a7ac339a3d9c7c0ac646c0f86218f96d56dc57f Mon Sep 17 00:00:00 2001 From: Mohit Date: Fri, 1 May 2020 17:20:40 +0530 Subject: [PATCH 8/9] conflict resolved --- app/navigations/MainNavigation.js | 2 +- app/screens/HomeScreen.js | 7 +- app/screens/index.js | 4 +- ios/HandWashTimer/Info.plist | 117 ++++++++++++++---------------- 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/app/navigations/MainNavigation.js b/app/navigations/MainNavigation.js index 8f4ed6c..cfbd287 100644 --- a/app/navigations/MainNavigation.js +++ b/app/navigations/MainNavigation.js @@ -1,6 +1,6 @@ import { createStackNavigator } from '@react-navigation/stack' import React from 'react' -import { HomeScreen, SettingsScreen } from '../screens' +import { HomeScreen, SettingsScreen, TimerScreen } from '../screens' import { routes, colors } from '../config' const { SETTINGS_SCREEN, TIMER_SCREEN, HOME_SCREEN } = routes diff --git a/app/screens/HomeScreen.js b/app/screens/HomeScreen.js index e6a693c..65593fc 100644 --- a/app/screens/HomeScreen.js +++ b/app/screens/HomeScreen.js @@ -20,10 +20,15 @@ export const HomeScreen = ({ navigation }) => { const { FontAwesome } = vectorIcons const { white } = colors const { settingButtonStyle } = styles + const { SETTINGS_SCREEN, HOME_SCREEN } = routes navigation.setOptions({ headerRight: () => ( - {}}> + { + navigation.navigate({ name: SETTINGS_SCREEN, key: HOME_SCREEN }) + }} + > - CFBundleDevelopmentRegion - en - CFBundleDisplayName - HandWashTimer - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSExceptionDomains - - localhost - - NSExceptionAllowsInsecureHTTPLoads - - - - - NSLocationWhenInUseUsageDescription - - UIAppFonts - - FontAwesome.ttf - - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - UIAppFonts - - FontAwesome.ttf - +CFBundleDevelopmentRegion +en +CFBundleDisplayName +HandWashTimer +CFBundleExecutable +$(EXECUTABLE_NAME) +CFBundleIdentifier +$(PRODUCT_BUNDLE_IDENTIFIER) +CFBundleInfoDictionaryVersion +6.0 +CFBundleName +$(PRODUCT_NAME) +CFBundlePackageType +APPL +CFBundleShortVersionString +1.0 +CFBundleSignature +???? +CFBundleVersion +1 +LSRequiresIPhoneOS + +NSAppTransportSecurity + +NSAllowsArbitraryLoads + +NSExceptionDomains + +localhost + +NSExceptionAllowsInsecureHTTPLoads + + + + +NSLocationWhenInUseUsageDescription + +UILaunchStoryboardName +LaunchScreen +UIRequiredDeviceCapabilities + +armv7 + +UISupportedInterfaceOrientations + +UIInterfaceOrientationPortrait +UIInterfaceOrientationLandscapeLeft +UIInterfaceOrientationLandscapeRight + +UIAppFonts + +FontAwesome.ttf + +UIViewControllerBasedStatusBarAppearance + - + \ No newline at end of file From c9ce862cfd8e0148c274a03e3824f89f0d93838d Mon Sep 17 00:00:00 2001 From: Mohit Date: Fri, 1 May 2020 19:26:11 +0530 Subject: [PATCH 9/9] save history check added before wash time adding in redux --- app/components/TimerButton.js | 12 +++++++++--- app/components/WashTimeCell.js | 4 ++-- app/config/colors.js | 2 +- app/state/Settings.js | 4 ++-- app/state/WashTimeHistory.js | 8 ++------ storybook/index.js | 11 +---------- 6 files changed, 17 insertions(+), 24 deletions(-) diff --git a/app/components/TimerButton.js b/app/components/TimerButton.js index cc118ed..bb860a5 100644 --- a/app/components/TimerButton.js +++ b/app/components/TimerButton.js @@ -1,12 +1,14 @@ import React, { useState, useEffect } from 'react' -import { View, Text, StyleSheet } from 'react-native' +import { View, Text, StyleSheet, Image } from 'react-native' import config, { colors, vectorIcons } from '../config' import { AnimatedCircularProgress } from 'react-native-circular-progress' -import { useDispatch } from 'react-redux' +import { useSelector, useDispatch } from 'react-redux' import { addWashTime } from '../state/WashTimeHistory' +import { selectStoreHistory } from '../state/Settings' const TimerButton = ({ timerStart, image, text }) => { const dispatch = useDispatch() + const isStoreHistory = useSelector(selectStoreHistory) const timerDefault = config.timerDefault const [timer, setCounter] = useState(timerDefault) const [bottomText, setBottomText] = useState(text) @@ -19,7 +21,10 @@ const TimerButton = ({ timerStart, image, text }) => { if (timer <= 0) { setBottomText('Well Done') setTimerStart(false) - dispatch(addWashTime({ datetime: Date.now() })) + + if (isStoreHistory) { + dispatch(addWashTime({ dateTime: Date.now() })) + } return } const id = setInterval(timerCounter, 1000) @@ -95,6 +100,7 @@ const styles = StyleSheet.create({ backgroundColor: circleBackground, borderRadius: 100, }, + imageView: { width: 100, height: 100 }, circularView: { height: 190, width: 190, diff --git a/app/components/WashTimeCell.js b/app/components/WashTimeCell.js index 24ac814..7700733 100644 --- a/app/components/WashTimeCell.js +++ b/app/components/WashTimeCell.js @@ -1,6 +1,7 @@ import React from 'react' import { View, StyleSheet, Text } from 'react-native' import { colors } from '../config' +import Divider from './Divider' import { timeIn24HrsFormat, getDayFromDate, @@ -15,7 +16,6 @@ const WashTimeCell = ({ item }) => { dayAndDateBgView, dateView, dayView, - sepratorViewStyle, } = styles const { dateTime } = item @@ -30,7 +30,7 @@ const WashTimeCell = ({ item }) => { {convertDateIntoDateComponent(dateTime)} - + ) } diff --git a/app/config/colors.js b/app/config/colors.js index bcb5acc..b5ce359 100644 --- a/app/config/colors.js +++ b/app/config/colors.js @@ -10,5 +10,5 @@ export default { dayText: '#4A4A4A', dateText: '#9b9b9b', separatorLineGray: '#E5E9EA', - circleBackground: '#5AC8FA', + circleBackground: '#00A1D2', } diff --git a/app/state/Settings.js b/app/state/Settings.js index 80f5e97..d8a90ad 100644 --- a/app/state/Settings.js +++ b/app/state/Settings.js @@ -1,6 +1,6 @@ const initialState = { - isToStoreHistory: false, - isToAllowShiftReminders: false, + isToStoreHistory: true, + isToAllowShiftReminders: true, } // Types diff --git a/app/state/WashTimeHistory.js b/app/state/WashTimeHistory.js index 8760bdb..a59ab83 100644 --- a/app/state/WashTimeHistory.js +++ b/app/state/WashTimeHistory.js @@ -8,12 +8,8 @@ export const ADD_WASH_TIME = 'add_wash_time' // Reducer export default (state = initialState, action = {}) => { switch (action.type) { - case ADD_WASH_TIME: { - const { washTimes } = state - console.log('washTimes', washTimes) - washTimes.push(action.payload) - return { ...state, washTimes: [...washTimes] } - } + case ADD_WASH_TIME: + return { ...state, washTimes: [...state.washTimes, action.payload] } default: return state } diff --git a/storybook/index.js b/storybook/index.js index 64b075a..73f983a 100644 --- a/storybook/index.js +++ b/storybook/index.js @@ -8,22 +8,13 @@ export const item = { dateTime: Date.now(), } -storiesOf('WashTimeCell', module).add('Story of WashTimeCell', () => ( +storiesOf('WashTimeCell', module).add('WashTime', () => ( // eslint-disable-next-line react/react-in-jsx-scope )) -// import stories -// configure(() => { -// require('./stories') -// }, module) - // Refer to https://github.com/storybookjs/storybook/tree/master/app/react-native#start-command-parameters // To find allowed options for getStorybookUI const StorybookUIRoot = getStorybookUI({}) -// If you are using React Native vanilla and after installation you don't see your app name here, write it manually. -// If you use Expo you can safely remove this line. -// AppRegistry.registerComponent('HandWashTimer', () => StorybookUIRoot) - export default StorybookUIRoot