diff --git a/components/settings/about.js b/components/settings/about.js index 6ee5451..9e33402 100644 --- a/components/settings/about.js +++ b/components/settings/about.js @@ -2,7 +2,7 @@ import React, { Component } from 'react' import { ScrollView } from 'react-native' import Hyperlink from 'react-native-hyperlink' import AppText from '../app-text' -import SettingsSegment from './settings-segment' +import SettingsSegment from './shared/settings-segment' import styles from '../../styles/index' import labels, { links } from '../../i18n/en/settings' import replace from '../helpers/replace-url-with-text' @@ -13,21 +13,21 @@ export default class AboutSection extends Component { - {`${labels.aboutSection.text} `} + {labels.aboutSection.text} {labels.philosophy.text} - {`${labels.credits.note}`} + {labels.credits.note} {links.website.url} - + {require('../../package.json').version} diff --git a/components/settings/data-management/delete-data.js b/components/settings/data-management/delete-data.js index dd09c4a..581c881 100644 --- a/components/settings/data-management/delete-data.js +++ b/components/settings/data-management/delete-data.js @@ -4,9 +4,9 @@ import { Alert, ToastAndroid } from 'react-native' import { clearDb, isDbEmpty } from '../../../db' import { hasEncryptionObservable } from '../../../local-storage' -import SettingsButton from '../settings-button' -import ConfirmWithPassword from './confirm-with-password' -import alertError from '../alert-error' +import SettingsButton from '../shared/settings-button' +import ConfirmWithPassword from '../shared/confirm-with-password' +import alertError from '../shared/alert-error' import settings from '../../../i18n/en/settings' import { shared as sharedLabels } from '../../../i18n/en/labels' diff --git a/components/settings/data-management/export-dialog.js b/components/settings/data-management/export-dialog.js index cfc5f5d..4b47c2c 100644 --- a/components/settings/data-management/export-dialog.js +++ b/components/settings/data-management/export-dialog.js @@ -2,7 +2,7 @@ import Share from 'react-native-share' import { getCycleDaysSortedByDate } from '../../../db' 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 { EXPORT_FILE_NAME } from './constants' import RNFS from 'react-native-fs' diff --git a/components/settings/data-management/import-dialog.js b/components/settings/data-management/import-dialog.js index 2ff977e..5971c4b 100644 --- a/components/settings/data-management/import-dialog.js +++ b/components/settings/data-management/import-dialog.js @@ -4,7 +4,7 @@ import rnfs from 'react-native-fs' import importCsv from '../../../lib/import-export/import-from-csv' import { shared as sharedLabels } from '../../../i18n/en/labels' import labels from '../../../i18n/en/settings' -import alertError from '../alert-error' +import alertError from '../shared/alert-error' export default function openImportDialogAndImport() { Alert.alert( diff --git a/components/settings/data-management/index.js b/components/settings/data-management/index.js index 93887b8..43b4f48 100644 --- a/components/settings/data-management/index.js +++ b/components/settings/data-management/index.js @@ -1,8 +1,8 @@ import React from 'react' import { ScrollView } from 'react-native' import AppText from '../../app-text' -import SettingsSegment from '../settings-segment' -import SettingsButton from '../settings-button' +import SettingsSegment from '../shared/settings-segment' +import SettingsButton from '../shared/settings-button' import openImportDialogAndImport from './import-dialog' import openShareDialogAndExport from './export-dialog' import DeleteData from './delete-data' @@ -25,7 +25,7 @@ const DataManagement = () => { {labels.deleteSegment.explainer} diff --git a/components/settings/nfp-settings/index.js b/components/settings/nfp-settings/index.js index c4810bc..a95c5de 100644 --- a/components/settings/nfp-settings/index.js +++ b/components/settings/nfp-settings/index.js @@ -6,6 +6,7 @@ import Hyperlink from 'react-native-hyperlink' import styles, { iconStyles } from '../../../styles' import labels from '../../../i18n/en/settings' import AppText from '../../app-text' +import SettingsSegment from '../shared/settings-segment' import TempSlider from './temp-slider' import UseCervixSetting from './use-cervix' import Icon from 'react-native-vector-icons/Entypo' @@ -20,15 +21,14 @@ export default class Settings extends Component { render() { return ( - - - - {labels.tempScale.segmentTitle} - + + + + {labels.tempScale.segmentExplainer} - - + + {`${labels.preOvu.title} `} @@ -36,8 +36,8 @@ export default class Settings extends Component { {labels.preOvu.note} - + ) } -} +} \ No newline at end of file diff --git a/components/settings/nfp-settings/temp-slider.js b/components/settings/nfp-settings/temp-slider.js index 9dcdfb9..ecccaf4 100644 --- a/components/settings/nfp-settings/temp-slider.js +++ b/components/settings/nfp-settings/temp-slider.js @@ -9,7 +9,7 @@ import { import { secondaryColor } from '../../../styles/index' import labels from '../../../i18n/en/settings' import config from '../../../config' -import alertError from '../alert-error' +import alertError from '../shared/alert-error' export default class TempSlider extends Component { constructor(props) { diff --git a/components/settings/nfp-settings/use-cervix.js b/components/settings/nfp-settings/use-cervix.js index ecfe5d3..2bb9ff9 100644 --- a/components/settings/nfp-settings/use-cervix.js +++ b/components/settings/nfp-settings/use-cervix.js @@ -1,7 +1,6 @@ import React, { Component } from 'react' import { View, - TouchableOpacity, Switch } from 'react-native' import AppText from '../../app-text' @@ -9,7 +8,6 @@ import { useCervixObservable, saveUseCervix } from '../../../local-storage' -import styles from '../../../styles/index' import labels from '../../../i18n/en/settings' export default class UseCervixSetting extends Component { @@ -20,29 +18,22 @@ export default class UseCervixSetting extends Component { render() { return ( - - - {labels.useCervix.title} - - - - {this.state.useCervix ? - {labels.useCervix.cervixModeOn} - : - {labels.useCervix.cervixModeOff} - } - - { - this.setState({ useCervix: bool }) - saveUseCervix(bool) - }} - /> + + + {this.state.useCervix ? + {labels.useCervix.cervixModeOn} + : + {labels.useCervix.cervixModeOff} + } - + { + this.setState({ useCervix: bool }) + saveUseCervix(bool) + }} + /> + ) } } diff --git a/components/settings/password/check-current-password.js b/components/settings/password/check-current-password.js deleted file mode 100644 index 92d78bf..0000000 --- a/components/settings/password/check-current-password.js +++ /dev/null @@ -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 - } -} \ No newline at end of file diff --git a/components/settings/password/create.js b/components/settings/password/create.js index cdc9b69..aaa021d 100644 --- a/components/settings/password/create.js +++ b/components/settings/password/create.js @@ -2,7 +2,7 @@ import React, { Component } from 'react' import { View } from 'react-native' import settings from '../../../i18n/en/settings' import EnterNewPassword from './enter-new-password' -import SettingsButton from '../settings-button' +import SettingsButton from '../shared/settings-button' import showBackUpReminder from './show-backup-reminder' export default class CreatePassword extends Component { diff --git a/components/settings/password/delete.js b/components/settings/password/delete.js index 6cef844..b6435a0 100644 --- a/components/settings/password/delete.js +++ b/components/settings/password/delete.js @@ -1,80 +1,47 @@ 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 { requestHash, changeEncryptionAndRestartApp } from '../../../db' -import PasswordField from './password-field' -import showBackUpReminder from './show-backup-reminder' -import checkCurrentPassword from './check-current-password' +import { changeEncryptionAndRestartApp } from '../../../db' +import ConfirmWithPassword from '../shared/confirm-with-password' +import SettingsButton from '../shared/settings-button' export default class DeletePassword extends Component { constructor() { super() this.state = { - enteringCurrentPassword: false, - currentPassword: null + enteringCurrentPassword: false } - - nodejs.channel.addListener( - 'pre-delete-pw-check', - this.removeEncryption, - this - ) } - componentWillUnmount() { - nodejs.channel.removeListener('pre-delete-pw-check', this.removeEncryption) + startConfirmWithPassword = () => { + this.setState({ enteringCurrentPassword: true }) + this.props.onStartDeletingPassword() } - removeEncryption = async hash => { - const passwordIsCorrect = await checkCurrentPassword({ - hash, - onTryAgain: () => this.setState({currentPassword: null}), - onCancel: () => this.setState({ - enteringCurrentPassword: false, - currentPassword: null - }) - }) + startDeletePassword = async () => { + await changeEncryptionAndRestartApp() + } - if (passwordIsCorrect) await changeEncryptionAndRestartApp() + cancelConfirmationWithPassword = () => { + this.setState({ enteringCurrentPassword: false }) } render() { + + const { enteringCurrentPassword } = this.state + + if (enteringCurrentPassword) { + return ( + + ) + } + return ( - - {this.state.enteringCurrentPassword && - this.setState({ currentPassword: val })} - value={this.state.currentPassword} - placeholder={labels.passwordSettings.enterCurrent} - /> - } - { - 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} - > - - {labels.passwordSettings.deletePassword} - - - + + {labels.passwordSettings.deletePassword} + ) } } \ No newline at end of file diff --git a/components/settings/password/enter-new-password.js b/components/settings/password/enter-new-password.js index 084a6bc..cba3a11 100644 --- a/components/settings/password/enter-new-password.js +++ b/components/settings/password/enter-new-password.js @@ -4,8 +4,8 @@ import nodejs from 'nodejs-mobile-react-native' import { requestHash, changeEncryptionAndRestartApp } from '../../../db' import AppText from '../../app-text' -import PasswordField from './password-field' -import SettingsButton from '../settings-button' +import PasswordField from '../shared/password-field' +import SettingsButton from '../shared/settings-button' import styles from '../../../styles' import settings from '../../../i18n/en/settings' diff --git a/components/settings/password/index.js b/components/settings/password/index.js index fca0966..d9caf4b 100644 --- a/components/settings/password/index.js +++ b/components/settings/password/index.js @@ -1,9 +1,9 @@ import React, { Component } from 'react' -import { View, ScrollView } from 'react-native' +import { ScrollView } from 'react-native' import CreatePassword from './create' import ChangePassword from './update' import DeletePassword from './delete' -import SettingsSegment from '../settings-segment' +import SettingsSegment from '../shared/settings-segment' import AppText from '../../app-text' import { hasEncryptionObservable @@ -14,33 +14,54 @@ export default class PasswordSetting extends Component { constructor(props) { super(props) this.state = { - showUpdateAndDelete: hasEncryptionObservable.value, - showCreate: !hasEncryptionObservable.value + isPasswordSet: hasEncryptionObservable.value, + isChangingPassword: false, + isDeletingPassword: false } } + onChangingPassword = () => { + this.setState({ isChangingPassword: true }) + } + + onDeletingPassword = () => { + this.setState({ isDeletingPassword: true }) + } + render() { + + const { + isPasswordSet, + isChangingPassword, + isDeletingPassword, + } = this.state + + const { + title, + explainerEnabled, + explainerDisabled + } = labels.passwordSettings + return ( - + + + { isPasswordSet ? explainerEnabled : explainerDisabled } + - {this.state.showUpdateAndDelete ? - {labels.passwordSettings.explainerEnabled} - : - {labels.passwordSettings.explainerDisabled} - } + { !isPasswordSet && } - {this.state.showUpdateAndDelete && - - - - - } - - {this.state.showCreate && - - } + { (isPasswordSet && !isDeletingPassword) && ( + + )} + { (isPasswordSet && !isChangingPassword) && ( + + )} ) diff --git a/components/settings/password/update.js b/components/settings/password/update.js index bac6d2b..e09433a 100644 --- a/components/settings/password/update.js +++ b/components/settings/password/update.js @@ -1,14 +1,9 @@ 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 { requestHash } from '../../../db' import EnterNewPassword from './enter-new-password' -import PasswordField from './password-field' -import SettingsButton from '../settings-button' +import SettingsButton from '../shared/settings-button' 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 { @@ -19,49 +14,29 @@ export default class ChangePassword extends Component { enteringCurrentPassword: 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 = () => { showBackUpReminder(() => { this.setState({ enteringCurrentPassword: true }) }) + this.props.onStartChangingPassword() } - handleCurrentPasswordInput = (currentPassword) => { - this.setState({ currentPassword }) + startEnteringNewPassword = () => { + this.setState({ + currentPassword: null, + enteringNewPassword: true, + enteringCurrentPassword: false + }) } - checkCurrentPassword = () => { - requestHash('pre-change-pw-check', this.state.currentPassword) + cancelConfirmationWithPassword = () => { + this.setState({ + currentPassword: null, + enteringNewPassword: false, + enteringCurrentPassword: false + }) } render() { @@ -76,19 +51,10 @@ export default class ChangePassword extends Component { if (enteringCurrentPassword) { return ( - - - - {sharedLabels.unlock} - - + ) } @@ -97,14 +63,12 @@ export default class ChangePassword extends Component { } return ( - - - {labels.changePassword} - - + + {labels.changePassword} + ) } } \ No newline at end of file diff --git a/components/settings/reminders/index.js b/components/settings/reminders/index.js index ca234d1..92fc461 100644 --- a/components/settings/reminders/index.js +++ b/components/settings/reminders/index.js @@ -2,9 +2,12 @@ import React, { Component } from 'react' import { ScrollView, } from 'react-native' +import SettingsSegment from '../shared/settings-segment' import TempReminderPicker from './temp-reminder-picker' import PeriodReminderPicker from './period-reminder' +import labels from '../../../i18n/en/settings' + export default class Settings extends Component { constructor(props) { super(props) @@ -14,8 +17,12 @@ export default class Settings extends Component { render() { return ( - - + + + + + + ) } diff --git a/components/settings/reminders/period-reminder.js b/components/settings/reminders/period-reminder.js index 3c07c10..f7e177c 100644 --- a/components/settings/reminders/period-reminder.js +++ b/components/settings/reminders/period-reminder.js @@ -8,7 +8,6 @@ import { periodReminderObservable, savePeriodReminder } from '../../../local-storage' -import styles from '../../../styles/index' import labels from '../../../i18n/en/settings' export default class PeriodReminderPicker extends Component { @@ -19,22 +18,17 @@ export default class PeriodReminderPicker extends Component { render() { return ( - - - {labels.periodReminder.title} - - - - {labels.periodReminder.reminderText} - - { - this.setState({ enabled: switchOn }) - savePeriodReminder({enabled: switchOn}) - }} - /> + + + {labels.periodReminder.reminderText} + { + this.setState({ enabled: switchOn }) + savePeriodReminder({enabled: switchOn}) + }} + /> ) } diff --git a/components/settings/reminders/temp-reminder-picker.js b/components/settings/reminders/temp-reminder-picker.js index 09dda42..a481d61 100644 --- a/components/settings/reminders/temp-reminder-picker.js +++ b/components/settings/reminders/temp-reminder-picker.js @@ -10,64 +10,63 @@ import { tempReminderObservable, saveTempReminder } from '../../../local-storage' -import styles from '../../../styles/index' import labels from '../../../i18n/en/settings' import padWithZeros from '../../helpers/pad-time-with-zeros' export default class TempReminderPicker extends Component { constructor(props) { super(props) - this.state = Object.assign({}, tempReminderObservable.value) + const { time, enabled } = tempReminderObservable.value + this.state = { + time, + enabled, + isTimePickerVisible: false + } } render() { return ( this.setState({ isTimePickerVisible: true })} > - - {labels.tempReminder.title} - - - - {this.state.time && this.state.enabled ? - {labels.tempReminder.timeSet(this.state.time)} - : - {labels.tempReminder.noTimeSet} - } - - { - this.setState({ enabled: switchOn }) - if (switchOn && !this.state.time) { - this.setState({ isTimePickerVisible: true }) - } - if (!switchOn) saveTempReminder({ enabled: false }) - }} - /> - { - 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}) - }} - /> + + {this.state.time && this.state.enabled ? + {labels.tempReminder.timeSet(this.state.time)} + : + {labels.tempReminder.noTimeSet} + } + { + this.setState({ enabled: switchOn }) + if (switchOn && !this.state.time) { + this.setState({ isTimePickerVisible: true }) + } + if (!switchOn) saveTempReminder({ enabled: false }) + }} + /> + { + 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}) + }} + /> ) } diff --git a/components/settings/alert-error.js b/components/settings/shared/alert-error.js similarity index 65% rename from components/settings/alert-error.js rename to components/settings/shared/alert-error.js index b4d447d..6d08d91 100644 --- a/components/settings/alert-error.js +++ b/components/settings/shared/alert-error.js @@ -1,5 +1,5 @@ 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) { Alert.alert(sharedLabels.errorTitle, msg) diff --git a/components/settings/data-management/confirm-with-password.js b/components/settings/shared/confirm-with-password.js similarity index 92% rename from components/settings/data-management/confirm-with-password.js rename to components/settings/shared/confirm-with-password.js index fee296a..bacef7c 100644 --- a/components/settings/data-management/confirm-with-password.js +++ b/components/settings/shared/confirm-with-password.js @@ -4,8 +4,8 @@ import { View, Alert } from 'react-native' import nodejs from 'nodejs-mobile-react-native' import { requestHash, openDb } from '../../../db' -import PasswordField from '../password/password-field' -import SettingsButton from '../settings-button' +import PasswordField from './password-field' +import SettingsButton from '../shared/settings-button' import settings from '../../../i18n/en/settings' import { shared } from '../../../i18n/en/labels' @@ -79,7 +79,7 @@ export default class ConfirmWithPassword extends Component { onPress={this.initPasswordCheck} disabled={!password} > - {settings.deleteSegment.title} + {shared.confirmToProceed} ) diff --git a/components/settings/password/password-field.js b/components/settings/shared/password-field.js similarity index 100% rename from components/settings/password/password-field.js rename to components/settings/shared/password-field.js diff --git a/components/settings/settings-button.js b/components/settings/shared/settings-button.js similarity index 84% rename from components/settings/settings-button.js rename to components/settings/shared/settings-button.js index bfa8983..97272bb 100644 --- a/components/settings/settings-button.js +++ b/components/settings/shared/settings-button.js @@ -2,8 +2,8 @@ import React from 'react' import PropTypes from 'prop-types' import { TouchableOpacity } from 'react-native' -import AppText from '../app-text' -import styles from '../../styles' +import AppText from '../../app-text' +import styles from '../../../styles' const SettingsButton = ({ children, ...props }) => { return ( diff --git a/components/settings/settings-segment.js b/components/settings/shared/settings-segment.js similarity index 53% rename from components/settings/settings-segment.js rename to components/settings/shared/settings-segment.js index f29f7c5..8d73a77 100644 --- a/components/settings/settings-segment.js +++ b/components/settings/shared/settings-segment.js @@ -2,22 +2,25 @@ import React from 'react' import PropTypes from 'prop-types' import { View } from 'react-native' -import AppText from '../app-text' -import styles from '../../styles' +import AppText from '../../app-text' +import styles from '../../../styles' const SettingsSegment = ({ children, ...props }) => { const style = [styles.settingsSegment, props.style] if (props.last) style.push(styles.settingsSegmentLast) return ( - - {props.title} + + { + props.title + && {props.title} + } {children} ) } SettingsSegment.propTypes = { - title: PropTypes.string.isRequired + title: PropTypes.string } export default SettingsSegment \ No newline at end of file diff --git a/i18n/en/labels.js b/i18n/en/labels.js index 0f569aa..c4b952a 100644 --- a/i18n/en/labels.js +++ b/i18n/en/labels.js @@ -11,7 +11,7 @@ export const shared = { incorrectPasswordMessage: 'That password is incorrect.', tryAgain: 'Try again', ok: 'OK', - unlock: 'Unlock', + confirmToProceed: 'Confirm to proceed', date: 'Date', cycleDayWithLinebreak: 'Cycle\nday', loading: 'Loading ...', diff --git a/lib/notifications.js b/lib/notifications.js index ded27c3..9836a37 100644 --- a/lib/notifications.js +++ b/lib/notifications.js @@ -2,7 +2,7 @@ import {tempReminderObservable, periodReminderObservable} from '../local-storage import Notification from 'react-native-push-notification' import { LocalDate } from 'js-joda' import Moment from 'moment' -import { settings as labels } from '../i18n/en/settings' +import labels from '../i18n/en/settings' import { getBleedingDaysSortedByDate } from '../db' import cycleModule from './cycle' import nothingChanged from '../db/db-unchanged'