Merge branch 'chore/make-function-components-3' into 'main'

Chore/make function components 3

See merge request bloodyhealth/drip!518
This commit is contained in:
Maria Zadnepryanets
2022-09-11 15:35:16 +00:00
4 changed files with 134 additions and 222 deletions
+23 -63
View File
@@ -1,4 +1,4 @@
import React, { Component } from 'react'
import React, { useState, useEffect } from 'react'
import { BackHandler, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
@@ -7,99 +7,59 @@ import { LocalDate } from '@js-joda/core'
import Header from './header'
import Menu from './menu'
import { viewsList } from './views'
import { isSettingsView, pages } from './pages'
import { pages } from './pages'
import { headerTitles } from '../i18n/en/labels'
import setupNotifications from '../lib/notifications'
import { closeDb } from '../db'
class App extends Component {
static propTypes = {
date: PropTypes.string,
navigate: PropTypes.func,
setDate: PropTypes.func,
goBack: PropTypes.func,
restartApp: PropTypes.func,
}
constructor(props) {
super(props)
this.backHandler = BackHandler.addEventListener(
'hardwareBackPress',
this.goBack
)
this.state = {
date: LocalDate.now().toString(),
currentPage: 'Home',
}
setupNotifications(this.navigate, this.setDate)
}
navigate = (page) => {
this.setState({ currentPage: page })
}
setDate = (date) => {
this.setState({ date })
}
goBack = () => {
const { currentPage } = this.state
const App = ({ restartApp }) => {
const [date, setDate] = useState(LocalDate.now().toString())
const [currentPage, setCurrentPage] = useState('Home')
const goBack = () => {
if (currentPage === 'Home') {
closeDb()
BackHandler.exitApp()
} else {
const { parent } = pages.find((p) => p.component === currentPage)
this.navigate(parent)
setCurrentPage(parent)
}
return true
}
componentWillUnmount() {
this.backHandler.remove()
}
useEffect(() => {
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
goBack
)
render() {
const { goBack, restartApp } = this.props
const { date, currentPage } = this.state
const { navigate } = this
return () => backHandler.remove()
})
if (!currentPage) {
return false
}
useEffect(() => setupNotifications(setCurrentPage, setDate), [])
const Page = viewsList[currentPage]
const title = headerTitles[currentPage]
const isSettingsSubView = isSettingsView(currentPage)
const isTemperatureEditView = currentPage === 'TemperatureEditView'
const headerProps = {
title,
handleBack: isSettingsSubView ? goBack : null,
navigate,
}
const headerProps = { navigate: setCurrentPage }
const pageProps = {
date,
setDate: this.setDate,
setDate,
isTemperatureEditView,
navigate,
navigate: setCurrentPage,
}
return (
<View style={styles.container}>
<Header {...headerProps} />
<Page {...pageProps} restartApp={restartApp} />
<Menu currentPage={currentPage} navigate={navigate} />
<Menu currentPage={currentPage} navigate={setCurrentPage} />
</View>
)
}
App.propTypes = {
restartApp: PropTypes.func,
}
const styles = StyleSheet.create({
+16 -48
View File
@@ -1,11 +1,10 @@
import React, { Component } from 'react'
import React from 'react'
import PropTypes from 'prop-types'
import { StyleSheet, View } from 'react-native'
import { CalendarList } from 'react-native-calendars'
import { getBleedingDaysSortedByDate } from '../db'
import cycleModule from '../lib/cycle'
import nothingChanged from '../db/db-unchanged'
import {
calendarTheme,
predictionToCalFormat,
@@ -13,55 +12,20 @@ import {
todayToCalFormat,
} from './helpers/calendar'
class CalendarView extends Component {
static propTypes = {
setDate: PropTypes.func.isRequired,
navigate: PropTypes.func.isRequired,
}
constructor(props) {
super(props)
this.bleedingDays = getBleedingDaysSortedByDate()
const CalendarView = ({ setDate, navigate }) => {
const bleedingDays = getBleedingDaysSortedByDate()
const predictedMenses = cycleModule().getPredictedMenses()
this.state = {
bleedingDaysInCalFormat: toCalFormat(this.bleedingDays),
predictedBleedingDaysInCalFormat: predictionToCalFormat(predictedMenses),
todayInCalFormat: todayToCalFormat(),
const passDateToDayView = ({ dateString }) => {
setDate(dateString)
navigate('CycleDay')
}
this.bleedingDays.addListener(this.setStateWithCalFormattedDays)
}
setStateWithCalFormattedDays = (_, changes) => {
if (nothingChanged(changes)) return
const predictedMenses = cycleModule().getPredictedMenses()
this.setState({
bleedingDaysInCalFormat: toCalFormat(this.bleedingDays),
predictedBleedingDaysInCalFormat: predictionToCalFormat(predictedMenses),
todayInCalFormat: todayToCalFormat(),
})
}
componentWillUnmount() {
this.bleedingDays.removeListener(this.setStateWithCalFormattedDays)
}
passDateToDayView = (result) => {
this.props.setDate(result.dateString)
this.props.navigate('CycleDay')
}
render() {
const {
todayInCalFormat,
bleedingDaysInCalFormat,
predictedBleedingDaysInCalFormat,
} = this.state
const markedDates = Object.assign(
{},
todayInCalFormat,
bleedingDaysInCalFormat,
predictedBleedingDaysInCalFormat
todayToCalFormat(),
toCalFormat(bleedingDays),
predictionToCalFormat(predictedMenses)
)
return (
@@ -69,7 +33,7 @@ class CalendarView extends Component {
<CalendarList
// If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
firstDay={1}
onDayPress={this.passDateToDayView.bind(this)}
onDayPress={passDateToDayView}
markedDates={markedDates}
markingType="custom"
theme={calendarTheme}
@@ -79,10 +43,14 @@ class CalendarView extends Component {
</View>
)
}
}
const styles = StyleSheet.create({
container: { flex: 1 },
})
CalendarView.propTypes = {
setDate: PropTypes.func.isRequired,
navigate: PropTypes.func.isRequired,
}
export default CalendarView
-3
View File
@@ -3,9 +3,6 @@ import settingsViews from './settings'
import settingsLabels from '../i18n/en/settings'
const labels = settingsLabels.menuItems
export const isSettingsView = (page) =>
Object.keys(settingsViews).includes(page)
export const pages = [
{
component: 'Home',
+44 -57
View File
@@ -1,4 +1,4 @@
import React, { Component } from 'react'
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { Alert, StyleSheet, View } from 'react-native'
import nodejs from 'nodejs-mobile-react-native'
@@ -15,97 +15,82 @@ import { Containers, Spacing } from '../styles'
const cancelButton = { text: shared.cancel, style: 'cancel' }
export default class PasswordPrompt extends Component {
static propTypes = {
enableShowApp: PropTypes.func.isRequired,
}
constructor(props) {
super(props)
this.state = { password: null }
nodejs.channel.addListener('check-pw', this.passHashToDb, this)
}
componentWillUnmount() {
nodejs.channel.removeListener('check-pw', this.passHashToDb)
}
onConfirmDeletion = async () => {
Alert.alert(labels.deleteDatabaseTitle, labels.deleteDatabaseExplainer, [
cancelButton,
{ text: labels.deleteData, onPress: this.onDeleteData },
])
}
onDeleteData = () => {
Alert.alert(labels.areYouSureTitle, labels.areYouSure, [
cancelButton,
{
text: labels.reallyDeleteData,
onPress: this.onDeleteDataConfirmation,
},
])
}
onDeleteDataConfirmation = async () => {
await deleteDbAndOpenNew()
await saveEncryptionFlag(false)
this.props.enableShowApp()
}
passHashToDb = async (hash) => {
const PasswordPrompt = ({ enableShowApp }) => {
const [password, setPassword] = useState(null)
const unlockApp = () => requestHash('check-pw', password)
const isPasswordEntered = Boolean(password)
const passHashToDb = async (hash) => {
const connected = await openDb(hash)
if (!connected) {
Alert.alert(shared.incorrectPassword, shared.incorrectPasswordMessage, [
{
text: shared.tryAgain,
onPress: () => this.setState({ password: null }),
onPress: () => setPassword(null),
},
])
return
}
this.props.enableShowApp()
enableShowApp()
}
unlockApp = () => {
requestHash('check-pw', this.state.password)
useEffect(() => {
nodejs.channel.addListener('check-pw', passHashToDb, this)
return () => nodejs.channel.remove('check-pw', passHashToDb)
}, [])
const onDeleteDataConfirmation = async () => {
await deleteDbAndOpenNew()
await saveEncryptionFlag(false)
enableShowApp()
}
setPassword = (password) => {
this.setState({ password })
const onDeleteData = () => {
Alert.alert(labels.areYouSureTitle, labels.areYouSure, [
cancelButton,
{
text: labels.reallyDeleteData,
onPress: onDeleteDataConfirmation,
},
])
}
render() {
const { password } = this.state
const isPasswordEntered = Boolean(password)
const onConfirmDeletion = async () => {
Alert.alert(labels.deleteDatabaseTitle, labels.deleteDatabaseExplainer, [
cancelButton,
{ text: labels.deleteData, onPress: onDeleteData },
])
}
return (
<React.Fragment>
<>
<Header isStatic />
<AppPage contentContainerStyle={styles.contentContainer}>
<AppTextInput
isKeyboardOffset={false}
onChangeText={this.setPassword}
onChangeText={setPassword}
secureTextEntry={true}
placeholder={labels.enterPassword}
/>
<View style={styles.containerButtons}>
<Button onPress={this.onConfirmDeletion}>
{labels.forgotPassword}
</Button>
<Button onPress={onConfirmDeletion}>{labels.forgotPassword}</Button>
<Button
disabled={!isPasswordEntered}
isCTA={isPasswordEntered}
onPress={this.unlockApp}
onPress={unlockApp}
>
{labels.title}
</Button>
</View>
</AppPage>
</React.Fragment>
</>
)
}
PasswordPrompt.propTypes = {
enableShowApp: PropTypes.func.isRequired,
}
const styles = StyleSheet.create({
@@ -119,3 +104,5 @@ const styles = StyleSheet.create({
justifyContent: 'space-around',
},
})
export default PasswordPrompt