Refactor MassiveSnack
Instead of using a context for the whole app use DeviceEventEmitter with root state. This will probably improve performance, since I think the react context was re-rendering the entire DOM tree.
This commit is contained in:
parent
ace327ecad
commit
49b5eb48c6
34
App.tsx
34
App.tsx
|
@ -4,19 +4,20 @@ import {
|
||||||
NavigationContainer,
|
NavigationContainer,
|
||||||
} from '@react-navigation/native'
|
} from '@react-navigation/native'
|
||||||
import {useEffect, useMemo, useState} from 'react'
|
import {useEffect, useMemo, useState} from 'react'
|
||||||
import {useColorScheme} from 'react-native'
|
import {DeviceEventEmitter, useColorScheme} from 'react-native'
|
||||||
import {
|
import {
|
||||||
DarkTheme as PaperDarkTheme,
|
DarkTheme as PaperDarkTheme,
|
||||||
DefaultTheme as PaperDefaultTheme,
|
DefaultTheme as PaperDefaultTheme,
|
||||||
Provider as PaperProvider,
|
Provider as PaperProvider,
|
||||||
|
Snackbar,
|
||||||
} from 'react-native-paper'
|
} from 'react-native-paper'
|
||||||
import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
|
import MaterialIcon from 'react-native-vector-icons/MaterialIcons'
|
||||||
import {lightColors} from './colors'
|
import {lightColors} from './colors'
|
||||||
import {AppDataSource} from './data-source'
|
import {AppDataSource} from './data-source'
|
||||||
import {settingsRepo} from './db'
|
import {settingsRepo} from './db'
|
||||||
import MassiveSnack from './MassiveSnack'
|
|
||||||
import Routes from './Routes'
|
import Routes from './Routes'
|
||||||
import Settings from './settings'
|
import Settings from './settings'
|
||||||
|
import {TOAST} from './toast'
|
||||||
import {defaultSettings, SettingsContext} from './use-settings'
|
import {defaultSettings, SettingsContext} from './use-settings'
|
||||||
|
|
||||||
export const CombinedDefaultTheme = {
|
export const CombinedDefaultTheme = {
|
||||||
|
@ -48,6 +49,7 @@ const App = () => {
|
||||||
? CombinedDarkTheme.colors.primary
|
? CombinedDarkTheme.colors.primary
|
||||||
: CombinedDefaultTheme.colors.primary,
|
: CombinedDefaultTheme.colors.primary,
|
||||||
})
|
})
|
||||||
|
const [snackbar, setSnackbar] = useState('')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
AppDataSource.initialize().then(async () => {
|
AppDataSource.initialize().then(async () => {
|
||||||
|
@ -56,6 +58,10 @@ const App = () => {
|
||||||
setSettings(gotSettings)
|
setSettings(gotSettings)
|
||||||
setInitialized(true)
|
setInitialized(true)
|
||||||
})
|
})
|
||||||
|
DeviceEventEmitter.addListener(TOAST, ({value}: {value: string}) => {
|
||||||
|
console.log(`${Routes.name}.toast:`, {value})
|
||||||
|
setSnackbar(value)
|
||||||
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const theme = useMemo(() => {
|
const theme = useMemo(() => {
|
||||||
|
@ -87,14 +93,24 @@ const App = () => {
|
||||||
theme={theme}
|
theme={theme}
|
||||||
settings={{icon: props => <MaterialIcon {...props} />}}>
|
settings={{icon: props => <MaterialIcon {...props} />}}>
|
||||||
<NavigationContainer theme={theme}>
|
<NavigationContainer theme={theme}>
|
||||||
<MassiveSnack>
|
{initialized && (
|
||||||
{initialized && (
|
<SettingsContext.Provider value={settingsContext}>
|
||||||
<SettingsContext.Provider value={settingsContext}>
|
<Routes />
|
||||||
<Routes />
|
</SettingsContext.Provider>
|
||||||
</SettingsContext.Provider>
|
)}
|
||||||
)}
|
|
||||||
</MassiveSnack>
|
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
|
|
||||||
|
<Snackbar
|
||||||
|
duration={3000}
|
||||||
|
onDismiss={() => setSnackbar('')}
|
||||||
|
visible={!!snackbar}
|
||||||
|
action={{
|
||||||
|
label: 'Close',
|
||||||
|
onPress: () => setSnackbar(''),
|
||||||
|
color: theme.colors.primary,
|
||||||
|
}}>
|
||||||
|
{snackbar}
|
||||||
|
</Snackbar>
|
||||||
</PaperProvider>
|
</PaperProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ import {AppDataSource} from './data-source'
|
||||||
import {planRepo} from './db'
|
import {planRepo} from './db'
|
||||||
import {DrawerParamList} from './drawer-param-list'
|
import {DrawerParamList} from './drawer-param-list'
|
||||||
import GymSet from './gym-set'
|
import GymSet from './gym-set'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
|
||||||
import {Plan} from './plan'
|
import {Plan} from './plan'
|
||||||
|
import {toast} from './toast'
|
||||||
import useDark from './use-dark'
|
import useDark from './use-dark'
|
||||||
import {write} from './write'
|
import {write} from './write'
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ const setRepo = AppDataSource.manager.getRepository(GymSet)
|
||||||
export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
const [showMenu, setShowMenu] = useState(false)
|
const [showMenu, setShowMenu] = useState(false)
|
||||||
const [showRemove, setShowRemove] = useState(false)
|
const [showRemove, setShowRemove] = useState(false)
|
||||||
const {toast} = useSnackbar()
|
|
||||||
const {reset} = useNavigation<NavigationProp<DrawerParamList>>()
|
const {reset} = useNavigation<NavigationProp<DrawerParamList>>()
|
||||||
const dark = useDark()
|
const dark = useDark()
|
||||||
|
|
||||||
|
@ -65,7 +64,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
console.log(`${DrawerMenu.name}.uploadSets:`, file.length)
|
console.log(`${DrawerMenu.name}.uploadSets:`, file.length)
|
||||||
const lines = file.split('\n')
|
const lines = file.split('\n')
|
||||||
console.log(lines[0])
|
console.log(lines[0])
|
||||||
if (!setFields.includes(lines[0])) return toast('Invalid csv.', 3000)
|
if (!setFields.includes(lines[0])) return toast('Invalid csv.')
|
||||||
const values = lines
|
const values = lines
|
||||||
.slice(1)
|
.slice(1)
|
||||||
.filter(line => line)
|
.filter(line => line)
|
||||||
|
@ -92,21 +91,22 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
sets: +sets,
|
sets: +sets,
|
||||||
minutes: +minutes,
|
minutes: +minutes,
|
||||||
seconds: +seconds,
|
seconds: +seconds,
|
||||||
|
image: '',
|
||||||
}
|
}
|
||||||
return set
|
return set
|
||||||
})
|
})
|
||||||
console.log(`${DrawerMenu.name}.uploadSets:`, {values})
|
console.log(`${DrawerMenu.name}.uploadSets:`, {values})
|
||||||
await setRepo.insert(values)
|
await setRepo.insert(values)
|
||||||
toast('Data imported.', 3000)
|
toast('Data imported.')
|
||||||
reset({index: 0, routes: [{name}]})
|
reset({index: 0, routes: [{name}]})
|
||||||
}, [reset, name, toast])
|
}, [reset, name])
|
||||||
|
|
||||||
const uploadPlans = useCallback(async () => {
|
const uploadPlans = useCallback(async () => {
|
||||||
const result = await DocumentPicker.pickSingle()
|
const result = await DocumentPicker.pickSingle()
|
||||||
const file = await FileSystem.readFile(result.uri)
|
const file = await FileSystem.readFile(result.uri)
|
||||||
console.log(`${DrawerMenu.name}.uploadPlans:`, file.length)
|
console.log(`${DrawerMenu.name}.uploadPlans:`, file.length)
|
||||||
const lines = file.split('\n')
|
const lines = file.split('\n')
|
||||||
if (lines[0] != planFields) return toast('Invalid csv.', 3000)
|
if (lines[0] !== planFields) return toast('Invalid csv.')
|
||||||
const values = file
|
const values = file
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.slice(1)
|
.slice(1)
|
||||||
|
@ -122,8 +122,8 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
return plan
|
return plan
|
||||||
})
|
})
|
||||||
await planRepo.insert(values)
|
await planRepo.insert(values)
|
||||||
toast('Data imported.', 3000)
|
toast('Data imported.')
|
||||||
}, [toast])
|
}, [])
|
||||||
|
|
||||||
const upload = useCallback(async () => {
|
const upload = useCallback(async () => {
|
||||||
setShowMenu(false)
|
setShowMenu(false)
|
||||||
|
@ -137,9 +137,9 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
setShowRemove(false)
|
setShowRemove(false)
|
||||||
if (name === 'Home') await setRepo.delete({})
|
if (name === 'Home') await setRepo.delete({})
|
||||||
else if (name === 'Plans') await planRepo.delete({})
|
else if (name === 'Plans') await planRepo.delete({})
|
||||||
toast('All data has been deleted.', 4000)
|
toast('All data has been deleted.')
|
||||||
reset({index: 0, routes: [{name}]})
|
reset({index: 0, routes: [{name}]})
|
||||||
}, [reset, name, toast])
|
}, [reset, name])
|
||||||
|
|
||||||
if (name === 'Home' || name === 'Plans')
|
if (name === 'Home' || name === 'Plans')
|
||||||
return (
|
return (
|
||||||
|
|
12
EditSet.tsx
12
EditSet.tsx
|
@ -2,19 +2,18 @@ import {RouteProp, useNavigation, useRoute} from '@react-navigation/native'
|
||||||
import {useCallback} from 'react'
|
import {useCallback} from 'react'
|
||||||
import {NativeModules, View} from 'react-native'
|
import {NativeModules, View} from 'react-native'
|
||||||
import {PADDING} from './constants'
|
import {PADDING} from './constants'
|
||||||
import {getNow, setRepo} from './db'
|
import {setRepo} from './db'
|
||||||
import GymSet from './gym-set'
|
import GymSet from './gym-set'
|
||||||
import {HomePageParams} from './home-page-params'
|
import {HomePageParams} from './home-page-params'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
|
||||||
import SetForm from './SetForm'
|
import SetForm from './SetForm'
|
||||||
import StackHeader from './StackHeader'
|
import StackHeader from './StackHeader'
|
||||||
|
import {toast} from './toast'
|
||||||
import {useSettings} from './use-settings'
|
import {useSettings} from './use-settings'
|
||||||
|
|
||||||
export default function EditSet() {
|
export default function EditSet() {
|
||||||
const {params} = useRoute<RouteProp<HomePageParams, 'EditSet'>>()
|
const {params} = useRoute<RouteProp<HomePageParams, 'EditSet'>>()
|
||||||
const {set} = params
|
const {set} = params
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const {toast} = useSnackbar()
|
|
||||||
const {settings} = useSettings()
|
const {settings} = useSettings()
|
||||||
|
|
||||||
const startTimer = useCallback(
|
const startTimer = useCallback(
|
||||||
|
@ -35,9 +34,6 @@ export default function EditSet() {
|
||||||
const add = useCallback(
|
const add = useCallback(
|
||||||
async (value: GymSet) => {
|
async (value: GymSet) => {
|
||||||
startTimer(value.name)
|
startTimer(value.name)
|
||||||
const [{now}] = await getNow()
|
|
||||||
value.created = now
|
|
||||||
value.hidden = false
|
|
||||||
console.log(`${EditSet.name}.add`, {set: value})
|
console.log(`${EditSet.name}.add`, {set: value})
|
||||||
const result = await setRepo.save(value)
|
const result = await setRepo.save(value)
|
||||||
console.log({result})
|
console.log({result})
|
||||||
|
@ -46,9 +42,9 @@ export default function EditSet() {
|
||||||
value.weight > set.weight ||
|
value.weight > set.weight ||
|
||||||
(value.reps > set.reps && value.weight === set.weight)
|
(value.reps > set.reps && value.weight === set.weight)
|
||||||
)
|
)
|
||||||
toast("Great work King! That's a new record.", 3000)
|
toast("Great work King! That's a new record.")
|
||||||
},
|
},
|
||||||
[startTimer, set, toast, settings],
|
[startTimer, set, settings],
|
||||||
)
|
)
|
||||||
|
|
||||||
const save = useCallback(
|
const save = useCallback(
|
||||||
|
|
|
@ -7,8 +7,8 @@ import ConfirmDialog from './ConfirmDialog'
|
||||||
import {MARGIN, PADDING} from './constants'
|
import {MARGIN, PADDING} from './constants'
|
||||||
import {getNow, planRepo, setRepo} from './db'
|
import {getNow, planRepo, setRepo} from './db'
|
||||||
import MassiveInput from './MassiveInput'
|
import MassiveInput from './MassiveInput'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
|
||||||
import StackHeader from './StackHeader'
|
import StackHeader from './StackHeader'
|
||||||
|
import {toast} from './toast'
|
||||||
import {useSettings} from './use-settings'
|
import {useSettings} from './use-settings'
|
||||||
import {WorkoutsPageParams} from './WorkoutsPage'
|
import {WorkoutsPageParams} from './WorkoutsPage'
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ export default function EditWorkout() {
|
||||||
params.value.seconds?.toString() ?? '30',
|
params.value.seconds?.toString() ?? '30',
|
||||||
)
|
)
|
||||||
const [sets, setSets] = useState(params.value.sets?.toString() ?? '3')
|
const [sets, setSets] = useState(params.value.sets?.toString() ?? '3')
|
||||||
const {toast} = useSnackbar()
|
|
||||||
const navigation = useNavigation()
|
const navigation = useNavigation()
|
||||||
const setsRef = useRef<TextInput>(null)
|
const setsRef = useRef<TextInput>(null)
|
||||||
const stepsRef = useRef<TextInput>(null)
|
const stepsRef = useRef<TextInput>(null)
|
||||||
|
@ -94,13 +93,13 @@ export default function EditWorkout() {
|
||||||
const handleName = (value: string) => {
|
const handleName = (value: string) => {
|
||||||
setName(value.replace(/,|'/g, ''))
|
setName(value.replace(/,|'/g, ''))
|
||||||
if (value.match(/,|'/))
|
if (value.match(/,|'/))
|
||||||
toast('Commas and single quotes would break CSV exports', 6000)
|
toast('Commas and single quotes would break CSV exports')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSteps = (value: string) => {
|
const handleSteps = (value: string) => {
|
||||||
setSteps(value.replace(/,|'/g, ''))
|
setSteps(value.replace(/,|'/g, ''))
|
||||||
if (value.match(/,|'/))
|
if (value.match(/,|'/))
|
||||||
toast('Commas and single quotes would break CSV exports', 6000)
|
toast('Commas and single quotes would break CSV exports')
|
||||||
}
|
}
|
||||||
|
|
||||||
const submitName = () => {
|
const submitName = () => {
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
import {createContext, useContext, useState} from 'react'
|
|
||||||
import {Snackbar} from 'react-native-paper'
|
|
||||||
import {CombinedDarkTheme, CombinedDefaultTheme} from './App'
|
|
||||||
import useDark from './use-dark'
|
|
||||||
|
|
||||||
export const SnackbarContext = createContext<{
|
|
||||||
toast: (value: string, timeout: number) => void
|
|
||||||
}>({toast: () => null})
|
|
||||||
|
|
||||||
export const useSnackbar = () => {
|
|
||||||
return useContext(SnackbarContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MassiveSnack({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children?: JSX.Element[] | JSX.Element
|
|
||||||
}) {
|
|
||||||
const [snackbar, setSnackbar] = useState('')
|
|
||||||
const [timeoutId, setTimeoutId] = useState(0)
|
|
||||||
const dark = useDark()
|
|
||||||
|
|
||||||
const toast = (value: string, timeout: number) => {
|
|
||||||
setSnackbar(value)
|
|
||||||
clearTimeout(timeoutId)
|
|
||||||
const id = setTimeout(() => setSnackbar(''), timeout)
|
|
||||||
setTimeoutId(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<SnackbarContext.Provider value={{toast}}>
|
|
||||||
{children}
|
|
||||||
</SnackbarContext.Provider>
|
|
||||||
<Snackbar
|
|
||||||
onDismiss={() => setSnackbar('')}
|
|
||||||
visible={!!snackbar}
|
|
||||||
action={{
|
|
||||||
label: 'Close',
|
|
||||||
onPress: () => setSnackbar(''),
|
|
||||||
color: dark
|
|
||||||
? CombinedDarkTheme.colors.background
|
|
||||||
: CombinedDefaultTheme.colors.background,
|
|
||||||
}}>
|
|
||||||
{snackbar}
|
|
||||||
</Snackbar>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {createDrawerNavigator} from '@react-navigation/drawer'
|
import {createDrawerNavigator} from '@react-navigation/drawer'
|
||||||
import {useMemo} from 'react'
|
import {useEffect, useMemo, useState} from 'react'
|
||||||
import {IconButton} from 'react-native-paper'
|
import {DeviceEventEmitter} from 'react-native'
|
||||||
|
import {IconButton, Snackbar, useTheme} from 'react-native-paper'
|
||||||
import BestPage from './BestPage'
|
import BestPage from './BestPage'
|
||||||
import {DrawerParamList} from './drawer-param-list'
|
import {DrawerParamList} from './drawer-param-list'
|
||||||
import HomePage from './HomePage'
|
import HomePage from './HomePage'
|
||||||
|
|
11
SetForm.tsx
11
SetForm.tsx
|
@ -4,10 +4,10 @@ import DocumentPicker from 'react-native-document-picker'
|
||||||
import {Button, Card, TouchableRipple} from 'react-native-paper'
|
import {Button, Card, TouchableRipple} from 'react-native-paper'
|
||||||
import ConfirmDialog from './ConfirmDialog'
|
import ConfirmDialog from './ConfirmDialog'
|
||||||
import {MARGIN} from './constants'
|
import {MARGIN} from './constants'
|
||||||
import {setRepo} from './db'
|
import {getNow, setRepo} from './db'
|
||||||
import GymSet from './gym-set'
|
import GymSet from './gym-set'
|
||||||
import MassiveInput from './MassiveInput'
|
import MassiveInput from './MassiveInput'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
import {toast} from './toast'
|
||||||
import {useSettings} from './use-settings'
|
import {useSettings} from './use-settings'
|
||||||
|
|
||||||
export default function SetForm({
|
export default function SetForm({
|
||||||
|
@ -28,7 +28,6 @@ export default function SetForm({
|
||||||
end: set.reps.toString().length,
|
end: set.reps.toString().length,
|
||||||
})
|
})
|
||||||
const [removeImage, setRemoveImage] = useState(false)
|
const [removeImage, setRemoveImage] = useState(false)
|
||||||
const {toast} = useSnackbar()
|
|
||||||
const {settings} = useSettings()
|
const {settings} = useSettings()
|
||||||
const weightRef = useRef<TextInput>(null)
|
const weightRef = useRef<TextInput>(null)
|
||||||
const repsRef = useRef<TextInput>(null)
|
const repsRef = useRef<TextInput>(null)
|
||||||
|
@ -42,8 +41,10 @@ export default function SetForm({
|
||||||
image = await setRepo.findOne({where: {name}}).then(s => s?.image)
|
image = await setRepo.findOne({where: {name}}).then(s => s?.image)
|
||||||
|
|
||||||
console.log(`${SetForm.name}.handleSubmit:`, {image})
|
console.log(`${SetForm.name}.handleSubmit:`, {image})
|
||||||
|
const [{now}] = await getNow()
|
||||||
save({
|
save({
|
||||||
name,
|
name,
|
||||||
|
created: now,
|
||||||
reps: Number(reps),
|
reps: Number(reps),
|
||||||
weight: Number(weight),
|
weight: Number(weight),
|
||||||
id: set.id,
|
id: set.id,
|
||||||
|
@ -59,13 +60,13 @@ export default function SetForm({
|
||||||
const handleName = (value: string) => {
|
const handleName = (value: string) => {
|
||||||
setName(value.replace(/,|'/g, ''))
|
setName(value.replace(/,|'/g, ''))
|
||||||
if (value.match(/,|'/))
|
if (value.match(/,|'/))
|
||||||
toast('Commas and single quotes would break CSV exports', 6000)
|
toast('Commas and single quotes would break CSV exports')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUnit = (value: string) => {
|
const handleUnit = (value: string) => {
|
||||||
setUnit(value.replace(/,|'/g, ''))
|
setUnit(value.replace(/,|'/g, ''))
|
||||||
if (value.match(/,|'/))
|
if (value.match(/,|'/))
|
||||||
toast('Commas and single quotes would break CSV exports', 6000)
|
toast('Commas and single quotes would break CSV exports')
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeImage = useCallback(async () => {
|
const changeImage = useCallback(async () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {Picker} from '@react-native-picker/picker'
|
import {Picker} from '@react-native-picker/picker'
|
||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
import {useCallback, useEffect, useMemo, useState} from 'react'
|
import {useCallback, useEffect, useMemo, useState} from 'react'
|
||||||
import {NativeModules, ScrollView} from 'react-native'
|
import {DeviceEventEmitter, NativeModules, ScrollView} from 'react-native'
|
||||||
import DocumentPicker from 'react-native-document-picker'
|
import DocumentPicker from 'react-native-document-picker'
|
||||||
import {Button} from 'react-native-paper'
|
import {Button} from 'react-native-paper'
|
||||||
import {darkColors, lightColors} from './colors'
|
import {darkColors, lightColors} from './colors'
|
||||||
|
@ -10,10 +10,10 @@ import {MARGIN} from './constants'
|
||||||
import {settingsRepo} from './db'
|
import {settingsRepo} from './db'
|
||||||
import DrawerHeader from './DrawerHeader'
|
import DrawerHeader from './DrawerHeader'
|
||||||
import Input from './input'
|
import Input from './input'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
|
||||||
import Page from './Page'
|
import Page from './Page'
|
||||||
import Settings from './settings'
|
import Settings from './settings'
|
||||||
import Switch from './Switch'
|
import Switch from './Switch'
|
||||||
|
import {toast} from './toast'
|
||||||
import {useSettings} from './use-settings'
|
import {useSettings} from './use-settings'
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
|
@ -21,7 +21,6 @@ export default function SettingsPage() {
|
||||||
const [ignoring, setIgnoring] = useState(false)
|
const [ignoring, setIgnoring] = useState(false)
|
||||||
const [term, setTerm] = useState('')
|
const [term, setTerm] = useState('')
|
||||||
const {settings, setSettings} = useSettings()
|
const {settings, setSettings} = useSettings()
|
||||||
const {toast} = useSnackbar()
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log(`${SettingsPage.name}.useEffect:`, {settings})
|
console.log(`${SettingsPage.name}.useEffect:`, {settings})
|
||||||
|
@ -43,21 +42,25 @@ export default function SettingsPage() {
|
||||||
|
|
||||||
const changeAlarmEnabled = useCallback(
|
const changeAlarmEnabled = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
if (enabled) toast('Timers will now run after each set.', 4000)
|
if (enabled)
|
||||||
else toast('Stopped timers running after each set.', 4000)
|
DeviceEventEmitter.emit('toast', {
|
||||||
|
value: 'Timers will now run after each set',
|
||||||
|
timeout: 4000,
|
||||||
|
})
|
||||||
|
else toast('Stopped timers running after each set.')
|
||||||
if (enabled && !ignoring) setBattery(true)
|
if (enabled && !ignoring) setBattery(true)
|
||||||
update(enabled, 'alarm')
|
update(enabled, 'alarm')
|
||||||
},
|
},
|
||||||
[setBattery, ignoring, toast, update],
|
[setBattery, ignoring, update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeVibrate = useCallback(
|
const changeVibrate = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
if (enabled) toast('When a timer completes, vibrate your phone.', 4000)
|
if (enabled) toast('When a timer completes, vibrate your phone.')
|
||||||
else toast('Stop vibrating at the end of timers.', 4000)
|
else toast('Stop vibrating at the end of timers.')
|
||||||
update(enabled, 'vibrate')
|
update(enabled, 'vibrate')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeSound = useCallback(async () => {
|
const changeSound = useCallback(async () => {
|
||||||
|
@ -68,70 +71,70 @@ export default function SettingsPage() {
|
||||||
if (!fileCopyUri) return
|
if (!fileCopyUri) return
|
||||||
settingsRepo.update({}, {sound: fileCopyUri})
|
settingsRepo.update({}, {sound: fileCopyUri})
|
||||||
setSettings({...settings, sound: fileCopyUri})
|
setSettings({...settings, sound: fileCopyUri})
|
||||||
toast('This song will now play after rest timers complete.', 4000)
|
toast('This song will now play after rest timers complete.')
|
||||||
}, [toast, setSettings, settings])
|
}, [setSettings, settings])
|
||||||
|
|
||||||
const changeNotify = useCallback(
|
const changeNotify = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'notify')
|
update(enabled, 'notify')
|
||||||
if (enabled) toast('Show when a set is a new record.', 4000)
|
if (enabled) toast('Show when a set is a new record.')
|
||||||
else toast('Stopped showing notifications for new records.', 4000)
|
else toast('Stopped showing notifications for new records.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeImages = useCallback(
|
const changeImages = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'images')
|
update(enabled, 'images')
|
||||||
if (enabled) toast('Show images for sets.', 4000)
|
if (enabled) toast('Show images for sets.')
|
||||||
else toast('Stopped showing images for sets.', 4000)
|
else toast('Stopped showing images for sets.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeUnit = useCallback(
|
const changeUnit = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'showUnit')
|
update(enabled, 'showUnit')
|
||||||
if (enabled) toast('Show option to select unit for sets.', 4000)
|
if (enabled) toast('Show option to select unit for sets.')
|
||||||
else toast('Hid unit option for sets.', 4000)
|
else toast('Hid unit option for sets.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeSteps = useCallback(
|
const changeSteps = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'steps')
|
update(enabled, 'steps')
|
||||||
if (enabled) toast('Show steps for a workout.', 4000)
|
if (enabled) toast('Show steps for a workout.')
|
||||||
else toast('Stopped showing steps for workouts.', 4000)
|
else toast('Stopped showing steps for workouts.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeShowDate = useCallback(
|
const changeShowDate = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'showDate')
|
update(enabled, 'showDate')
|
||||||
if (enabled) toast('Show date for sets by default.', 4000)
|
if (enabled) toast('Show date for sets by default.')
|
||||||
else toast('Stopped showing date for sets by default.', 4000)
|
else toast('Stopped showing date for sets by default.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeShowSets = useCallback(
|
const changeShowSets = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'showSets')
|
update(enabled, 'showSets')
|
||||||
if (enabled) toast('Show target sets for workouts.', 4000)
|
if (enabled) toast('Show target sets for workouts.')
|
||||||
else toast('Stopped showing target sets for workouts.', 4000)
|
else toast('Stopped showing target sets for workouts.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const changeNoSound = useCallback(
|
const changeNoSound = useCallback(
|
||||||
(enabled: boolean) => {
|
(enabled: boolean) => {
|
||||||
update(enabled, 'noSound')
|
update(enabled, 'noSound')
|
||||||
if (enabled) toast('Disable sound on rest timer alarms.', 4000)
|
if (enabled) toast('Disable sound on rest timer alarms.')
|
||||||
else toast('Enabled sound for rest timer alarms.', 4000)
|
else toast('Enabled sound for rest timer alarms.')
|
||||||
},
|
},
|
||||||
[toast, update],
|
[update],
|
||||||
)
|
)
|
||||||
|
|
||||||
const switches: Input<boolean>[] = [
|
const switches: Input<boolean>[] = [
|
||||||
|
@ -183,10 +186,13 @@ export default function SettingsPage() {
|
||||||
)
|
)
|
||||||
}, [term, settings.color, changeTheme, settings.theme])
|
}, [term, settings.color, changeTheme, settings.theme])
|
||||||
|
|
||||||
const changeColor = useCallback((value: string) => {
|
const changeColor = useCallback(
|
||||||
setSettings({...settings, color: value})
|
(value: string) => {
|
||||||
settingsRepo.update({}, {color: value})
|
setSettings({...settings, color: value})
|
||||||
}, [])
|
settingsRepo.update({}, {color: value})
|
||||||
|
},
|
||||||
|
[setSettings, settings],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -10,11 +10,11 @@ import {AppDataSource} from './data-source'
|
||||||
import {getNow, setRepo} from './db'
|
import {getNow, setRepo} from './db'
|
||||||
import GymSet from './gym-set'
|
import GymSet from './gym-set'
|
||||||
import MassiveInput from './MassiveInput'
|
import MassiveInput from './MassiveInput'
|
||||||
import {useSnackbar} from './MassiveSnack'
|
|
||||||
import {PlanPageParams} from './plan-page-params'
|
import {PlanPageParams} from './plan-page-params'
|
||||||
import SetForm from './SetForm'
|
import SetForm from './SetForm'
|
||||||
import StackHeader from './StackHeader'
|
import StackHeader from './StackHeader'
|
||||||
import StartPlanItem from './StartPlanItem'
|
import StartPlanItem from './StartPlanItem'
|
||||||
|
import {toast} from './toast'
|
||||||
import {useSettings} from './use-settings'
|
import {useSettings} from './use-settings'
|
||||||
|
|
||||||
export default function StartPlan() {
|
export default function StartPlan() {
|
||||||
|
@ -23,7 +23,6 @@ export default function StartPlan() {
|
||||||
const [reps, setReps] = useState('')
|
const [reps, setReps] = useState('')
|
||||||
const [weight, setWeight] = useState('')
|
const [weight, setWeight] = useState('')
|
||||||
const [unit, setUnit] = useState<string>('kg')
|
const [unit, setUnit] = useState<string>('kg')
|
||||||
const {toast} = useSnackbar()
|
|
||||||
const [minutes, setMinutes] = useState(3)
|
const [minutes, setMinutes] = useState(3)
|
||||||
const [seconds, setSeconds] = useState(30)
|
const [seconds, setSeconds] = useState(30)
|
||||||
const [best, setBest] = useState<GymSet>()
|
const [best, setBest] = useState<GymSet>()
|
||||||
|
@ -109,9 +108,9 @@ export default function StartPlan() {
|
||||||
settings.notify &&
|
settings.notify &&
|
||||||
(+weight > best.weight || (+reps > best.reps && +weight === best.weight))
|
(+weight > best.weight || (+reps > best.reps && +weight === best.weight))
|
||||||
)
|
)
|
||||||
toast("Great work King! That's a new record.", 5000)
|
toast("Great work King! That's a new record.")
|
||||||
else if (settings.alarm) toast('Resting...', 3000)
|
else if (settings.alarm) toast('Resting...')
|
||||||
else toast('Added set', 3000)
|
else toast('Added set')
|
||||||
if (!settings.alarm) return
|
if (!settings.alarm) return
|
||||||
const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000
|
const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000
|
||||||
const {vibrate, sound, noSound} = settings
|
const {vibrate, sound, noSound} = settings
|
||||||
|
@ -119,14 +118,11 @@ export default function StartPlan() {
|
||||||
NativeModules.AlarmModule.timer(...args)
|
NativeModules.AlarmModule.timer(...args)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleUnit = useCallback(
|
const handleUnit = useCallback((value: string) => {
|
||||||
(value: string) => {
|
setUnit(value.replace(/,|'/g, ''))
|
||||||
setUnit(value.replace(/,|'/g, ''))
|
if (value.match(/,|'/))
|
||||||
if (value.match(/,|'/))
|
toast('Commas and single quotes would break CSV exports')
|
||||||
toast('Commas and single quotes would break CSV exports', 6000)
|
}, [])
|
||||||
},
|
|
||||||
[toast],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user