Change toasts based on context of settings

The messages should explain what you have now changed
rather than the setting itself.
This commit is contained in:
Brandon Presley 2022-09-11 15:35:20 +12:00
parent 1a83b20069
commit 567bf182b4
5 changed files with 67 additions and 39 deletions

30
App.tsx
View File

@ -4,15 +4,15 @@ import {
DefaultTheme as NavigationDefaultTheme, DefaultTheme as NavigationDefaultTheme,
NavigationContainer, NavigationContainer,
} from '@react-navigation/native'; } from '@react-navigation/native';
import React, {useState} from 'react'; import React from 'react';
import {useColorScheme} from 'react-native'; import {useColorScheme} from 'react-native';
import { import {
DarkTheme as PaperDarkTheme, DarkTheme as PaperDarkTheme,
DefaultTheme as PaperDefaultTheme, DefaultTheme as PaperDefaultTheme,
Provider, Provider,
Snackbar,
} from 'react-native-paper'; } from 'react-native-paper';
import Ionicon from 'react-native-vector-icons/Ionicons'; import Ionicon from 'react-native-vector-icons/Ionicons';
import MassiveSnack from './MassiveSnack';
import Routes from './Routes'; import Routes from './Routes';
export const Drawer = createDrawerNavigator<DrawerParamList>(); export const Drawer = createDrawerNavigator<DrawerParamList>();
@ -25,10 +25,6 @@ export type DrawerParamList = {
Loading: {}; Loading: {};
}; };
export const SnackbarContext = React.createContext<{
toast: (value: string, timeout: number) => void;
}>({toast: () => null});
export const CombinedDefaultTheme = { export const CombinedDefaultTheme = {
...PaperDefaultTheme, ...PaperDefaultTheme,
...NavigationDefaultTheme, ...NavigationDefaultTheme,
@ -49,36 +45,18 @@ export const CombinedDarkTheme = {
}; };
const App = () => { const App = () => {
const [snackbar, setSnackbar] = useState('');
const dark = useColorScheme() === 'dark'; const dark = useColorScheme() === 'dark';
const toast = (value: string, timeout: number) => {
setSnackbar(value);
setTimeout(() => setSnackbar(''), timeout);
};
return ( return (
<Provider <Provider
theme={dark ? CombinedDarkTheme : CombinedDefaultTheme} theme={dark ? CombinedDarkTheme : CombinedDefaultTheme}
settings={{icon: props => <Ionicon {...props} />}}> settings={{icon: props => <Ionicon {...props} />}}>
<NavigationContainer <NavigationContainer
theme={dark ? CombinedDarkTheme : CombinedDefaultTheme}> theme={dark ? CombinedDarkTheme : CombinedDefaultTheme}>
<SnackbarContext.Provider value={{toast}}> <MassiveSnack>
<Routes /> <Routes />
</SnackbarContext.Provider> </MassiveSnack>
</NavigationContainer> </NavigationContainer>
<Snackbar
onDismiss={() => setSnackbar('')}
visible={!!snackbar}
action={{
label: 'Close',
onPress: () => setSnackbar(''),
color: dark
? CombinedDarkTheme.colors.background
: CombinedDefaultTheme.colors.primary,
}}>
{snackbar}
</Snackbar>
</Provider> </Provider>
); );
}; };

View File

@ -3,8 +3,9 @@ import React, {useCallback, useContext, useState} from 'react';
import DocumentPicker from 'react-native-document-picker'; import DocumentPicker from 'react-native-document-picker';
import {FileSystem} from 'react-native-file-access'; import {FileSystem} from 'react-native-file-access';
import {Divider, IconButton, Menu} from 'react-native-paper'; import {Divider, IconButton, Menu} from 'react-native-paper';
import {DrawerParamList, SnackbarContext} from './App'; import {DrawerParamList} from './App';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import {SnackbarContext} from './MassiveSnack';
import {Plan} from './plan'; import {Plan} from './plan';
import {addPlans, deletePlans, getAllPlans} from './plan.service'; import {addPlans, deletePlans, getAllPlans} from './plan.service';
import {addSets, deleteSets, getAllSets} from './set.service'; import {addSets, deleteSets, getAllSets} from './set.service';

View File

@ -7,8 +7,8 @@ import {
import React, {useCallback, useContext} from 'react'; import React, {useCallback, useContext} from 'react';
import {NativeModules, View} from 'react-native'; import {NativeModules, View} from 'react-native';
import {IconButton} from 'react-native-paper'; import {IconButton} from 'react-native-paper';
import {SnackbarContext} from './App';
import {HomePageParams} from './HomePage'; import {HomePageParams} from './HomePage';
import {SnackbarContext} from './MassiveSnack';
import Set from './set'; import Set from './set';
import {addSet, setSet} from './set.service'; import {addSet, setSet} from './set.service';
import SetForm from './SetForm'; import SetForm from './SetForm';

42
MassiveSnack.tsx Normal file
View File

@ -0,0 +1,42 @@
import React, {useState} from 'react';
import {useColorScheme} from 'react-native';
import {Snackbar} from 'react-native-paper';
import {CombinedDarkTheme, CombinedDefaultTheme} from './App';
export const SnackbarContext = React.createContext<{
toast: (value: string, timeout: number) => void;
}>({toast: () => null});
const MassiveSnack = ({children}: {children: JSX.Element[] | JSX.Element}) => {
const [snackbar, setSnackbar] = useState('');
const dark = useColorScheme() === 'dark';
let timeoutId: number;
const toast = (value: string, timeout: number) => {
setSnackbar(value);
clearTimeout(timeoutId);
timeoutId = setTimeout(() => setSnackbar(''), timeout);
};
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.primary,
}}>
{snackbar}
</Snackbar>
</>
);
};
export default MassiveSnack;

