Merge branch 'refactoring-settings-view' into 'master'

Refactoring settings view

Closes #275

See merge request bloodyhealth/drip!147
This commit is contained in:
Julia Friesel
2019-01-10 08:06:32 +00:00
24 changed files with 211 additions and 288 deletions
+4 -4
View File
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
import { ScrollView } from 'react-native' import { ScrollView } from 'react-native'
import Hyperlink from 'react-native-hyperlink' import Hyperlink from 'react-native-hyperlink'
import AppText from '../app-text' import AppText from '../app-text'
import SettingsSegment from './settings-segment' import SettingsSegment from './shared/settings-segment'
import styles from '../../styles/index' import styles from '../../styles/index'
import labels, { links } from '../../i18n/en/settings' import labels, { links } from '../../i18n/en/settings'
import replace from '../helpers/replace-url-with-text' import replace from '../helpers/replace-url-with-text'
@@ -13,21 +13,21 @@ export default class AboutSection extends Component {
<ScrollView> <ScrollView>
<SettingsSegment title={labels.aboutSection.title}> <SettingsSegment title={labels.aboutSection.title}>
<Hyperlink linkStyle={styles.link} linkText={replace}> <Hyperlink linkStyle={styles.link} linkText={replace}>
<AppText>{`${labels.aboutSection.text} `}</AppText> <AppText>{labels.aboutSection.text}</AppText>
</Hyperlink> </Hyperlink>
</SettingsSegment> </SettingsSegment>
<SettingsSegment title={labels.philosophy.title}> <SettingsSegment title={labels.philosophy.title}>
<AppText>{labels.philosophy.text}</AppText> <AppText>{labels.philosophy.text}</AppText>
</SettingsSegment> </SettingsSegment>
<SettingsSegment title={labels.credits.title}> <SettingsSegment title={labels.credits.title}>
<AppText>{`${labels.credits.note}`}</AppText> <AppText>{labels.credits.note}</AppText>
</SettingsSegment> </SettingsSegment>
<SettingsSegment title={labels.website.title}> <SettingsSegment title={labels.website.title}>
<Hyperlink linkStyle={styles.link}> <Hyperlink linkStyle={styles.link}>
<AppText>{links.website.url}</AppText> <AppText>{links.website.url}</AppText>
</Hyperlink> </Hyperlink>
</SettingsSegment> </SettingsSegment>
<SettingsSegment title={labels.version.title} last={true}> <SettingsSegment title={labels.version.title} last>
<AppText>{require('../../package.json').version}</AppText> <AppText>{require('../../package.json').version}</AppText>
</SettingsSegment> </SettingsSegment>
</ScrollView> </ScrollView>
@@ -4,9 +4,9 @@ import { Alert, ToastAndroid } from 'react-native'
import { clearDb, isDbEmpty } from '../../../db' import { clearDb, isDbEmpty } from '../../../db'
import { hasEncryptionObservable } from '../../../local-storage' import { hasEncryptionObservable } from '../../../local-storage'
import SettingsButton from '../settings-button' import SettingsButton from '../shared/settings-button'
import ConfirmWithPassword from './confirm-with-password' import ConfirmWithPassword from '../shared/confirm-with-password'
import alertError from '../alert-error' import alertError from '../shared/alert-error'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
import { shared as sharedLabels } from '../../../i18n/en/labels' import { shared as sharedLabels } from '../../../i18n/en/labels'
@@ -2,7 +2,7 @@ import Share from 'react-native-share'
import { getCycleDaysSortedByDate } from '../../../db' import { getCycleDaysSortedByDate } from '../../../db'
import getDataAsCsvDataUri from '../../../lib/import-export/export-to-csv' import getDataAsCsvDataUri from '../../../lib/import-export/export-to-csv'
import alertError from '../alert-error' import alertError from '../shared/alert-error'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
import { EXPORT_FILE_NAME } from './constants' import { EXPORT_FILE_NAME } from './constants'
import RNFS from 'react-native-fs' import RNFS from 'react-native-fs'
@@ -4,7 +4,7 @@ import rnfs from 'react-native-fs'
import importCsv from '../../../lib/import-export/import-from-csv' import importCsv from '../../../lib/import-export/import-from-csv'
import { shared as sharedLabels } from '../../../i18n/en/labels' import { shared as sharedLabels } from '../../../i18n/en/labels'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
import alertError from '../alert-error' import alertError from '../shared/alert-error'
export default function openImportDialogAndImport() { export default function openImportDialogAndImport() {
Alert.alert( Alert.alert(
+3 -3
View File
@@ -1,8 +1,8 @@
import React from 'react' import React from 'react'
import { ScrollView } from 'react-native' import { ScrollView } from 'react-native'
import AppText from '../../app-text' import AppText from '../../app-text'
import SettingsSegment from '../settings-segment' import SettingsSegment from '../shared/settings-segment'
import SettingsButton from '../settings-button' import SettingsButton from '../shared/settings-button'
import openImportDialogAndImport from './import-dialog' import openImportDialogAndImport from './import-dialog'
import openShareDialogAndExport from './export-dialog' import openShareDialogAndExport from './export-dialog'
import DeleteData from './delete-data' import DeleteData from './delete-data'
@@ -25,7 +25,7 @@ const DataManagement = () => {
</SettingsSegment> </SettingsSegment>
<SettingsSegment <SettingsSegment
title={labels.deleteSegment.title} title={labels.deleteSegment.title}
last={true} last
> >
<AppText>{labels.deleteSegment.explainer}</AppText> <AppText>{labels.deleteSegment.explainer}</AppText>
<DeleteData /> <DeleteData />
+9 -9
View File
@@ -6,6 +6,7 @@ import Hyperlink from 'react-native-hyperlink'
import styles, { iconStyles } from '../../../styles' import styles, { iconStyles } from '../../../styles'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
import AppText from '../../app-text' import AppText from '../../app-text'
import SettingsSegment from '../shared/settings-segment'
import TempSlider from './temp-slider' import TempSlider from './temp-slider'
import UseCervixSetting from './use-cervix' import UseCervixSetting from './use-cervix'
import Icon from 'react-native-vector-icons/Entypo' import Icon from 'react-native-vector-icons/Entypo'
@@ -20,15 +21,14 @@ export default class Settings extends Component {
render() { render() {
return ( return (
<ScrollView> <ScrollView>
<UseCervixSetting/> <SettingsSegment title={labels.useCervix.title}>
<View style={styles.settingsSegment}> <UseCervixSetting/>
<AppText style={styles.settingsSegmentTitle}> </SettingsSegment>
{labels.tempScale.segmentTitle} <SettingsSegment title={labels.tempScale.segmentTitle}>
</AppText>
<AppText>{labels.tempScale.segmentExplainer}</AppText> <AppText>{labels.tempScale.segmentExplainer}</AppText>
<TempSlider/> <TempSlider/>
</View> </SettingsSegment>
<View style={[styles.settingsSegment, styles.settingsSegmentLast]}> <SettingsSegment style={styles.settingsSegmentLast} >
<View style={{flexDirection: 'row', alignItems: 'center'}}> <View style={{flexDirection: 'row', alignItems: 'center'}}>
<Icon name="info-with-circle" style={iconStyles.infoInHeading}/> <Icon name="info-with-circle" style={iconStyles.infoInHeading}/>
<AppText style={styles.settingsSegmentTitle}>{`${labels.preOvu.title} `}</AppText> <AppText style={styles.settingsSegmentTitle}>{`${labels.preOvu.title} `}</AppText>
@@ -36,8 +36,8 @@ export default class Settings extends Component {
<Hyperlink linkStyle={styles.link} linkText={replaceUrlWithText}> <Hyperlink linkStyle={styles.link} linkText={replaceUrlWithText}>
<AppText>{labels.preOvu.note}</AppText> <AppText>{labels.preOvu.note}</AppText>
</Hyperlink> </Hyperlink>
</View> </SettingsSegment>
</ScrollView> </ScrollView>
) )
} }
} }
@@ -9,7 +9,7 @@ import {
import { secondaryColor } from '../../../styles/index' import { secondaryColor } from '../../../styles/index'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
import config from '../../../config' import config from '../../../config'
import alertError from '../alert-error' import alertError from '../shared/alert-error'
export default class TempSlider extends Component { export default class TempSlider extends Component {
constructor(props) { constructor(props) {
+15 -24
View File
@@ -1,7 +1,6 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { import {
View, View,
TouchableOpacity,
Switch Switch
} from 'react-native' } from 'react-native'
import AppText from '../../app-text' import AppText from '../../app-text'
@@ -9,7 +8,6 @@ import {
useCervixObservable, useCervixObservable,
saveUseCervix saveUseCervix
} from '../../../local-storage' } from '../../../local-storage'
import styles from '../../../styles/index'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
export default class UseCervixSetting extends Component { export default class UseCervixSetting extends Component {
@@ -20,29 +18,22 @@ export default class UseCervixSetting extends Component {
render() { render() {
return ( return (
<TouchableOpacity <View style={{ flexDirection: 'row', alignItems: 'center' }}>
style={styles.settingsSegment} <View style={{ flex: 1 }}>
> {this.state.useCervix ?
<AppText style={styles.settingsSegmentTitle}> <AppText>{labels.useCervix.cervixModeOn}</AppText>
{labels.useCervix.title} :
</AppText> <AppText>{labels.useCervix.cervixModeOff}</AppText>
<View style={{ flexDirection: 'row', alignItems: 'center' }}> }
<View style={{ flex: 1 }}>
{this.state.useCervix ?
<AppText>{labels.useCervix.cervixModeOn}</AppText>
:
<AppText>{labels.useCervix.cervixModeOff}</AppText>
}
</View>
<Switch
value={this.state.useCervix}
onValueChange={bool => {
this.setState({ useCervix: bool })
saveUseCervix(bool)
}}
/>
</View> </View>
</TouchableOpacity> <Switch
value={this.state.useCervix}
onValueChange={bool => {
this.setState({ useCervix: bool })
saveUseCervix(bool)
}}
/>
</View>
) )
} }
} }
@@ -1,23 +0,0 @@
import { Alert } from 'react-native'
import { openDb } from '../../../db'
import { shared } from '../../../i18n/en/labels'
export default async function checkPassword({hash, onCancel, onTryAgain }) {
try {
await openDb(hash)
return true
} catch (err) {
Alert.alert(
shared.incorrectPassword,
shared.incorrectPasswordMessage,
[{
text: shared.cancel,
onPress: onCancel
}, {
text: shared.tryAgain,
onPress: onTryAgain
}]
)
return false
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ import React, { Component } from 'react'
import { View } from 'react-native' import { View } from 'react-native'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
import EnterNewPassword from './enter-new-password' import EnterNewPassword from './enter-new-password'
import SettingsButton from '../settings-button' import SettingsButton from '../shared/settings-button'
import showBackUpReminder from './show-backup-reminder' import showBackUpReminder from './show-backup-reminder'
export default class CreatePassword extends Component { export default class CreatePassword extends Component {
+27 -60
View File
@@ -1,80 +1,47 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import {
View,
TouchableOpacity
} from 'react-native'
import nodejs from 'nodejs-mobile-react-native'
import AppText from '../../app-text'
import styles from '../../../styles'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
import { requestHash, changeEncryptionAndRestartApp } from '../../../db' import { changeEncryptionAndRestartApp } from '../../../db'
import PasswordField from './password-field' import ConfirmWithPassword from '../shared/confirm-with-password'
import showBackUpReminder from './show-backup-reminder' import SettingsButton from '../shared/settings-button'
import checkCurrentPassword from './check-current-password'
export default class DeletePassword extends Component { export default class DeletePassword extends Component {
constructor() { constructor() {
super() super()
this.state = { this.state = {
enteringCurrentPassword: false, enteringCurrentPassword: false
currentPassword: null
} }
nodejs.channel.addListener(
'pre-delete-pw-check',
this.removeEncryption,
this
)
} }
componentWillUnmount() { startConfirmWithPassword = () => {
nodejs.channel.removeListener('pre-delete-pw-check', this.removeEncryption) this.setState({ enteringCurrentPassword: true })
this.props.onStartDeletingPassword()
} }
removeEncryption = async hash => { startDeletePassword = async () => {
const passwordIsCorrect = await checkCurrentPassword({ await changeEncryptionAndRestartApp()
hash, }
onTryAgain: () => this.setState({currentPassword: null}),
onCancel: () => this.setState({
enteringCurrentPassword: false,
currentPassword: null
})
})
if (passwordIsCorrect) await changeEncryptionAndRestartApp() cancelConfirmationWithPassword = () => {
this.setState({ enteringCurrentPassword: false })
} }
render() { render() {
const { enteringCurrentPassword } = this.state
if (enteringCurrentPassword) {
return (
<ConfirmWithPassword
onSuccess={this.startDeletePassword}
onCancel={this.cancelConfirmationWithPassword}
/>
)
}
return ( return (
<View> <SettingsButton onPress={this.startConfirmWithPassword} >
{this.state.enteringCurrentPassword && {labels.passwordSettings.deletePassword}
<PasswordField </SettingsButton>
onChangeText={val => this.setState({ currentPassword: val })}
value={this.state.currentPassword}
placeholder={labels.passwordSettings.enterCurrent}
/>
}
<TouchableOpacity
onPress={() => {
if (!this.state.enteringCurrentPassword) {
showBackUpReminder(() => {
this.setState({ enteringCurrentPassword: true })
}, true)
} else {
requestHash('pre-delete-pw-check', this.state.currentPassword)
}
}}
disabled={
this.state.enteringCurrentPassword &&
!this.state.currentPassword
}
style={styles.settingsButton}
>
<AppText style={styles.settingsButtonText}>
{labels.passwordSettings.deletePassword}
</AppText>
</TouchableOpacity>
</View>
) )
} }
} }
@@ -4,8 +4,8 @@ import nodejs from 'nodejs-mobile-react-native'
import { requestHash, changeEncryptionAndRestartApp } from '../../../db' import { requestHash, changeEncryptionAndRestartApp } from '../../../db'
import AppText from '../../app-text' import AppText from '../../app-text'
import PasswordField from './password-field' import PasswordField from '../shared/password-field'
import SettingsButton from '../settings-button' import SettingsButton from '../shared/settings-button'
import styles from '../../../styles' import styles from '../../../styles'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
+41 -20
View File
@@ -1,9 +1,9 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { View, ScrollView } from 'react-native' import { ScrollView } from 'react-native'
import CreatePassword from './create' import CreatePassword from './create'
import ChangePassword from './update' import ChangePassword from './update'
import DeletePassword from './delete' import DeletePassword from './delete'
import SettingsSegment from '../settings-segment' import SettingsSegment from '../shared/settings-segment'
import AppText from '../../app-text' import AppText from '../../app-text'
import { import {
hasEncryptionObservable hasEncryptionObservable
@@ -14,33 +14,54 @@ export default class PasswordSetting extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = { this.state = {
showUpdateAndDelete: hasEncryptionObservable.value, isPasswordSet: hasEncryptionObservable.value,
showCreate: !hasEncryptionObservable.value isChangingPassword: false,
isDeletingPassword: false
} }
} }
onChangingPassword = () => {
this.setState({ isChangingPassword: true })
}
onDeletingPassword = () => {
this.setState({ isDeletingPassword: true })
}
render() { render() {
const {
isPasswordSet,
isChangingPassword,
isDeletingPassword,
} = this.state
const {
title,
explainerEnabled,
explainerDisabled
} = labels.passwordSettings
return ( return (
<ScrollView> <ScrollView>
<SettingsSegment title={labels.passwordSettings.title}> <SettingsSegment title={title}>
<AppText>
{ isPasswordSet ? explainerEnabled : explainerDisabled }
</AppText>
{this.state.showUpdateAndDelete ? { !isPasswordSet && <CreatePassword/> }
<AppText>{labels.passwordSettings.explainerEnabled}</AppText>
:
<AppText>{labels.passwordSettings.explainerDisabled}</AppText>
}
{this.state.showUpdateAndDelete && { (isPasswordSet && !isDeletingPassword) && (
<View> <ChangePassword
<ChangePassword/> onStartChangingPassword = {this.onChangingPassword}
<DeletePassword/> />
</View> )}
}
{this.state.showCreate &&
<CreatePassword/>
}
{ (isPasswordSet && !isChangingPassword) && (
<DeletePassword
onStartDeletingPassword = {this.onDeletingPassword}
/>
)}
</SettingsSegment> </SettingsSegment>
</ScrollView> </ScrollView>
) )
+25 -61
View File
@@ -1,14 +1,9 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { View } from 'react-native'
import nodejs from 'nodejs-mobile-react-native'
import { shared as sharedLabels } from '../../../i18n/en/labels'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
import { requestHash } from '../../../db'
import EnterNewPassword from './enter-new-password' import EnterNewPassword from './enter-new-password'
import PasswordField from './password-field' import SettingsButton from '../shared/settings-button'
import SettingsButton from '../settings-button'
import showBackUpReminder from './show-backup-reminder' import showBackUpReminder from './show-backup-reminder'
import checkCurrentPassword from './check-current-password' import ConfirmWithPassword from '../shared/confirm-with-password'
export default class ChangePassword extends Component { export default class ChangePassword extends Component {
@@ -19,49 +14,29 @@ export default class ChangePassword extends Component {
enteringCurrentPassword: false, enteringCurrentPassword: false,
enteringNewPassword: false enteringNewPassword: false
} }
nodejs.channel.addListener(
'pre-change-pw-check',
this.openNewPasswordField,
this
)
}
componentWillUnmount() {
nodejs.channel.removeListener('pre-change-pw-check', this.openNewPasswordField)
}
openNewPasswordField = async hash => {
const passwordCorrect = await checkCurrentPassword({
hash,
onTryAgain: () => this.setState({ currentPassword: null }),
onCancel: () => this.setState({
enteringCurrentPassword: false,
currentPassword: null
})
})
if (passwordCorrect) {
this.setState({
currentPassword: null,
enteringNewPassword: true,
enteringCurrentPassword: false
})
}
} }
startChangingPassword = () => { startChangingPassword = () => {
showBackUpReminder(() => { showBackUpReminder(() => {
this.setState({ enteringCurrentPassword: true }) this.setState({ enteringCurrentPassword: true })
}) })
this.props.onStartChangingPassword()
} }
handleCurrentPasswordInput = (currentPassword) => { startEnteringNewPassword = () => {
this.setState({ currentPassword }) this.setState({
currentPassword: null,
enteringNewPassword: true,
enteringCurrentPassword: false
})
} }
checkCurrentPassword = () => { cancelConfirmationWithPassword = () => {
requestHash('pre-change-pw-check', this.state.currentPassword) this.setState({
currentPassword: null,
enteringNewPassword: false,
enteringCurrentPassword: false
})
} }
render() { render() {
@@ -76,19 +51,10 @@ export default class ChangePassword extends Component {
if (enteringCurrentPassword) { if (enteringCurrentPassword) {
return ( return (
<View> <ConfirmWithPassword
<PasswordField onSuccess={this.startEnteringNewPassword}
placeholder={labels.enterCurrent} onCancel={this.cancelConfirmationWithPassword}
value={currentPassword} />
onChangeText={this.handleCurrentPasswordInput}
/>
<SettingsButton
onPress={this.checkCurrentPassword}
disabled={!currentPassword}
>
{sharedLabels.unlock}
</SettingsButton>
</View>
) )
} }
@@ -97,14 +63,12 @@ export default class ChangePassword extends Component {
} }
return ( return (
<View> <SettingsButton
<SettingsButton onPress={this.startChangingPassword}
onPress={this.startChangingPassword} disabled={currentPassword}
disabled={currentPassword} >
> {labels.changePassword}
{labels.changePassword} </SettingsButton>
</SettingsButton>
</View>
) )
} }
} }
+9 -2
View File
@@ -2,9 +2,12 @@ import React, { Component } from 'react'
import { import {
ScrollView, ScrollView,
} from 'react-native' } from 'react-native'
import SettingsSegment from '../shared/settings-segment'
import TempReminderPicker from './temp-reminder-picker' import TempReminderPicker from './temp-reminder-picker'
import PeriodReminderPicker from './period-reminder' import PeriodReminderPicker from './period-reminder'
import labels from '../../../i18n/en/settings'
export default class Settings extends Component { export default class Settings extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
@@ -14,8 +17,12 @@ export default class Settings extends Component {
render() { render() {
return ( return (
<ScrollView> <ScrollView>
<TempReminderPicker/> <SettingsSegment title={labels.tempReminder.title}>
<PeriodReminderPicker/> <TempReminderPicker/>
</SettingsSegment>
<SettingsSegment title={labels.periodReminder.title}>
<PeriodReminderPicker/>
</SettingsSegment>
</ScrollView> </ScrollView>
) )
} }
@@ -8,7 +8,6 @@ import {
periodReminderObservable, periodReminderObservable,
savePeriodReminder savePeriodReminder
} from '../../../local-storage' } from '../../../local-storage'
import styles from '../../../styles/index'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
export default class PeriodReminderPicker extends Component { export default class PeriodReminderPicker extends Component {
@@ -19,22 +18,17 @@ export default class PeriodReminderPicker extends Component {
render() { render() {
return ( return (
<View style={styles.settingsSegment}> <View style={{ flexDirection: 'row', alignItems: 'center' }}>
<AppText style={styles.settingsSegmentTitle}> <View style={{ flex: 1 }}>
{labels.periodReminder.title} <AppText>{labels.periodReminder.reminderText}</AppText>
</AppText>
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View style={{ flex: 1 }}>
<AppText>{labels.periodReminder.reminderText}</AppText>
</View>
<Switch
value={this.state.enabled}
onValueChange={switchOn => {
this.setState({ enabled: switchOn })
savePeriodReminder({enabled: switchOn})
}}
/>
</View> </View>
<Switch
value={this.state.enabled}
onValueChange={switchOn => {
this.setState({ enabled: switchOn })
savePeriodReminder({enabled: switchOn})
}}
/>
</View> </View>
) )
} }
@@ -10,64 +10,63 @@ import {
tempReminderObservable, tempReminderObservable,
saveTempReminder saveTempReminder
} from '../../../local-storage' } from '../../../local-storage'
import styles from '../../../styles/index'
import labels from '../../../i18n/en/settings' import labels from '../../../i18n/en/settings'
import padWithZeros from '../../helpers/pad-time-with-zeros' import padWithZeros from '../../helpers/pad-time-with-zeros'
export default class TempReminderPicker extends Component { export default class TempReminderPicker extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
this.state = Object.assign({}, tempReminderObservable.value) const { time, enabled } = tempReminderObservable.value
this.state = {
time,
enabled,
isTimePickerVisible: false
}
} }
render() { render() {
return ( return (
<TouchableOpacity <TouchableOpacity
style={styles.settingsSegment} style={{ flexDirection: 'row', alignItems: 'center' }}
onPress={() => this.setState({ isTimePickerVisible: true })} onPress={() => this.setState({ isTimePickerVisible: true })}
> >
<AppText style={styles.settingsSegmentTitle}> <View style={{ flex: 1 }}>
{labels.tempReminder.title} {this.state.time && this.state.enabled ?
</AppText> <AppText>{labels.tempReminder.timeSet(this.state.time)}</AppText>
<View style={{ flexDirection: 'row', alignItems: 'center' }}> :
<View style={{ flex: 1 }}> <AppText>{labels.tempReminder.noTimeSet}</AppText>
{this.state.time && this.state.enabled ? }
<AppText>{labels.tempReminder.timeSet(this.state.time)}</AppText>
:
<AppText>{labels.tempReminder.noTimeSet}</AppText>
}
</View>
<Switch
value={this.state.enabled}
onValueChange={switchOn => {
this.setState({ enabled: switchOn })
if (switchOn && !this.state.time) {
this.setState({ isTimePickerVisible: true })
}
if (!switchOn) saveTempReminder({ enabled: false })
}}
/>
<DateTimePicker
mode="time"
isVisible={this.state.isTimePickerVisible}
onConfirm={jsDate => {
const time = padWithZeros(jsDate)
this.setState({
time,
isTimePickerVisible: false,
enabled: true
})
saveTempReminder({
time,
enabled: true
})
}}
onCancel={() => {
this.setState({ isTimePickerVisible: false })
if (!this.state.time) this.setState({enabled: false})
}}
/>
</View> </View>
<Switch
value={this.state.enabled}
onValueChange={switchOn => {
this.setState({ enabled: switchOn })
if (switchOn && !this.state.time) {
this.setState({ isTimePickerVisible: true })
}
if (!switchOn) saveTempReminder({ enabled: false })
}}
/>
<DateTimePicker
mode="time"
isVisible={this.state.isTimePickerVisible}
onConfirm={jsDate => {
const time = padWithZeros(jsDate)
this.setState({
time,
isTimePickerVisible: false,
enabled: true
})
saveTempReminder({
time,
enabled: true
})
}}
onCancel={() => {
this.setState({ isTimePickerVisible: false })
if (!this.state.time) this.setState({enabled: false})
}}
/>
</TouchableOpacity> </TouchableOpacity>
) )
} }
@@ -1,5 +1,5 @@
import { Alert } from 'react-native' import { Alert } from 'react-native'
import { shared as sharedLabels } from '../../i18n/en/labels' import { shared as sharedLabels } from '../../../i18n/en/labels'
export default function alertError(msg) { export default function alertError(msg) {
Alert.alert(sharedLabels.errorTitle, msg) Alert.alert(sharedLabels.errorTitle, msg)
@@ -4,8 +4,8 @@ import { View, Alert } from 'react-native'
import nodejs from 'nodejs-mobile-react-native' import nodejs from 'nodejs-mobile-react-native'
import { requestHash, openDb } from '../../../db' import { requestHash, openDb } from '../../../db'
import PasswordField from '../password/password-field' import PasswordField from './password-field'
import SettingsButton from '../settings-button' import SettingsButton from '../shared/settings-button'
import settings from '../../../i18n/en/settings' import settings from '../../../i18n/en/settings'
import { shared } from '../../../i18n/en/labels' import { shared } from '../../../i18n/en/labels'
@@ -79,7 +79,7 @@ export default class ConfirmWithPassword extends Component {
onPress={this.initPasswordCheck} onPress={this.initPasswordCheck}
disabled={!password} disabled={!password}
> >
{settings.deleteSegment.title} {shared.confirmToProceed}
</SettingsButton> </SettingsButton>
</View> </View>
) )
@@ -2,8 +2,8 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { TouchableOpacity } from 'react-native' import { TouchableOpacity } from 'react-native'
import AppText from '../app-text' import AppText from '../../app-text'
import styles from '../../styles' import styles from '../../../styles'
const SettingsButton = ({ children, ...props }) => { const SettingsButton = ({ children, ...props }) => {
return ( return (
@@ -2,22 +2,25 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { View } from 'react-native' import { View } from 'react-native'
import AppText from '../app-text' import AppText from '../../app-text'
import styles from '../../styles' import styles from '../../../styles'
const SettingsSegment = ({ children, ...props }) => { const SettingsSegment = ({ children, ...props }) => {
const style = [styles.settingsSegment, props.style] const style = [styles.settingsSegment, props.style]
if (props.last) style.push(styles.settingsSegmentLast) if (props.last) style.push(styles.settingsSegmentLast)
return ( return (
<View style={style}> <View style={[styles.settingsSegment, props.style]}>
<AppText style={styles.settingsSegmentTitle}>{props.title}</AppText> {
props.title
&& <AppText style={styles.settingsSegmentTitle}>{props.title}</AppText>
}
{children} {children}
</View> </View>
) )
} }
SettingsSegment.propTypes = { SettingsSegment.propTypes = {
title: PropTypes.string.isRequired title: PropTypes.string
} }
export default SettingsSegment export default SettingsSegment
+1 -1
View File
@@ -11,7 +11,7 @@ export const shared = {
incorrectPasswordMessage: 'That password is incorrect.', incorrectPasswordMessage: 'That password is incorrect.',
tryAgain: 'Try again', tryAgain: 'Try again',
ok: 'OK', ok: 'OK',
unlock: 'Unlock', confirmToProceed: 'Confirm to proceed',
date: 'Date', date: 'Date',
cycleDayWithLinebreak: 'Cycle\nday', cycleDayWithLinebreak: 'Cycle\nday',
loading: 'Loading ...', loading: 'Loading ...',
+1 -1
View File
@@ -2,7 +2,7 @@ import {tempReminderObservable, periodReminderObservable} from '../local-storage
import Notification from 'react-native-push-notification' import Notification from 'react-native-push-notification'
import { LocalDate } from 'js-joda' import { LocalDate } from 'js-joda'
import Moment from 'moment' import Moment from 'moment'
import { settings as labels } from '../i18n/en/settings' import labels from '../i18n/en/settings'
import { getBleedingDaysSortedByDate } from '../db' import { getBleedingDaysSortedByDate } from '../db'
import cycleModule from './cycle' import cycleModule from './cycle'
import nothingChanged from '../db/db-unchanged' import nothingChanged from '../db/db-unchanged'