From f9e357ff80b0c509485af00d258af0569cb85fdd Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Wed, 21 Dec 2022 13:02:53 +1300 Subject: [PATCH 01/13] Factor out list menu --- ListMenu.tsx | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ PlanList.tsx | 76 +++++------------------------------------- SetList.tsx | 76 +++++------------------------------------- 3 files changed, 111 insertions(+), 134 deletions(-) create mode 100644 ListMenu.tsx diff --git a/ListMenu.tsx b/ListMenu.tsx new file mode 100644 index 0000000..488ec7d --- /dev/null +++ b/ListMenu.tsx @@ -0,0 +1,93 @@ +import {useState} from 'react' +import {Divider, IconButton, Menu} from 'react-native-paper' +import ConfirmDialog from './ConfirmDialog' +import useDark from './use-dark' + +export default function ListMenu({ + onEdit, + onCopy, + onClear, + onDelete, + ids, +}: { + onEdit: () => void + onCopy: () => void + onClear: () => void + onDelete: () => void + ids?: number[] +}) { + const [showMenu, setShowMenu] = useState(false) + const [showRemove, setShowRemove] = useState(false) + const dark = useDark() + + const edit = () => { + setShowMenu(false) + onEdit() + } + + const copy = () => { + setShowMenu(false) + onCopy() + } + + const clear = () => { + setShowMenu(false) + onClear() + } + + const remove = () => { + setShowMenu(false) + setShowRemove(false) + onDelete() + } + + return ( + setShowMenu(false)} + anchor={ + setShowMenu(true)} + icon="more-vert" + /> + }> + + + + + setShowRemove(true)} + title="Delete" + /> + setShowMenu(false)}> + {ids?.length === 0 ? ( + <>This irreversibly deletes records from the app. Are you sure? + ) : ( + <>This will delete {ids?.length} record(s). Are you sure? + )} + + + ) +} diff --git a/PlanList.tsx b/PlanList.tsx index 0b4ec35..2629010 100644 --- a/PlanList.tsx +++ b/PlanList.tsx @@ -5,24 +5,20 @@ import { } from '@react-navigation/native' import {useCallback, useState} from 'react' import {FlatList} from 'react-native' -import {Divider, IconButton, List, Menu} from 'react-native-paper' +import {List} from 'react-native-paper' import {Like} from 'typeorm' -import ConfirmDialog from './ConfirmDialog' import {planRepo} from './db' import DrawerHeader from './DrawerHeader' +import ListMenu from './ListMenu' import Page from './Page' import {Plan} from './plan' import {PlanPageParams} from './plan-page-params' import PlanItem from './PlanItem' -import useDark from './use-dark' export default function PlanList() { const [term, setTerm] = useState('') const [plans, setPlans] = useState() const [ids, setIds] = useState([]) - const [showMenu, setShowMenu] = useState(false) - const [showRemove, setShowRemove] = useState(false) - const dark = useDark() const navigation = useNavigation>() const refresh = useCallback(async (value: string) => { @@ -58,14 +54,12 @@ export default function PlanList() { navigation.navigate('EditPlan', {plan: {days: '', workouts: ''}}) const edit = useCallback(async () => { - setShowMenu(false) const plan = await planRepo.findOne({where: {id: ids.pop()}}) navigation.navigate('EditPlan', {plan}) setIds([]) }, [ids, navigation]) const copy = useCallback(async () => { - setShowMenu(false) const plan = await planRepo.findOne({ where: {id: ids.pop()}, }) @@ -75,77 +69,25 @@ export default function PlanList() { }, [ids, navigation]) const clear = useCallback(() => { - setShowMenu(false) setIds([]) }, []) const remove = useCallback(async () => { - setShowMenu(false) - setShowRemove(false) await planRepo.delete(ids.length > 0 ? ids : {}) await refresh(term) setIds([]) }, [ids, refresh, term]) - const menuItems = ( - <> - - - - - setShowRemove(true)} - title="Delete" - /> - - ) - return ( <> - setShowMenu(false)} - anchor={ - setShowMenu(true)} - icon="more-vert" - /> - }> - {menuItems} - - setShowMenu(false)}> - {ids?.length === 0 ? ( - <> - This irreversibly deletes all plans from the app. Are you sure? - - ) : ( - <>This will delete {ids?.length} plan(s). Are you sure? - )} - - + {plans?.length === 0 ? ( diff --git a/SetList.tsx b/SetList.tsx index a08b212..f971fcb 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -5,17 +5,16 @@ import { } from '@react-navigation/native' import {useCallback, useState} from 'react' import {FlatList} from 'react-native' -import {Divider, IconButton, List, Menu} from 'react-native-paper' +import {List} from 'react-native-paper' import {Like} from 'typeorm' -import ConfirmDialog from './ConfirmDialog' import {getNow, setRepo, settingsRepo} from './db' import DrawerHeader from './DrawerHeader' import GymSet, {defaultSet} from './gym-set' import {HomePageParams} from './home-page-params' +import ListMenu from './ListMenu' import Page from './Page' import SetItem from './SetItem' import Settings from './settings' -import useDark from './use-dark' const limit = 15 @@ -26,9 +25,6 @@ export default function SetList() { const [end, setEnd] = useState(false) const [settings, setSettings] = useState() const [ids, setIds] = useState([]) - const [showMenu, setShowMenu] = useState(false) - const [showRemove, setShowRemove] = useState(false) - const dark = useDark() const navigation = useNavigation>() const refresh = useCallback(async (value: string) => { @@ -104,13 +100,11 @@ export default function SetList() { ) const edit = useCallback(() => { - setShowMenu(false) navigation.navigate('EditSets', {ids}) setIds([]) }, [ids, navigation]) const copy = useCallback(async () => { - setShowMenu(false) const set = await setRepo.findOne({ where: {id: ids.pop()}, }) @@ -121,77 +115,25 @@ export default function SetList() { }, [ids, navigation]) const clear = useCallback(() => { - setShowMenu(false) setIds([]) }, []) const remove = useCallback(async () => { setIds([]) - setShowMenu(false) - setShowRemove(false) await setRepo.delete(ids.length > 0 ? ids : {}) await refresh(term) }, [ids, refresh, term]) - const menuItems = ( - <> - - - - - setShowRemove(true)} - title="Delete" - /> - - ) - return ( <> - setShowMenu(false)} - anchor={ - setShowMenu(true)} - icon="more-vert" - /> - }> - {menuItems} - - setShowMenu(false)}> - {ids?.length === 0 ? ( - <> - This irreversibly deletes all sets from the app. Are you sure? - - ) : ( - <>This will delete {ids?.length} set(s). Are you sure? - )} - - + From fb19685bb5657bf4ba45e26e649e85966e6b99d3 Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Thu, 22 Dec 2022 16:18:05 +1300 Subject: [PATCH 02/13] Change delete menu title if selected Closes #133 --- ListMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ListMenu.tsx b/ListMenu.tsx index 488ec7d..fc7e51d 100644 --- a/ListMenu.tsx +++ b/ListMenu.tsx @@ -77,7 +77,7 @@ export default function ListMenu({ title="Delete" /> Date: Thu, 22 Dec 2022 17:08:01 +1300 Subject: [PATCH 03/13] Add select all button Very useful final addition to the multi edit/delete function. Typically a user will search for certain criteria, and then select them all to be removed/edited. For example, if yesterdays sets were all 10x150kg deadlifts, but you review your form video and decide the form sucked, you would want to mass edit them to lower the weight/reps (or maybe delete them). This way you won't have these invalid entries ruining all your progress graphs (showing false progress). --- ListMenu.tsx | 8 ++++++++ PlanList.tsx | 5 +++++ SetList.tsx | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/ListMenu.tsx b/ListMenu.tsx index fc7e51d..dc661b4 100644 --- a/ListMenu.tsx +++ b/ListMenu.tsx @@ -8,12 +8,14 @@ export default function ListMenu({ onCopy, onClear, onDelete, + onSelect, ids, }: { onEdit: () => void onCopy: () => void onClear: () => void onDelete: () => void + onSelect: () => void ids?: number[] }) { const [showMenu, setShowMenu] = useState(false) @@ -41,6 +43,11 @@ export default function ListMenu({ onDelete() } + const select = () => { + setShowMenu(false) + onSelect() + } + return ( }> + { + setIds(plans.map(plan => plan.id)) + }, [plans]) + return ( <> @@ -87,6 +91,7 @@ export default function PlanList() { onDelete={remove} onEdit={edit} ids={ids} + onSelect={select} /> diff --git a/SetList.tsx b/SetList.tsx index f971fcb..9378c70 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -124,6 +124,10 @@ export default function SetList() { await refresh(term) }, [ids, refresh, term]) + const select = useCallback(() => { + setIds(sets.map(set => set.id)) + }, [sets]) + return ( <> @@ -133,6 +137,7 @@ export default function SetList() { onDelete={remove} onEdit={edit} ids={ids} + onSelect={select} /> From 777eddf943b70992f876b85fc0a8a4472b854425 Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Thu, 22 Dec 2022 19:14:34 +1300 Subject: [PATCH 04/13] Remove usage of FlatList in Settings page Doing so looks like it improved the performance of the switches. Related to #135. --- SettingsPage.tsx | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/SettingsPage.tsx b/SettingsPage.tsx index b3b40b2..06ee7a3 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -5,13 +5,7 @@ import { } from '@react-navigation/native' import {format} from 'date-fns' import {useCallback, useMemo, useState} from 'react' -import { - DeviceEventEmitter, - FlatList, - NativeModules, - Platform, - View, -} from 'react-native' +import {DeviceEventEmitter, NativeModules, Platform, View} from 'react-native' import DocumentPicker from 'react-native-document-picker' import {Dirs, FileSystem} from 'react-native-file-access' import {Button, Subheading} from 'react-native-paper' @@ -198,7 +192,7 @@ export default function SettingsPage() { ) const renderSwitch = useCallback( - ({item}: {item: Input}) => ( + (item: Input) => ( item.onChange(!item.value)} key={item.name} @@ -236,7 +230,7 @@ export default function SettingsPage() { ].filter(({name}) => name.toLowerCase().includes(term.toLowerCase())) const renderSelect = useCallback( - ({item}: {item: Input}) => ( + (item: Input) => ( Date: Sat, 24 Dec 2022 13:36:11 +1300 Subject: [PATCH 10/13] Factor out buttons in SettingsPage --- SettingsPage.tsx | 54 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/SettingsPage.tsx b/SettingsPage.tsx index df4639e..8f2d0de 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -262,16 +262,13 @@ export default function SettingsPage() { toast('Database exported. Check downloads.') }, []) - return ( - <> - - - - {switches.map(s => renderSwitch(s))} - - <>{selects.map(s => renderSelect(s))} - {'alarm sound'.includes(term.toLowerCase()) && ( + const buttons = useMemo( + () => [ + { + name: 'Alarm sound', + element: ( Alarm sound - )} - {'export database'.includes(term.toLowerCase()) && ( - - )} - {'import database'.includes(term.toLowerCase()) && ( + ), + }, + { + name: 'Import database', + element: ( - )} + ), + }, + ], + [changeSound, exportDatabase, soundString], + ) + + return ( + <> + + + + + {switches.map(s => renderSwitch(s))} + {selects.map(s => renderSelect(s))} + {buttons + .filter(b => b.name.includes(term.toLowerCase())) + .map(b => b.element)} + Date: Sat, 24 Dec 2022 19:55:38 +1300 Subject: [PATCH 11/13] Simplify Switch.tsx --- EditPlan.tsx | 8 +++----- SettingsPage.tsx | 6 +----- Switch.tsx | 10 ++++------ 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/EditPlan.tsx b/EditPlan.tsx index c857a85..4e69281 100644 --- a/EditPlan.tsx +++ b/EditPlan.tsx @@ -79,8 +79,7 @@ export default function EditPlan() { {DAYS.map(day => ( toggleDay(value, day)} - onPress={() => toggleDay(!days.includes(day), day)} + onChange={value => toggleDay(value, day)} value={days.includes(day)}> {day} @@ -94,9 +93,8 @@ export default function EditPlan() { names.map(name => ( toggleWorkout(value, name)} - value={workouts.includes(name)} - onPress={() => toggleWorkout(!workouts.includes(name), name)}> + onChange={value => toggleWorkout(value, name)} + value={workouts.includes(name)}> {name} )) diff --git a/SettingsPage.tsx b/SettingsPage.tsx index 8f2d0de..64478ee 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -192,11 +192,7 @@ export default function SettingsPage() { const renderSwitch = useCallback( (item: Input) => ( - item.onChange(!item.value)} - key={item.name} - value={item.value} - onValueChange={item.onChange}> + {item.name} ), diff --git a/Switch.tsx b/Switch.tsx index 3885ded..198b1bd 100644 --- a/Switch.tsx +++ b/Switch.tsx @@ -4,20 +4,18 @@ import {MARGIN} from './constants' export default function Switch({ value, - onValueChange, - onPress, + onChange, children, }: { value?: boolean - onValueChange: (value: boolean) => void - onPress: () => void + onChange: (value: boolean) => void children: string }) { const {colors} = useTheme() return ( onChange(!value)} style={{ flexDirection: 'row', flexWrap: 'wrap', @@ -28,7 +26,7 @@ export default function Switch({ color={colors.primary} style={{marginRight: MARGIN}} value={value} - onValueChange={onValueChange} + onValueChange={onChange} /> {children} From 60cc619e391aad6dfcdb42fb7b3cd84acefed0c2 Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Sat, 24 Dec 2022 19:58:55 +1300 Subject: [PATCH 12/13] Move button filter to memoized call This reduces re-renders --- SettingsPage.tsx | 85 ++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/SettingsPage.tsx b/SettingsPage.tsx index 64478ee..5987c80 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -259,46 +259,47 @@ export default function SettingsPage() { }, []) const buttons = useMemo( - () => [ - { - name: 'Alarm sound', - element: ( - - Alarm sound - - - ), - }, - { - name: 'Export database', - element: ( - - ), - }, - { - name: 'Import database', - element: ( - - ), - }, - ], - [changeSound, exportDatabase, soundString], + () => + [ + { + name: 'Alarm sound', + element: ( + + Alarm sound + + + ), + }, + { + name: 'Export database', + element: ( + + ), + }, + { + name: 'Import database', + element: ( + + ), + }, + ].filter(({name}) => name.toLowerCase().includes(term.toLowerCase())), + [changeSound, exportDatabase, soundString, term], ) return ( @@ -309,9 +310,7 @@ export default function SettingsPage() { {switches.map(s => renderSwitch(s))} {selects.map(s => renderSelect(s))} - {buttons - .filter(b => b.name.includes(term.toLowerCase())) - .map(b => b.element)} + {buttons.map(b => b.element)} From a9b86fb5558ffd605df05a8d124c2ec411049c2d Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Sat, 24 Dec 2022 20:10:26 +1300 Subject: [PATCH 13/13] Set versionCode=36125 --- android/app/build.gradle | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0428b1f..48fff25 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -41,8 +41,8 @@ android { missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 36124 - versionName "1.98" + versionCode 36125 + versionName "1.99" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/package.json b/package.json index a98eb71..8091f23 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "massive", - "version": "1.98", + "version": "1.99", "private": true, "license": "GPL-3.0-only", "scripts": {