View File

@ -2,9 +2,9 @@ import React, {useCallback, useContext, useEffect, useState} from 'react';
import {NativeModules, ScrollView, StyleSheet, View} from 'react-native'; import {NativeModules, ScrollView, StyleSheet, View} from 'react-native';
import DocumentPicker from 'react-native-document-picker'; import DocumentPicker from 'react-native-document-picker';
import {Button, Searchbar, Text} from 'react-native-paper'; import {Button, Searchbar, Text} from 'react-native-paper';
import {SnackbarContext} from './App';
import ConfirmDialog from './ConfirmDialog'; import ConfirmDialog from './ConfirmDialog';
import MassiveInput from './MassiveInput'; import MassiveInput from './MassiveInput';
import {SnackbarContext} from './MassiveSnack';
import MassiveSwitch from './MassiveSwitch'; import MassiveSwitch from './MassiveSwitch';
import {getSettings, setSettings} from './settings.service'; import {getSettings, setSettings} from './settings.service';
@ -65,7 +65,8 @@ export default function SettingsPage() {
const changeAlarmEnabled = useCallback( const changeAlarmEnabled = useCallback(
(enabled: boolean) => { (enabled: boolean) => {
setAlarm(enabled); setAlarm(enabled);
toast('Time your rest duration after each set.', 4000); if (enabled) toast('Timers will now run after each set.', 4000);
else toast('Stopped timers running after each set.', 4000);
if (enabled && !ignoring) setBattery(true); if (enabled && !ignoring) setBattery(true);
}, },
[setBattery, ignoring, toast], [setBattery, ignoring, toast],
@ -74,15 +75,18 @@ export default function SettingsPage() {
const changePredict = useCallback( const changePredict = useCallback(
(enabled: boolean) => { (enabled: boolean) => {
setPredict(enabled); setPredict(enabled);
toast('Predict your next set based on todays plan.', 4000); if (enabled)
toast('Predicting your next set based on todays plan.', 4000);
else toast('New sets will always be empty.', 4000);
}, },
[setPredict, toast], [setPredict, toast],
); );
const changeVibrate = useCallback( const changeVibrate = useCallback(
(value: boolean) => { (enabled: boolean) => {
setVibrate(value); setVibrate(enabled);
toast('When a timer completes, vibrate your phone.', 4000); if (enabled) toast('When a timer completes, vibrate your phone.', 4000);
else toast('Stop vibrating at the end of timers.', 4000);
}, },
[setVibrate, toast], [setVibrate, toast],
); );
@ -92,13 +96,16 @@ export default function SettingsPage() {
type: 'audio/*', type: 'audio/*',
copyTo: 'documentDirectory', copyTo: 'documentDirectory',
}); });
if (fileCopyUri) setSound(fileCopyUri); if (!fileCopyUri) return;
}, []); setSound(fileCopyUri);
toast('This song will now play after rest timers complete.', 4000);
}, [toast]);
const changeNotify = useCallback( const changeNotify = useCallback(
(value: boolean) => { (enabled: boolean) => {
setNotify(value); setNotify(enabled);
toast('If a set is a new record, show a notification.', 4000); if (enabled) toast('Show when a set is a new record.', 4000);
else toast('Stopped showing notifications for new records.', 4000);
}, },
[toast], [toast],
); );