Memoize the most expensive parts of SettingsPage

This commit is contained in:
Brandon Presley 2023-01-01 13:39:10 +13:00
parent 5335f4afbc
commit 86f01eb002
1 changed files with 114 additions and 98 deletions

View File

@ -30,7 +30,6 @@ export default function SettingsPage() {
const [formatOptions, setFormatOptions] = useState<string[]>(twelveHours) const [formatOptions, setFormatOptions] = useState<string[]>(twelveHours)
const [importing, setImporting] = useState(false) const [importing, setImporting] = useState(false)
const {reset} = useNavigation<NavigationProp<DrawerParamList>>() const {reset} = useNavigation<NavigationProp<DrawerParamList>>()
const today = new Date()
const {watch, setValue} = useForm<Settings>({ const {watch, setValue} = useForm<Settings>({
defaultValues: () => settingsRepo.findOne({where: {}}), defaultValues: () => settingsRepo.findOne({where: {}}),
@ -80,32 +79,9 @@ export default function SettingsPage() {
[settings], [settings],
) )
const changeString = useCallback( const filter = useCallback(
async (key: keyof Settings, value: string) => { ({name}) => name.toLowerCase().includes(term.toLowerCase()),
setValue(key, value) [term],
await settingsRepo.save({...settings, [key]: value})
switch (key) {
case 'date':
return toast('Changed date format')
case 'darkColor':
setDarkColor(value)
return toast('Set primary color for dark mode.')
case 'lightColor':
setLightColor(value)
return toast('Set primary color for light mode.')
case 'vibrate':
return toast('Set primary color for light mode.')
case 'sound':
return toast('Sound will play after rest timers.')
case 'theme':
setTheme(value as string)
if (value === 'dark') toast('Theme will always be dark.')
else if (value === 'light') toast('Theme will always be light.')
else if (value === 'system') toast('Theme will follow system.')
return
}
},
[settings, setTheme, setDarkColor, setLightColor, setValue],
) )
const changeBoolean = useCallback( const changeBoolean = useCallback(
@ -163,30 +139,66 @@ export default function SettingsPage() {
[changeBoolean], [changeBoolean],
) )
const selects: Input<string>[] = [ const switchesMarkup = useMemo(
{name: 'Theme', value: theme, items: themeOptions, key: 'theme'}, () => switches.filter(filter).map(s => renderSwitch(s)),
{ [filter, switches, renderSwitch],
name: 'Dark color', )
value: darkColor,
items: lightOptions, const changeString = useCallback(
key: 'darkColor', async (key: keyof Settings, value: string) => {
setValue(key, value)
await settingsRepo.save({...settings, [key]: value})
switch (key) {
case 'date':
return toast('Changed date format')
case 'darkColor':
setDarkColor(value)
return toast('Set primary color for dark mode.')
case 'lightColor':
setLightColor(value)
return toast('Set primary color for light mode.')
case 'vibrate':
return toast('Set primary color for light mode.')
case 'sound':
return toast('Sound will play after rest timers.')
case 'theme':
setTheme(value as string)
if (value === 'dark') toast('Theme will always be dark.')
else if (value === 'light') toast('Theme will always be light.')
else if (value === 'system') toast('Theme will follow system.')
return
}
}, },
{ [settings, setTheme, setDarkColor, setLightColor, setValue],
name: 'Light color', )
value: lightColor,
items: darkOptions, const selects: Input<string>[] = useMemo(() => {
key: 'lightColor', const today = new Date()
}, return [
{ {name: 'Theme', value: theme, items: themeOptions, key: 'theme'},
name: 'Date format', {
value: settings.date, name: 'Dark color',
items: formatOptions.map(option => ({ value: darkColor,
label: format(today, option), items: lightOptions,
value: option, key: 'darkColor',
})), },
key: 'date', {
}, name: 'Light color',
] value: lightColor,
items: darkOptions,
key: 'lightColor',
},
{
name: 'Date format',
value: settings.date,
items: formatOptions.map(option => ({
label: format(today, option),
value: option,
})),
key: 'date',
},
]
}, [settings.date, darkColor, formatOptions, theme, lightColor])
const renderSelect = useCallback( const renderSelect = useCallback(
(item: Input<string>) => ( (item: Input<string>) => (
@ -201,6 +213,11 @@ export default function SettingsPage() {
[changeString], [changeString],
) )
const selectsMarkup = useMemo(
() => selects.filter(filter).map(renderSelect),
[filter, selects, renderSelect],
)
const confirmImport = useCallback(async () => { const confirmImport = useCallback(async () => {
setImporting(false) setImporting(false)
await AppDataSource.destroy() await AppDataSource.destroy()
@ -222,53 +239,52 @@ export default function SettingsPage() {
toast('Database exported. Check downloads.') toast('Database exported. Check downloads.')
}, []) }, [])
const filter = useCallback( const buttons = useMemo(
({name}) => name.toLowerCase().includes(term.toLowerCase()), () => [
[term], {
name: 'Alarm sound',
element: (
<View
key="alarm-sound"
style={{
flexDirection: 'row',
alignItems: 'center',
paddingLeft: ITEM_PADDING,
}}>
<Subheading style={{width: 100}}>Alarm sound</Subheading>
<Button onPress={changeSound}>{soundString || 'Default'}</Button>
</View>
),
},
{
name: 'Export database',
element: (
<Button
key="export-db"
style={{alignSelf: 'flex-start'}}
onPress={exportDatabase}>
Export database
</Button>
),
},
{
name: 'Import database',
element: (
<Button
key="import-db"
style={{alignSelf: 'flex-start'}}
onPress={() => setImporting(true)}>
Import database
</Button>
),
},
],
[changeSound, exportDatabase, soundString],
) )
const buttons = useMemo( const buttonsMarkup = useMemo(
() => () => buttons.filter(filter).map(b => b.element),
[ [buttons, filter],
{
name: 'Alarm sound',
element: (
<View
key="alarm-sound"
style={{
flexDirection: 'row',
alignItems: 'center',
paddingLeft: ITEM_PADDING,
}}>
<Subheading style={{width: 100}}>Alarm sound</Subheading>
<Button onPress={changeSound}>{soundString || 'Default'}</Button>
</View>
),
},
{
name: 'Export database',
element: (
<Button
key="export-db"
style={{alignSelf: 'flex-start'}}
onPress={exportDatabase}>
Export database
</Button>
),
},
{
name: 'Import database',
element: (
<Button
key="import-db"
style={{alignSelf: 'flex-start'}}
onPress={() => setImporting(true)}>
Import database
</Button>
),
},
].filter(filter),
[changeSound, exportDatabase, soundString, filter],
) )
return ( return (
@ -277,9 +293,9 @@ export default function SettingsPage() {
<Page term={term} search={setTerm} style={{flexGrow: 0}}> <Page term={term} search={setTerm} style={{flexGrow: 0}}>
<View style={{marginTop: MARGIN}}> <View style={{marginTop: MARGIN}}>
{switches.filter(filter).map(s => renderSwitch(s))} {switchesMarkup}
{selects.filter(filter).map(s => renderSelect(s))} {selectsMarkup}
{buttons.map(b => b.element)} {buttonsMarkup}
</View> </View>
</Page> </Page>