From 949b435853b719da60fc92a543078a3356cd60fe Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Tue, 1 Nov 2022 18:58:09 +1300 Subject: [PATCH] Split up state for SettingsPage This improved performance when visually toggling an option --- SettingsPage.tsx | 233 ++++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 123 deletions(-) diff --git a/SettingsPage.tsx b/SettingsPage.tsx index 4f1aa29..e188a33 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -1,6 +1,6 @@ import {Picker} from '@react-native-picker/picker' import {useFocusEffect} from '@react-navigation/native' -import {useCallback, useEffect, useMemo, useState} from 'react' +import {useCallback, useMemo, useState} from 'react' import {DeviceEventEmitter, NativeModules, ScrollView} from 'react-native' import DocumentPicker from 'react-native-document-picker' import {Button} from 'react-native-paper' @@ -12,35 +12,45 @@ import DrawerHeader from './DrawerHeader' import Input from './input' import Page from './Page' import Select from './Select' -import Settings from './settings' import Switch from './Switch' import {toast} from './toast' +import {useTheme} from './use-theme' export default function SettingsPage() { const [battery, setBattery] = useState(false) const [ignoring, setIgnoring] = useState(false) const [term, setTerm] = useState('') - const [settings, setSettings] = useState({} as Settings) - - useEffect(() => { - console.log(`${SettingsPage.name}.useEffect:`, {settings}) - }, [settings]) + const [vibrate, setVibrate] = useState(false) + const [alarm, setAlarm] = useState(false) + const [sound, setSound] = useState('') + const [notify, setNotify] = useState(false) + const [images, setImages] = useState(false) + const [showUnit, setShowUnit] = useState(false) + const [steps, setSteps] = useState(false) + const [date, setDate] = useState('%Y-%m-%d %H:%M') + const {theme, setTheme, color, setColor} = useTheme() + const [showDate, setShowDate] = useState(false) + const [showSets, setShowSets] = useState(false) + const [noSound, setNoSound] = useState(false) useFocusEffect( useCallback(() => { NativeModules.AlarmModule.ignoringBattery(setIgnoring) - settingsRepo.findOne({where: {}}).then(setSettings) + settingsRepo.findOne({where: {}}).then(settings => { + setAlarm(settings.alarm) + setVibrate(settings.vibrate) + setSound(settings.sound) + setNotify(settings.notify) + setImages(settings.images) + setShowUnit(settings.showUnit) + setSteps(settings.steps) + setDate(settings.date) + setShowDate(settings.showDate) + setShowSets(settings.showSets) + }) }, []), ) - const update = useCallback( - (value: boolean, field: keyof Settings) => { - settingsRepo.update({}, {[field]: value}) - setSettings({...settings, [field]: value}) - }, - [settings, setSettings], - ) - const changeAlarmEnabled = useCallback( (enabled: boolean) => { if (enabled) @@ -50,19 +60,18 @@ export default function SettingsPage() { }) else toast('Stopped timers running after each set.') if (enabled && !ignoring) setBattery(true) - update(enabled, 'alarm') + setAlarm(enabled) + settingsRepo.update({}, {alarm: enabled}) }, - [setBattery, ignoring, update], + [setBattery, ignoring], ) - const changeVibrate = useCallback( - (enabled: boolean) => { - if (enabled) toast('When a timer completes, vibrate your phone.') - else toast('Stop vibrating at the end of timers.') - update(enabled, 'vibrate') - }, - [update], - ) + const changeVibrate = useCallback((enabled: boolean) => { + if (enabled) toast('When a timer completes, vibrate your phone.') + else toast('Stop vibrating at the end of timers.') + setVibrate(enabled) + settingsRepo.update({}, {vibrate: enabled}) + }, []) const changeSound = useCallback(async () => { const {fileCopyUri} = await DocumentPicker.pickSingle({ @@ -71,124 +80,96 @@ export default function SettingsPage() { }) if (!fileCopyUri) return settingsRepo.update({}, {sound: fileCopyUri}) - setSettings({...settings, sound: fileCopyUri}) + setSound(fileCopyUri) toast('This song will now play after rest timers complete.') - }, [setSettings, settings]) + }, []) - const changeNotify = useCallback( - (enabled: boolean) => { - update(enabled, 'notify') - if (enabled) toast('Show when a set is a new record.') - else toast('Stopped showing notifications for new records.') - }, - [update], - ) + const changeNotify = useCallback((enabled: boolean) => { + setNotify(enabled) + settingsRepo.update({}, {notify: enabled}) + if (enabled) toast('Show when a set is a new record.') + else toast('Stopped showing notifications for new records.') + }, []) - const changeImages = useCallback( - (enabled: boolean) => { - update(enabled, 'images') - if (enabled) toast('Show images for sets.') - else toast('Stopped showing images for sets.') - }, - [update], - ) + const changeImages = useCallback((enabled: boolean) => { + setImages(enabled) + settingsRepo.update({}, {images: enabled}) + if (enabled) toast('Show images for sets.') + else toast('Stopped showing images for sets.') + }, []) - const changeUnit = useCallback( - (enabled: boolean) => { - update(enabled, 'showUnit') - if (enabled) toast('Show option to select unit for sets.') - else toast('Hid unit option for sets.') - }, - [update], - ) + const changeUnit = useCallback((enabled: boolean) => { + setShowUnit(enabled) + settingsRepo.update({}, {showUnit: enabled}) + if (enabled) toast('Show option to select unit for sets.') + else toast('Hid unit option for sets.') + }, []) - const changeSteps = useCallback( - (enabled: boolean) => { - update(enabled, 'steps') - if (enabled) toast('Show steps for a workout.') - else toast('Stopped showing steps for workouts.') - }, - [update], - ) + const changeSteps = useCallback((enabled: boolean) => { + setSteps(enabled) + settingsRepo.update({}, {steps: enabled}) + if (enabled) toast('Show steps for a workout.') + else toast('Stopped showing steps for workouts.') + }, []) - const changeShowDate = useCallback( - (enabled: boolean) => { - update(enabled, 'showDate') - if (enabled) toast('Show date for sets by default.') - else toast('Stopped showing date for sets by default.') - }, - [update], - ) + const changeShowDate = useCallback((enabled: boolean) => { + setShowDate(enabled) + settingsRepo.update({}, {showDate: enabled}) + if (enabled) toast('Show date for sets by default.') + else toast('Stopped showing date for sets by default.') + }, []) - const changeShowSets = useCallback( - (enabled: boolean) => { - update(enabled, 'showSets') - if (enabled) toast('Show target sets for workouts.') - else toast('Stopped showing target sets for workouts.') - }, - [update], - ) + const changeShowSets = useCallback((enabled: boolean) => { + setShowSets(enabled) + settingsRepo.update({}, {showSets: enabled}) + if (enabled) toast('Show target sets for workouts.') + else toast('Stopped showing target sets for workouts.') + }, []) - const changeNoSound = useCallback( - (enabled: boolean) => { - update(enabled, 'noSound') - if (enabled) toast('Disable sound on rest timer alarms.') - else toast('Enabled sound for rest timer alarms.') - }, - [update], - ) + const changeNoSound = useCallback((enabled: boolean) => { + setNoSound(enabled) + settingsRepo.update({}, {noSound: enabled}) + if (enabled) toast('Disable sound on rest timer alarms.') + else toast('Enabled sound for rest timer alarms.') + }, []) const switches: Input[] = [ - {name: 'Rest timers', value: settings.alarm, onChange: changeAlarmEnabled}, - {name: 'Vibrate', value: settings.vibrate, onChange: changeVibrate}, - {name: 'Disable sound', value: settings.noSound, onChange: changeNoSound}, - {name: 'Notifications', value: settings.notify, onChange: changeNotify}, - {name: 'Show images', value: settings.images, onChange: changeImages}, - {name: 'Show unit', value: settings.showUnit, onChange: changeUnit}, - {name: 'Show steps', value: settings.steps, onChange: changeSteps}, - {name: 'Show date', value: settings.showDate, onChange: changeShowDate}, - {name: 'Show sets', value: settings.showSets, onChange: changeShowSets}, + {name: 'Rest timers', value: alarm, onChange: changeAlarmEnabled}, + {name: 'Vibrate', value: vibrate, onChange: changeVibrate}, + {name: 'Disable sound', value: noSound, onChange: changeNoSound}, + {name: 'Notifications', value: notify, onChange: changeNotify}, + {name: 'Show images', value: images, onChange: changeImages}, + {name: 'Show unit', value: showUnit, onChange: changeUnit}, + {name: 'Show steps', value: steps, onChange: changeSteps}, + {name: 'Show date', value: showDate, onChange: changeShowDate}, + {name: 'Show sets', value: showSets, onChange: changeShowSets}, ] const changeTheme = useCallback( (value: string) => { settingsRepo.update({}, {theme: value}) - setSettings({...settings, theme: value}) + setTheme(value) }, - [settings, setSettings], + [setTheme], ) - const changeDate = useCallback( - (value: string) => { - settingsRepo.update({}, {date: value}) - setSettings({...settings, date: value as any}) - }, - [settings, setSettings], - ) + const changeDate = useCallback((value: string) => { + settingsRepo.update({}, {date: value}) + setDate(value) + }, []) - const sound = useMemo(() => { - if (!settings.sound) return null - const split = settings.sound.split('/') + const soundString = useMemo(() => { + if (!sound) return null + const split = sound.split('/') return ': ' + split.pop() - }, [settings.sound]) - - const theme = useMemo(() => { - if (!'theme'.includes(term.toLowerCase())) return null - return ( - - ) - }, [term, changeTheme, settings.theme]) + }, [sound]) const changeColor = useCallback( (value: string) => { - setSettings({...settings, color: value}) + setColor(value) settingsRepo.update({}, {color: value}) }, - [setSettings, settings], + [setColor], ) return ( @@ -209,9 +190,15 @@ export default function SettingsPage() { {input.name} ))} - {theme} + {'theme'.includes(term.toLowerCase()) && ( + + )} {'color'.includes(term.toLowerCase()) && ( - {lightColors.concat(darkColors).map(colorOption => ( )} {'date format'.includes(term.toLowerCase()) && ( - @@ -240,7 +227,7 @@ export default function SettingsPage() { )} {'alarm sound'.includes(term.toLowerCase()) && ( )}