Refactor cycle day overview screen
This commit is contained in:
@@ -1,87 +1,61 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { useState } 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 { LocalDate } from 'js-joda'
|
|
||||||
|
|
||||||
import AppPage from '../common/app-page'
|
import AppPage from '../common/app-page'
|
||||||
import SymptomBox from './symptom-box'
|
import SymptomBox from './symptom-box'
|
||||||
import SymptomPageTitle from './symptom-page-title'
|
import SymptomPageTitle from './symptom-page-title'
|
||||||
|
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import { getDate, setDate } from '../../slices/date'
|
import { getDate } from '../../slices/date'
|
||||||
import { navigate } from '../../slices/navigation'
|
|
||||||
|
|
||||||
import cycleModule from '../../lib/cycle'
|
import cycleModule from '../../lib/cycle'
|
||||||
import { dateToTitle } from '../helpers/format-date'
|
import { dateToTitle } from '../helpers/format-date'
|
||||||
import { getCycleDay } from '../../db'
|
import { getCycleDay } from '../../db'
|
||||||
import { getData } from '../helpers/cycle-day'
|
import { getData } from '../helpers/cycle-day'
|
||||||
|
|
||||||
import { general as labels} from '../../i18n/en/cycle-day'
|
import { general as labels } from '../../i18n/en/cycle-day'
|
||||||
import { Spacing } from '../../styles'
|
import { Spacing } from '../../styles'
|
||||||
import { SYMPTOMS } from '../../config'
|
import { SYMPTOMS } from '../../config'
|
||||||
|
|
||||||
class CycleDayOverView extends Component {
|
const CycleDayOverView = ({ date, isTemperatureEditView }) => {
|
||||||
|
const cycleDay = getCycleDay(date)
|
||||||
|
|
||||||
static propTypes = {
|
const { getCycleDayNumber } = cycleModule()
|
||||||
navigate: PropTypes.func,
|
const cycleDayNumber = getCycleDayNumber(date)
|
||||||
setDate: PropTypes.func,
|
const subtitle = cycleDayNumber && `${labels.cycleDayNumber}${cycleDayNumber}`
|
||||||
cycleDay: PropTypes.object,
|
const [editedSymptom, setEditedSymptom] = useState(
|
||||||
date: PropTypes.string,
|
isTemperatureEditView ? 'temperature' : ''
|
||||||
isTemperatureEditView: PropTypes.bool,
|
)
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
return (
|
||||||
super(props)
|
<AppPage>
|
||||||
|
<SymptomPageTitle subtitle={subtitle} title={dateToTitle(date)} />
|
||||||
|
<View style={styles.container}>
|
||||||
|
{SYMPTOMS.map((symptom) => {
|
||||||
|
const symptomData =
|
||||||
|
cycleDay && cycleDay[symptom] ? cycleDay[symptom] : null
|
||||||
|
|
||||||
this.state = { cycleDay: getCycleDay(props.date), data: null }
|
return (
|
||||||
if (props.isTemperatureEditView) {
|
<SymptomBox
|
||||||
const todayDateString = LocalDate.now().toString()
|
key={symptom}
|
||||||
props.setDate(todayDateString)
|
symptom={symptom}
|
||||||
}
|
symptomData={symptomData}
|
||||||
}
|
symptomDataToDisplay={getData(symptom, symptomData)}
|
||||||
|
editedSymptom={editedSymptom}
|
||||||
|
setEditedSymptom={setEditedSymptom}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</AppPage>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
updateCycleDay = (date) => {
|
CycleDayOverView.propTypes = {
|
||||||
this.props.setDate(date)
|
cycleDay: PropTypes.object,
|
||||||
this.setState({ cycleDay: getCycleDay(date) })
|
date: PropTypes.string,
|
||||||
}
|
isTemperatureEditView: PropTypes.bool,
|
||||||
|
|
||||||
render() {
|
|
||||||
const { cycleDay } = this.state
|
|
||||||
const { date, isTemperatureEditView } = this.props
|
|
||||||
|
|
||||||
const { getCycleDayNumber } = cycleModule()
|
|
||||||
const cycleDayNumber = getCycleDayNumber(date)
|
|
||||||
const subtitle = cycleDayNumber && `${labels.cycleDayNumber}${cycleDayNumber}`
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppPage>
|
|
||||||
<SymptomPageTitle
|
|
||||||
reloadSymptomData={this.updateCycleDay}
|
|
||||||
subtitle={subtitle}
|
|
||||||
title={dateToTitle(date)}
|
|
||||||
/>
|
|
||||||
<View style={styles.container}>
|
|
||||||
{SYMPTOMS.map(symptom => {
|
|
||||||
const symptomData = cycleDay && cycleDay[symptom]
|
|
||||||
? cycleDay[symptom] : null
|
|
||||||
|
|
||||||
const isSymptomEdited = isTemperatureEditView && symptom === 'temperature'
|
|
||||||
|
|
||||||
return(
|
|
||||||
<SymptomBox
|
|
||||||
key={symptom}
|
|
||||||
symptom={symptom}
|
|
||||||
symptomData={symptomData}
|
|
||||||
symptomDataToDisplay={getData(symptom, symptomData)}
|
|
||||||
updateCycleDayData={this.updateCycleDay}
|
|
||||||
isSymptomEdited={isSymptomEdited}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</View>
|
|
||||||
</AppPage>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
@@ -89,24 +63,14 @@ const styles = StyleSheet.create({
|
|||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
padding: Spacing.base
|
padding: Spacing.base,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = (state) => {
|
const mapStateToProps = (state) => {
|
||||||
return({
|
return {
|
||||||
date: getDate(state),
|
date: getDate(state),
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => {
|
export default connect(mapStateToProps, null)(CycleDayOverView)
|
||||||
return({
|
|
||||||
setDate: (date) => dispatch(setDate(date)),
|
|
||||||
navigate: (page) => dispatch(navigate(page)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps,
|
|
||||||
)(CycleDayOverView)
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { Component } from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { StyleSheet, View, TouchableOpacity } from 'react-native'
|
import { StyleSheet, View, TouchableOpacity } from 'react-native'
|
||||||
import { scale } from 'react-native-size-matters'
|
import { scale } from 'react-native-size-matters'
|
||||||
@@ -14,94 +14,75 @@ import { isDateInFuture } from '../helpers/cycle-day'
|
|||||||
import { Colors, Sizes, Spacing } from '../../styles'
|
import { Colors, Sizes, Spacing } from '../../styles'
|
||||||
import { headerTitles as symptomTitles } from '../../i18n/en/labels'
|
import { headerTitles as symptomTitles } from '../../i18n/en/labels'
|
||||||
|
|
||||||
class SymptomBox extends Component {
|
const SymptomBox = ({
|
||||||
static propTypes = {
|
date,
|
||||||
date: PropTypes.string.isRequired,
|
symptom,
|
||||||
isSymptomEdited: PropTypes.bool,
|
symptomData,
|
||||||
symptom: PropTypes.string.isRequired,
|
symptomDataToDisplay,
|
||||||
symptomData: PropTypes.object,
|
editedSymptom,
|
||||||
symptomDataToDisplay: PropTypes.string,
|
setEditedSymptom,
|
||||||
updateCycleDayData: PropTypes.func.isRequired,
|
}) => {
|
||||||
}
|
const isSymptomEdited = editedSymptom === symptom
|
||||||
|
const isSymptomDisabled = isDateInFuture(date) && symptom !== 'note'
|
||||||
|
const isExcluded = symptomData !== null ? symptomData.exclude : false
|
||||||
|
|
||||||
static defaultProps = {
|
const iconColor = isSymptomDisabled ? Colors.greyLight : Colors.grey
|
||||||
isSymptomEdited: false,
|
const iconName = `drip-icon-${symptom}`
|
||||||
}
|
const symptomNameStyle = [
|
||||||
|
styles.symptomName,
|
||||||
|
isSymptomDisabled && styles.symptomNameDisabled,
|
||||||
|
isExcluded && styles.symptomNameExcluded,
|
||||||
|
]
|
||||||
|
const textStyle = [
|
||||||
|
styles.text,
|
||||||
|
isSymptomDisabled && styles.textDisabled,
|
||||||
|
isExcluded && styles.textExcluded,
|
||||||
|
]
|
||||||
|
|
||||||
constructor(props) {
|
return (
|
||||||
super(props)
|
<>
|
||||||
|
{isSymptomEdited && (
|
||||||
|
<SymptomEditView
|
||||||
|
symptom={symptom}
|
||||||
|
symptomData={symptomData}
|
||||||
|
onClose={() => setEditedSymptom('')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
this.state = {
|
<TouchableOpacity
|
||||||
isSymptomEdited: props.isSymptomEdited,
|
disabled={isSymptomDisabled}
|
||||||
}
|
onPress={() => setEditedSymptom(symptom)}
|
||||||
}
|
style={styles.container}
|
||||||
|
testID={iconName}
|
||||||
onFinishEditing = () => {
|
>
|
||||||
const { date, updateCycleDayData } = this.props
|
<DripIcon
|
||||||
|
color={iconColor}
|
||||||
updateCycleDayData(date)
|
isActive={!isSymptomDisabled}
|
||||||
this.setState({ isSymptomEdited: false })
|
name={iconName}
|
||||||
}
|
size={Sizes.icon}
|
||||||
|
/>
|
||||||
onEditSymptom = () => {
|
<View style={styles.textContainer}>
|
||||||
this.setState({ isSymptomEdited: true })
|
<AppText style={symptomNameStyle}>
|
||||||
}
|
{symptomTitles[symptom].toLowerCase()}
|
||||||
|
</AppText>
|
||||||
render() {
|
{symptomDataToDisplay && (
|
||||||
const { date, symptom, symptomData, symptomDataToDisplay } = this.props
|
<AppText style={textStyle} numberOfLines={4}>
|
||||||
const { isSymptomEdited } = this.state
|
{symptomDataToDisplay}
|
||||||
const isSymptomDisabled = isDateInFuture(date) && symptom !== 'note'
|
|
||||||
const isExcluded = symptomData !== null ? symptomData.exclude : false
|
|
||||||
|
|
||||||
const iconColor = isSymptomDisabled ? Colors.greyLight : Colors.grey
|
|
||||||
const iconName = `drip-icon-${symptom}`
|
|
||||||
const symptomNameStyle = [
|
|
||||||
styles.symptomName,
|
|
||||||
isSymptomDisabled && styles.symptomNameDisabled,
|
|
||||||
isExcluded && styles.symptomNameExcluded,
|
|
||||||
]
|
|
||||||
const textStyle = [
|
|
||||||
styles.text,
|
|
||||||
isSymptomDisabled && styles.textDisabled,
|
|
||||||
isExcluded && styles.textExcluded,
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{isSymptomEdited && (
|
|
||||||
<SymptomEditView
|
|
||||||
symptom={symptom}
|
|
||||||
symptomData={symptomData}
|
|
||||||
onClose={this.onFinishEditing}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
disabled={isSymptomDisabled}
|
|
||||||
onPress={this.onEditSymptom}
|
|
||||||
style={styles.container}
|
|
||||||
testID={iconName}
|
|
||||||
>
|
|
||||||
<DripIcon
|
|
||||||
color={iconColor}
|
|
||||||
isActive={!isSymptomDisabled}
|
|
||||||
name={iconName}
|
|
||||||
size={Sizes.icon}
|
|
||||||
/>
|
|
||||||
<View style={styles.textContainer}>
|
|
||||||
<AppText style={symptomNameStyle}>
|
|
||||||
{symptomTitles[symptom].toLowerCase()}
|
|
||||||
</AppText>
|
</AppText>
|
||||||
{symptomDataToDisplay && (
|
)}
|
||||||
<AppText style={textStyle} numberOfLines={4}>
|
</View>
|
||||||
{symptomDataToDisplay}
|
</TouchableOpacity>
|
||||||
</AppText>
|
</>
|
||||||
)}
|
)
|
||||||
</View>
|
}
|
||||||
</TouchableOpacity>
|
|
||||||
</React.Fragment>
|
SymptomBox.propTypes = {
|
||||||
)
|
date: PropTypes.string.isRequired,
|
||||||
}
|
symptom: PropTypes.string.isRequired,
|
||||||
|
symptomData: PropTypes.object,
|
||||||
|
symptomDataToDisplay: PropTypes.string,
|
||||||
|
editedSymptom: PropTypes.string.isRequired,
|
||||||
|
setEditedSymptom: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
|
|||||||
@@ -12,33 +12,25 @@ import { nextDate, prevDate } from '../helpers/cycle-day'
|
|||||||
import { Colors, Containers, Spacing, Typography } from '../../styles'
|
import { Colors, Containers, Spacing, Typography } from '../../styles'
|
||||||
import { HIT_SLOP } from '../../config'
|
import { HIT_SLOP } from '../../config'
|
||||||
|
|
||||||
const SymptomPageTitle = ({
|
const SymptomPageTitle = ({ date, setDate, subtitle, title }) => {
|
||||||
date,
|
|
||||||
reloadSymptomData,
|
|
||||||
setDate,
|
|
||||||
subtitle,
|
|
||||||
title,
|
|
||||||
}) => {
|
|
||||||
const navigate = (isForward) => {
|
const navigate = (isForward) => {
|
||||||
const nextDay = isForward ? nextDate(date) : prevDate(date)
|
const newDate = isForward ? nextDate(date) : prevDate(date)
|
||||||
reloadSymptomData(nextDay)
|
setDate(newDate)
|
||||||
setDate(nextDay)
|
|
||||||
}
|
}
|
||||||
const formattedTitle = title.length > 21
|
const formattedTitle =
|
||||||
? title.substring(0, 18) + '...'
|
title.length > 21 ? title.substring(0, 18) + '...' : title
|
||||||
: title
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<TouchableOpacity onPress={() => navigate(false)} hitSlop={HIT_SLOP}>
|
<TouchableOpacity onPress={() => navigate(false)} hitSlop={HIT_SLOP}>
|
||||||
<AppIcon name='chevron-left' color={Colors.orange}/>
|
<AppIcon name="chevron-left" color={Colors.orange} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<View style={styles.textContainer}>
|
<View style={styles.textContainer}>
|
||||||
<AppText style={styles.title}>{formattedTitle}</AppText>
|
<AppText style={styles.title}>{formattedTitle}</AppText>
|
||||||
{subtitle && <AppText style={styles.subtitle}>{subtitle}</AppText>}
|
{subtitle && <AppText style={styles.subtitle}>{subtitle}</AppText>}
|
||||||
</View>
|
</View>
|
||||||
<TouchableOpacity onPress={() => navigate(true)} hitSlop={HIT_SLOP}>
|
<TouchableOpacity onPress={() => navigate(true)} hitSlop={HIT_SLOP}>
|
||||||
<AppIcon name='chevron-right' color={Colors.orange}/>
|
<AppIcon name="chevron-right" color={Colors.orange} />
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
@@ -46,7 +38,6 @@ const SymptomPageTitle = ({
|
|||||||
|
|
||||||
SymptomPageTitle.propTypes = {
|
SymptomPageTitle.propTypes = {
|
||||||
date: PropTypes.string.isRequired,
|
date: PropTypes.string.isRequired,
|
||||||
reloadSymptomData: PropTypes.func.isRequired,
|
|
||||||
setDate: PropTypes.func.isRequired,
|
setDate: PropTypes.func.isRequired,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
|
|||||||
+24
-13
@@ -1,25 +1,34 @@
|
|||||||
import {tempReminderObservable, periodReminderObservable} from '../local-storage'
|
import {
|
||||||
|
tempReminderObservable,
|
||||||
|
periodReminderObservable,
|
||||||
|
} from '../local-storage'
|
||||||
import Notification from 'react-native-push-notification'
|
import Notification from 'react-native-push-notification'
|
||||||
import Moment from 'moment'
|
import Moment from 'moment'
|
||||||
|
import { LocalDate } from 'js-joda'
|
||||||
|
|
||||||
import 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'
|
||||||
|
import store from '../store'
|
||||||
|
import { setDate } from '../slices/date'
|
||||||
|
|
||||||
export default function setupNotifications(navigate) {
|
export default function setupNotifications(navigate) {
|
||||||
Notification.configure({
|
Notification.configure({
|
||||||
onNotification: (notification) => {
|
onNotification: (notification) => {
|
||||||
// https://github.com/zo0r/react-native-push-notification/issues/966#issuecomment-479069106
|
// https://github.com/zo0r/react-native-push-notification/issues/966#issuecomment-479069106
|
||||||
if (notification.data?.id === '1' || notification.id === '1') {
|
if (notification.data?.id === '1' || notification.id === '1') {
|
||||||
|
const todayDate = LocalDate.now().toString()
|
||||||
|
store.dispatch(setDate(todayDate))
|
||||||
navigate('TemperatureEditView')
|
navigate('TemperatureEditView')
|
||||||
} else {
|
} else {
|
||||||
navigate('Home')
|
navigate('Home')
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
tempReminderObservable(reminder => {
|
tempReminderObservable((reminder) => {
|
||||||
Notification.cancelLocalNotifications({id: '1'})
|
Notification.cancelLocalNotifications({ id: '1' })
|
||||||
if (reminder.enabled) {
|
if (reminder.enabled) {
|
||||||
const [hours, minutes] = reminder.time.split(':')
|
const [hours, minutes] = reminder.time.split(':')
|
||||||
let target = new Moment()
|
let target = new Moment()
|
||||||
@@ -27,7 +36,7 @@ export default function setupNotifications(navigate) {
|
|||||||
.minutes(parseInt(minutes))
|
.minutes(parseInt(minutes))
|
||||||
.seconds(0)
|
.seconds(0)
|
||||||
|
|
||||||
if(target.isBefore(new Moment())) {
|
if (target.isBefore(new Moment())) {
|
||||||
target = target.add(1, 'd')
|
target = target.add(1, 'd')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,29 +46,31 @@ export default function setupNotifications(navigate) {
|
|||||||
message: labels.tempReminder.notification,
|
message: labels.tempReminder.notification,
|
||||||
date: target.toDate(),
|
date: target.toDate(),
|
||||||
vibrate: false,
|
vibrate: false,
|
||||||
repeatType: 'day'
|
repeatType: 'day',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
periodReminderObservable(reminder => {
|
periodReminderObservable((reminder) => {
|
||||||
Notification.cancelLocalNotifications({id: '2'})
|
Notification.cancelLocalNotifications({ id: '2' })
|
||||||
if (reminder.enabled) setupPeriodReminder()
|
if (reminder.enabled) setupPeriodReminder()
|
||||||
}, false)
|
}, false)
|
||||||
|
|
||||||
getBleedingDaysSortedByDate().addListener((_, changes) => {
|
getBleedingDaysSortedByDate().addListener((_, changes) => {
|
||||||
// the listener fires on setup, so we check if there were actually any changes
|
// the listener fires on setup, so we check if there were actually any changes
|
||||||
if (nothingChanged(changes)) return
|
if (nothingChanged(changes)) return
|
||||||
Notification.cancelLocalNotifications({id: '2'})
|
Notification.cancelLocalNotifications({ id: '2' })
|
||||||
if (periodReminderObservable.value.enabled) setupPeriodReminder()
|
if (periodReminderObservable.value.enabled) setupPeriodReminder()
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupPeriodReminder() {
|
function setupPeriodReminder() {
|
||||||
const bleedingPrediction = cycleModule().getPredictedMenses()
|
const bleedingPrediction = cycleModule().getPredictedMenses()
|
||||||
if (bleedingPrediction.length > 0) {
|
if (bleedingPrediction.length > 0) {
|
||||||
const predictedBleedingStart = Moment(bleedingPrediction[0][0], "YYYY-MM-DD")
|
const predictedBleedingStart = Moment(
|
||||||
|
bleedingPrediction[0][0],
|
||||||
|
'YYYY-MM-DD'
|
||||||
|
)
|
||||||
// 3 days before and at 6 am
|
// 3 days before and at 6 am
|
||||||
const reminderDate = predictedBleedingStart
|
const reminderDate = predictedBleedingStart
|
||||||
.subtract(3, 'days')
|
.subtract(3, 'days')
|
||||||
@@ -68,7 +79,7 @@ function setupPeriodReminder() {
|
|||||||
.seconds(0)
|
.seconds(0)
|
||||||
|
|
||||||
if (reminderDate.isAfter()) {
|
if (reminderDate.isAfter()) {
|
||||||
// period is likely to start in 3 to 3 + (length of prediction - 1) days
|
// period is likely to start in 3 to 3 + (length of prediction - 1) days
|
||||||
const daysToEndOfPrediction = bleedingPrediction[0].length + 2
|
const daysToEndOfPrediction = bleedingPrediction[0].length + 2
|
||||||
|
|
||||||
Notification.localNotificationSchedule({
|
Notification.localNotificationSchedule({
|
||||||
@@ -76,7 +87,7 @@ function setupPeriodReminder() {
|
|||||||
userInfo: { id: '2' },
|
userInfo: { id: '2' },
|
||||||
message: labels.periodReminder.notification(daysToEndOfPrediction),
|
message: labels.periodReminder.notification(daysToEndOfPrediction),
|
||||||
date: reminderDate.toDate(),
|
date: reminderDate.toDate(),
|
||||||
vibrate: false
|
vibrate: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user