Post-review updates
This commit is contained in:
@@ -0,0 +1,93 @@
|
|||||||
|
import React, { Component } from 'react'
|
||||||
|
import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native'
|
||||||
|
|
||||||
|
import AppIcon from '../common/app-icon'
|
||||||
|
import MenuItem from './menu-item'
|
||||||
|
|
||||||
|
import { Colors, Sizes } from '../../styles/redesign'
|
||||||
|
import settingsLabels from '../../i18n/en/settings'
|
||||||
|
|
||||||
|
const { menuItems } = settingsLabels
|
||||||
|
|
||||||
|
const settingsMenuItems = [
|
||||||
|
{ name: menuItems.settings, component: 'SettingsMenu' },
|
||||||
|
{ name: menuItems.about, component: 'About' },
|
||||||
|
{ name: menuItems.license, component: 'License' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export default class HamburgerMenu extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = { shouldShowMenu: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMenu = () => {
|
||||||
|
this.setState({ shouldShowMenu: !this.state.shouldShowMenu})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { shouldShowMenu } = this.state
|
||||||
|
|
||||||
|
return(
|
||||||
|
<React.Fragment>
|
||||||
|
{!shouldShowMenu &&
|
||||||
|
<TouchableOpacity onPress={this.toggleMenu}>
|
||||||
|
<AppIcon name='dots-three-vertical' color={Colors.orange}/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
}
|
||||||
|
{shouldShowMenu &&
|
||||||
|
<Modal
|
||||||
|
animationType='fade'
|
||||||
|
onRequestClose={this.toggleMenu}
|
||||||
|
transparent={true}
|
||||||
|
visible={shouldShowMenu}
|
||||||
|
>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={this.toggleMenu}
|
||||||
|
style={styles.blackBackground}
|
||||||
|
>
|
||||||
|
</TouchableOpacity>
|
||||||
|
<View style={styles.menu}>
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={this.toggleMenu}
|
||||||
|
style={styles.iconContainer}
|
||||||
|
>
|
||||||
|
<AppIcon name='cross' color='black'/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
{settingsMenuItems.map(item =>
|
||||||
|
<MenuItem
|
||||||
|
item={item}
|
||||||
|
key={item.name}
|
||||||
|
closeMenu={this.toggleMenu}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
blackBackground: {
|
||||||
|
backgroundColor: 'black',
|
||||||
|
flex: 1,
|
||||||
|
opacity: 0.65,
|
||||||
|
},
|
||||||
|
iconContainer: {
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
marginBottom: Sizes.base
|
||||||
|
},
|
||||||
|
menu: {
|
||||||
|
alignSelf: 'flex-end',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
height: '100%',
|
||||||
|
padding: Sizes.base,
|
||||||
|
position: 'absolute',
|
||||||
|
width: '60%'
|
||||||
|
}
|
||||||
|
})
|
||||||
+14
-31
@@ -1,43 +1,24 @@
|
|||||||
import React, { Component } from 'react'
|
import React from 'react'
|
||||||
import { StyleSheet, View } from 'react-native'
|
import { StyleSheet, View } from 'react-native'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import Logo from './logo'
|
import Logo from './logo'
|
||||||
import SideMenu from './side-menu'
|
import HamburgerMenu from './hamburger-menu'
|
||||||
|
|
||||||
import { Colors, Containers, Sizes } from '../../styles/redesign'
|
import { Colors, Containers, Sizes } from '../../styles/redesign'
|
||||||
|
|
||||||
export default class Header extends Component {
|
const Header = ({ isSideMenuEnabled }) => {
|
||||||
static propTypes = {
|
|
||||||
isSideMenuEnabled: PropTypes.bool
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
return (
|
||||||
super(props)
|
<View style={styles.header}>
|
||||||
|
<Logo />
|
||||||
|
{isSideMenuEnabled && <HamburgerMenu />}
|
||||||
|
</View >
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
this.state = { shouldShowMenu: false }
|
Header.propTypes = {
|
||||||
}
|
isSideMenuEnabled: PropTypes.bool
|
||||||
|
|
||||||
toggleMenu = () => {
|
|
||||||
this.setState({ shouldShowMenu: !this.state.shouldShowMenu})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { isSideMenuEnabled } = this.props
|
|
||||||
const { shouldShowMenu } = this.state
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View style={styles.header}>
|
|
||||||
<Logo />
|
|
||||||
{isSideMenuEnabled &&
|
|
||||||
<SideMenu
|
|
||||||
shouldShowMenu={shouldShowMenu}
|
|
||||||
toggleMenu={this.toggleMenu}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
</View >
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Header.defaultProps = {
|
Header.defaultProps = {
|
||||||
@@ -51,3 +32,5 @@ const styles = StyleSheet.create({
|
|||||||
...Containers.rowContainer
|
...Containers.rowContainer
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export default Header
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import { Modal, StyleSheet, TouchableOpacity, View } from 'react-native'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
|
|
||||||
import AppIcon from '../common/app-icon'
|
|
||||||
import MenuItem from './menu-item'
|
|
||||||
|
|
||||||
import { Colors, Sizes } from '../../styles/redesign'
|
|
||||||
import settingsLabels from '../../i18n/en/settings'
|
|
||||||
|
|
||||||
const { menuItems } = settingsLabels
|
|
||||||
|
|
||||||
const settingsMenuItems = [
|
|
||||||
{ name: menuItems.settings, component: 'SettingsMenu' },
|
|
||||||
{ name: menuItems.about, component: 'About' },
|
|
||||||
{ name: menuItems.license, component: 'License' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const SideMenu = ({ shouldShowMenu, toggleMenu }) => {
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
{!shouldShowMenu &&
|
|
||||||
<TouchableOpacity onPress={toggleMenu}>
|
|
||||||
<AppIcon name='dots-three-vertical' color={Colors.orange}/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
}
|
|
||||||
{shouldShowMenu &&
|
|
||||||
<Modal
|
|
||||||
animationType='fade'
|
|
||||||
onRequestClose={toggleMenu}
|
|
||||||
transparent={true}
|
|
||||||
visible={shouldShowMenu}
|
|
||||||
>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={toggleMenu}
|
|
||||||
style={styles.blackBackground}
|
|
||||||
>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<View style={styles.menu}>
|
|
||||||
<TouchableOpacity onPress={toggleMenu} style={styles.iconContainer}>
|
|
||||||
<AppIcon name='cross' color='black'/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
{settingsMenuItems.map(item =>
|
|
||||||
<MenuItem
|
|
||||||
item={item}
|
|
||||||
key={item.name}
|
|
||||||
closeMenu={toggleMenu}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</Modal>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SideMenu.propTypes = {
|
|
||||||
shouldShowMenu: PropTypes.bool.isRequired,
|
|
||||||
toggleMenu: PropTypes.func
|
|
||||||
}
|
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
blackBackground: {
|
|
||||||
backgroundColor: 'black',
|
|
||||||
flex: 1,
|
|
||||||
opacity: 0.65,
|
|
||||||
},
|
|
||||||
iconContainer: {
|
|
||||||
alignSelf: 'flex-end',
|
|
||||||
marginBottom: Sizes.base
|
|
||||||
},
|
|
||||||
menu: {
|
|
||||||
alignSelf: 'flex-end',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
height: '100%',
|
|
||||||
padding: Sizes.base,
|
|
||||||
position: 'absolute',
|
|
||||||
width: '60%'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default SideMenu
|
|
||||||
@@ -22,14 +22,14 @@ export default function License({ setLicense }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppPage testID='licensePage'>
|
<AppPage testID="licensePage">
|
||||||
<Segment last testID='test' title={labels.title}>
|
<Segment last testID="test" title={labels.title}>
|
||||||
<AppText testID='test'>{labels.text}</AppText>
|
<AppText testID="test">{labels.text}</AppText>
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Button onPress={BackHandler.exitApp} testID='licenseCancelButton'>
|
<Button onPress={BackHandler.exitApp} testID="licenseCancelButton">
|
||||||
{shared.cancel}
|
{shared.cancel}
|
||||||
</Button>
|
</Button>
|
||||||
<Button isCTA onPress={onAcceptLicense} testID='licenseOkButton'>
|
<Button isCTA onPress={onAcceptLicense} testID="licenseOkButton">
|
||||||
{shared.ok}
|
{shared.ok}
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default class PasswordPrompt extends Component {
|
|||||||
shared.incorrectPasswordMessage,
|
shared.incorrectPasswordMessage,
|
||||||
[{
|
[{
|
||||||
text: shared.tryAgain,
|
text: shared.tryAgain,
|
||||||
onPress: this.setPassword(null)
|
onPress: () => this.setState({ password: null })
|
||||||
}]
|
}]
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
@@ -72,10 +72,6 @@ export default class PasswordPrompt extends Component {
|
|||||||
this.props.enableShowApp()
|
this.props.enableShowApp()
|
||||||
}
|
}
|
||||||
|
|
||||||
setPassword = (password) => {
|
|
||||||
this.setState({ password })
|
|
||||||
}
|
|
||||||
|
|
||||||
unlockApp = () => {
|
unlockApp = () => {
|
||||||
requestHash('check-pw', this.state.password)
|
requestHash('check-pw', this.state.password)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-11
@@ -16,25 +16,23 @@ const image = require('../assets/cycle-icon.png')
|
|||||||
|
|
||||||
const Stats = () => {
|
const Stats = () => {
|
||||||
const cycleLengths = cycleModule().getAllCycleLengths()
|
const cycleLengths = cycleModule().getAllCycleLengths()
|
||||||
const atLeastOneCycle = cycleLengths.length >= 1
|
|
||||||
const numberOfCycles = cycleLengths.length
|
const numberOfCycles = cycleLengths.length
|
||||||
let cycleData
|
const hasAtLeastOneCycle = numberOfCycles >= 1
|
||||||
if (atLeastOneCycle) {
|
const cycleData = hasAtLeastOneCycle ? getCycleInfo(cycleLengths)
|
||||||
cycleData = getCycleInfo(cycleLengths)
|
: { minimum: '—', maximum: '—', stdDeviation: '—' }
|
||||||
}
|
|
||||||
|
|
||||||
const statsData = [
|
const statsData = [
|
||||||
[atLeastOneCycle ? cycleData.minimum : 0, labels.minLabel],
|
[cycleData.minimum, labels.minLabel],
|
||||||
[atLeastOneCycle ? cycleData.maximum : 0, labels.maxLabel],
|
[cycleData.maximum, labels.maxLabel],
|
||||||
[atLeastOneCycle && cycleData.stdDeviation ? cycleData.stdDeviation : '—', labels.stdLabel],
|
[cycleData.stdDeviation ? cycleData.stdDeviation : '—', labels.stdLabel],
|
||||||
[numberOfCycles, labels.basisOfStatsEnd]
|
[numberOfCycles, labels.basisOfStatsEnd]
|
||||||
]
|
]
|
||||||
return (
|
return (
|
||||||
<AppPage>
|
<AppPage>
|
||||||
<Segment last style={styles.pageContainer}>
|
<Segment last style={styles.pageContainer}>
|
||||||
<AppText>{labels.cycleLengthExplainer}</AppText>
|
<AppText>{labels.cycleLengthExplainer}</AppText>
|
||||||
{!atLeastOneCycle && <AppText>{labels.emptyStats}</AppText>}
|
{!hasAtLeastOneCycle && <AppText>{labels.emptyStats}</AppText>}
|
||||||
{atLeastOneCycle &&
|
{hasAtLeastOneCycle &&
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<View style={styles.columnLeft}>
|
<View style={styles.columnLeft}>
|
||||||
<ImageBackground
|
<ImageBackground
|
||||||
@@ -77,7 +75,7 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
accentPurpleGiant: {
|
accentPurpleGiant: {
|
||||||
...Typography.accentPurpleGiant,
|
...Typography.accentPurpleGiant,
|
||||||
marginVertical: Sizes.giant * (-0.5)
|
marginVertical: -25
|
||||||
},
|
},
|
||||||
accentPurpleHuge: {
|
accentPurpleHuge: {
|
||||||
...Typography.accentPurpleHuge,
|
...Typography.accentPurpleHuge,
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ export const sizes = {
|
|||||||
base: 18,
|
base: 18,
|
||||||
subtitle: 22,
|
subtitle: 22,
|
||||||
title: 24,
|
title: 24,
|
||||||
big: 30,
|
huge: 40
|
||||||
huge: 40,
|
|
||||||
giant: 50
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = {
|
const title = {
|
||||||
@@ -30,12 +28,12 @@ const accentText = {
|
|||||||
|
|
||||||
const accentTextBig = {
|
const accentTextBig = {
|
||||||
...accentText,
|
...accentText,
|
||||||
fontSize: sizes.big,
|
fontSize: 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
const accentTextGiant = {
|
const accentTextGiant = {
|
||||||
...accentText,
|
...accentText,
|
||||||
fontSize: sizes.giant,
|
fontSize: 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
const accentTextHuge = {
|
const accentTextHuge = {
|
||||||
|
|||||||
Reference in New Issue
Block a user