diff --git a/components/settings/common/confirm-with-password.js b/components/settings/common/confirm-with-password.js
index 6f518b2..4fceacb 100644
--- a/components/settings/common/confirm-with-password.js
+++ b/components/settings/common/confirm-with-password.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import { Alert, StyleSheet, View } from 'react-native'
import nodejs from 'nodejs-mobile-react-native'
@@ -11,78 +11,65 @@ import { Containers } from '../../../styles'
import settings from '../../../i18n/en/settings'
import { shared } from '../../../i18n/en/labels'
-export default class ConfirmWithPassword extends Component {
- constructor() {
- super()
+const ConfirmWithPassword = ({ onSuccess, onCancel }) => {
+ const [password, setPassword] = useState(null)
- this.state = { password: null }
- nodejs.channel.addListener('password-check', this.checkPassword, this)
+ const checkPassword = async (hash) => {
+ try {
+ await openDb(hash)
+ onSuccess()
+ } catch (err) {
+ onIncorrectPassword()
+ }
}
- componentWillUnmount() {
- nodejs.channel.removeListener('password-check', this.checkPassword)
- }
+ useEffect(() => {
+ nodejs.channel.addListener('password-check', checkPassword, this)
+ return () => {
+ nodejs.channel.removeListener('password-check', checkPassword)
+ }
+ }, [])
- resetPasswordInput = () => {
- this.setState({ password: null })
- }
-
- onIncorrectPassword = () => {
+ const onIncorrectPassword = () => {
Alert.alert(shared.incorrectPassword, shared.incorrectPasswordMessage, [
{
text: shared.cancel,
- onPress: this.props.onCancel,
+ onPress: onCancel,
},
{
text: shared.tryAgain,
- onPress: this.resetPasswordInput,
+ onPress: () => setPassword(null),
},
])
}
- checkPassword = async (hash) => {
- try {
- await openDb(hash)
- this.props.onSuccess()
- } catch (err) {
- this.onIncorrectPassword()
- }
+ const initPasswordCheck = () => {
+ requestHash('password-check', password)
}
- handlePasswordInput = (password) => {
- this.setState({ password })
- }
+ const labels = settings.passwordSettings
+ const isPassword = password !== null
- initPasswordCheck = () => {
- requestHash('password-check', this.state.password)
- }
-
- render() {
- const { password } = this.state
- const labels = settings.passwordSettings
- const isPassword = password !== null
-
- return (
-
-
-
-
-
-
-
- )
- }
+ return (
+ <>
+
+
+
+
+
+ >
+ )
}
ConfirmWithPassword.propTypes = {
@@ -95,3 +82,5 @@ const styles = StyleSheet.create({
...Containers.rowContainer,
},
})
+
+export default ConfirmWithPassword
diff --git a/components/settings/data-management/delete-data.js b/components/settings/data-management/delete-data.js
index d0ddef7..4ba3035 100644
--- a/components/settings/data-management/delete-data.js
+++ b/components/settings/data-management/delete-data.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { useState } from 'react'
import RNFS from 'react-native-fs'
import { Alert } from 'react-native'
import PropTypes from 'prop-types'
@@ -17,26 +17,21 @@ import { EXPORT_FILE_NAME } from './constants'
const exportedFilePath = `${RNFS.DocumentDirectoryPath}/${EXPORT_FILE_NAME}`
-export default class DeleteData extends Component {
- constructor() {
- super()
+const DeleteData = ({ onStartDeletion, isDeletingData }) => {
+ const isPasswordSet = hasEncryptionObservable.value
+ const [isConfirmingWithPassword, setIsConfirmingWithPassword] =
+ useState(false)
- this.state = {
- isPasswordSet: hasEncryptionObservable.value,
- isConfirmingWithPassword: false,
- }
- }
-
- onAlertConfirmation = () => {
- this.props.onStartDeletion()
- if (this.state.isPasswordSet) {
- this.setState({ isConfirmingWithPassword: true })
+ const onAlertConfirmation = () => {
+ onStartDeletion()
+ if (isPasswordSet) {
+ setIsConfirmingWithPassword(true)
} else {
- this.deleteAppData()
+ deleteAppData()
}
}
- alertBeforeDeletion = async () => {
+ const alertBeforeDeletion = async () => {
const { question, message, confirmation, errors } = settings.deleteSegment
if (isDbEmpty() && !(await RNFS.exists(exportedFilePath))) {
alertError(errors.noData)
@@ -44,64 +39,61 @@ export default class DeleteData extends Component {
Alert.alert(question, message, [
{
text: confirmation,
- onPress: this.onAlertConfirmation,
+ onPress: onAlertConfirmation,
},
{
text: sharedLabels.cancel,
style: 'cancel',
- onPress: this.cancelConfirmationWithPassword,
+ onPress: cancelConfirmationWithPassword,
},
])
}
}
- deleteExportedFile = async () => {
+ const deleteExportedFile = async () => {
if (await RNFS.exists(exportedFilePath)) {
await RNFS.unlink(exportedFilePath)
}
}
- deleteAppData = async () => {
+ const deleteAppData = async () => {
const { errors, success } = settings.deleteSegment
try {
if (!isDbEmpty()) {
clearDb()
}
- await this.deleteExportedFile()
+ await deleteExportedFile()
showToast(success.message)
} catch (err) {
alertError(errors.couldNotDeleteFile)
}
- this.cancelConfirmationWithPassword()
+ cancelConfirmationWithPassword()
}
- cancelConfirmationWithPassword = () => {
- this.setState({ isConfirmingWithPassword: false })
+ const cancelConfirmationWithPassword = () => {
+ setIsConfirmingWithPassword(false)
}
- render() {
- const { isConfirmingWithPassword } = this.state
- const { isDeletingData } = this.props
-
- if (isConfirmingWithPassword && isDeletingData) {
- return (
-
- )
- }
-
+ if (isConfirmingWithPassword && isDeletingData) {
return (
-
+
)
}
+
+ return (
+
+ )
}
DeleteData.propTypes = {
isDeletingData: PropTypes.bool,
onStartDeletion: PropTypes.func.isRequired,
}
+
+export default DeleteData
diff --git a/components/settings/data-management/index.js b/components/settings/data-management/index.js
index b6d3524..d36ad70 100644
--- a/components/settings/data-management/index.js
+++ b/components/settings/data-management/index.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { useState } from 'react'
import AppLoadingView from '../../common/app-loading'
import AppPage from '../../common/app-page'
@@ -13,78 +13,56 @@ import DeleteData from './delete-data'
import labels from '../../../i18n/en/settings'
import { ACTION_DELETE, ACTION_EXPORT, ACTION_IMPORT } from '../../../config'
-export default class DataManagement extends Component {
- constructor(props) {
- super(props)
+const DataManagement = () => {
+ const [isLoading, setIsLoading] = useState(false)
+ const [currentAction, setCurrentAction] = useState(null)
- this.state = {
- isLoading: false,
- currentAction: null,
- }
- }
-
- startLoading = () => {
- this.setState({ isLoading: true })
- }
-
- endLoading = () => {
- this.setState({ isLoading: false })
- }
-
- startImportFlow = async (shouldDeleteExistingData) => {
- this.startLoading()
+ const startImportFlow = async (shouldDeleteExistingData) => {
+ setIsLoading(true)
const fileContent = await getFileContent()
if (fileContent) {
await importData(shouldDeleteExistingData, fileContent)
}
- this.endLoading()
+ setIsLoading(false)
}
- startExport = () => {
- this.setCurrentAction(ACTION_EXPORT)
+ const startExport = () => {
+ setCurrentAction(ACTION_EXPORT)
openShareDialogAndExport()
}
- startImport = () => {
- this.setCurrentAction(ACTION_IMPORT)
- openImportDialog(this.startImportFlow)
+ const startImport = () => {
+ setCurrentAction(ACTION_IMPORT)
+ openImportDialog(startImportFlow)
}
- setCurrentAction = (action) => {
- this.setState({ currentAction: action })
- }
+ if (isLoading) return
- render() {
- const { currentAction, isLoading } = this.state
- const isDeletingData = currentAction === ACTION_DELETE
+ const isDeletingData = currentAction === ACTION_DELETE
- return (
-
- {isLoading && }
- {!isLoading && (
-
-
- {labels.export.segmentExplainer}
-
-
-
- {labels.import.segmentExplainer}
-
-
-
- {labels.deleteSegment.explainer}
- this.setCurrentAction(ACTION_DELETE)}
- />
-
-
- )}
-
- )
- }
+ return (
+
+
+ {labels.export.segmentExplainer}
+
+
+
+ {labels.import.segmentExplainer}
+
+
+
+ {labels.deleteSegment.explainer}
+ setCurrentAction(ACTION_DELETE)}
+ />
+
+
+ )
}
+
+export default DataManagement
diff --git a/components/settings/nfp-settings/index.js b/components/settings/nfp-settings/index.js
index 427527f..bf83580 100644
--- a/components/settings/nfp-settings/index.js
+++ b/components/settings/nfp-settings/index.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { useState } from 'react'
import { Platform, StyleSheet, View } from 'react-native'
import AppIcon from '../../common/app-icon'
@@ -12,58 +12,53 @@ import { useCervixObservable, saveUseCervix } from '../../../local-storage'
import { Colors, Spacing, Typography } from '../../../styles'
import labels from '../../../i18n/en/settings'
-export default class Settings extends Component {
- constructor(props) {
- super(props)
+const Settings = () => {
+ const [shouldUseCervix, setShouldUseCervix] = useState(
+ useCervixObservable.value
+ )
- this.state = {
- shouldUseCervix: useCervixObservable.value,
- }
- }
-
- onCervixToggle = (value) => {
- this.setState({ shouldUseCervix: value })
+ const onCervixToggle = (value) => {
+ setShouldUseCervix(value)
saveUseCervix(value)
}
- render() {
- const { shouldUseCervix } = this.state
- const cervixText = shouldUseCervix
- ? labels.useCervix.cervixModeOn
- : labels.useCervix.cervixModeOff
+ const cervixText = shouldUseCervix
+ ? labels.useCervix.cervixModeOn
+ : labels.useCervix.cervixModeOff
- return (
-
-
-
+
+
+
+ {/* for iOS disabled temporarily, TODO https://gitlab.com/bloodyhealth/drip/-/issues/545 */}
+ {Platform.OS !== 'ios' && (
+
+ {labels.tempScale.segmentExplainer}
+
+
+ )}
+
+
+
-
- {/* for iOS disabled temporarily, TODO https://gitlab.com/bloodyhealth/drip/-/issues/545 */}
- {Platform.OS !== 'ios' && (
-
- {labels.tempScale.segmentExplainer}
-
-
- )}
-
-
-
- {labels.preOvu.title}
-
- {labels.preOvu.note}
-
-
- )
- }
+ {labels.preOvu.title}
+
+ {labels.preOvu.note}
+
+
+ )
}
+export default Settings
+
const styles = StyleSheet.create({
icon: {
marginRight: Spacing.base,
diff --git a/components/settings/nfp-settings/temperature-slider.js b/components/settings/nfp-settings/temperature-slider.js
index 9795af4..2019d55 100644
--- a/components/settings/nfp-settings/temperature-slider.js
+++ b/components/settings/nfp-settings/temperature-slider.js
@@ -1,4 +1,4 @@
-import React, { Component } from 'react'
+import React, { useState } from 'react'
import { StyleSheet, View } from 'react-native'
import Slider from '@ptomasroos/react-native-multi-slider'
@@ -10,51 +10,43 @@ import { Colors, Sizes } from '../../../styles'
import labels from '../../../i18n/en/settings'
import { TEMP_MIN, TEMP_MAX, TEMP_SLIDER_STEP } from '../../../config'
-export default class TemperatureSlider extends Component {
- constructor(props) {
- super(props)
-
- const { min, max } = scaleObservable.value
- this.state = { minTemperature: min, maxTemperature: max }
- }
-
- onTemperatureSliderChange = (values) => {
- this.setState({
- minTemperature: values[0],
- maxTemperature: values[1],
- })
+const TemperatureSlider = () => {
+ const savedValue = scaleObservable.value
+ const [minTemperature, setMinTemperature] = useState(savedValue.min)
+ const [maxTemperature, setMaxTemperature] = useState(savedValue.max)
+ const onTemperatureSliderChange = ([min, max]) => {
+ setMinTemperature(min)
+ setMaxTemperature(max)
try {
- saveTempScale({ min: values[0], max: values[1] })
+ saveTempScale({ min, max })
} catch (err) {
alertError(labels.tempScale.saveError)
}
}
- render() {
- const { minTemperature, maxTemperature } = this.state
-
- return (
-
-
-
- )
- }
+ return (
+
+
+
+ )
}
+export default TemperatureSlider
+
const styles = StyleSheet.create({
container: {
alignItems: 'center',