diff --git a/App.tsx b/App.tsx index 8846c2d0..024714cf 100644 --- a/App.tsx +++ b/App.tsx @@ -1,4 +1,3 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; import {createDrawerNavigator} from '@react-navigation/drawer'; import { DarkTheme as NavigationDarkTheme, @@ -14,7 +13,7 @@ import { } from 'react-native-paper'; import {SQLiteDatabase} from 'react-native-sqlite-storage'; import Ionicon from 'react-native-vector-icons/Ionicons'; -import {createPlans, createSets, getDb} from './db'; +import {createPlans, createSets, createSettings, getDb} from './db'; import Routes from './Routes'; export const Drawer = createDrawerNavigator(); @@ -27,8 +26,6 @@ export type DrawerParamList = { export const DatabaseContext = React.createContext({} as any); -const {getItem, setItem} = AsyncStorage; - const CombinedDefaultTheme = { ...PaperDefaultTheme, ...NavigationDefaultTheme, @@ -52,21 +49,17 @@ const App = () => { useEffect(() => { const init = async () => { - const gotDb = await getDb(); - await gotDb.executeSql(createPlans); - await gotDb.executeSql(createSets); - setDb(gotDb); - const minutes = await getItem('minutes'); - if (minutes === null) await setItem('minutes', '3'); - const seconds = await getItem('seconds'); - if (seconds === null) await setItem('seconds', '30'); - const alarmEnabled = await getItem('alarmEnabled'); - if (alarmEnabled === null) await setItem('alarmEnabled', 'false'); - const vibrate = await getItem('vibrate'); - if (vibrate === null) await setItem('vibrate', 'true'); - if (!(await getItem('predictiveSets'))) - await setItem('predictiveSets', 'true'); - if (!(await getItem('maxSets'))) await setItem('maxSets', '3'); + const _db = await getDb(); + await _db.executeSql(createPlans); + await _db.executeSql(createSets); + await _db.executeSql(createSettings); + setDb(_db); + const [result] = await _db.executeSql(`SELECT * FROM settings LIMIT 1`); + if (result.rows.length === 0) + return _db.executeSql(` + INSERT INTO settings(minutes,seconds,alarm,vibrate,predict,sets) + VALUES(3,30,false,true,true,3); + `); }; init(); }, []); diff --git a/EditSet.tsx b/EditSet.tsx index a04f1c4f..54a05681 100644 --- a/EditSet.tsx +++ b/EditSet.tsx @@ -1,4 +1,3 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; import { RouteProp, useFocusEffect, @@ -12,6 +11,7 @@ import {DatabaseContext} from './App'; import {HomePageParams} from './HomePage'; import Set from './set'; import SetForm from './SetForm'; +import Settings from './settings'; export default function EditSet() { const {params} = useRoute>(); @@ -30,14 +30,12 @@ export default function EditSet() { ); const startTimer = useCallback(async () => { - const enabled = await AsyncStorage.getItem('alarmEnabled'); - if (enabled !== 'true') return; - const minutes = await AsyncStorage.getItem('minutes'); - const seconds = await AsyncStorage.getItem('seconds'); - const milliseconds = Number(minutes) * 60 * 1000 + Number(seconds) * 1000; - const vibrate = (await AsyncStorage.getItem('vibrate')) === 'true'; - NativeModules.AlarmModule.timer(milliseconds, vibrate); - }, []); + const [result] = await db.executeSql(`SELECT * FROM settings LIMIT 1`); + const settings: Settings = result.rows.item(0); + if (!settings.alarm) return; + const milliseconds = settings.minutes * 60 * 1000 + settings.seconds * 1000; + NativeModules.AlarmModule.timer(milliseconds, !!settings.vibrate); + }, [db]); const update = useCallback( async (set: Set) => { diff --git a/SetList.tsx b/SetList.tsx index b1eb313d..c58c20a3 100644 --- a/SetList.tsx +++ b/SetList.tsx @@ -5,7 +5,6 @@ import { } from '@react-navigation/native'; import React, {useCallback, useContext, useEffect, useState} from 'react'; import {FlatList, StyleSheet, View} from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; import {List, Searchbar} from 'react-native-paper'; import {DatabaseContext} from './App'; import {HomePageParams} from './HomePage'; @@ -13,6 +12,7 @@ import MassiveFab from './MassiveFab'; import {Plan} from './plan'; import Set from './set'; import SetItem from './SetItem'; +import Settings from './settings'; import {DAYS} from './time'; const limit = 15; @@ -105,7 +105,9 @@ export default function SetList() { ); const predict = useCallback(async () => { - if ((await AsyncStorage.getItem('predictiveSets')) === 'false') return; + const [result] = await db.executeSql(`SELECT * FROM settings LIMIT 1`); + const settings: Settings = result.rows.item(0); + if (!settings.predict) return; const todaysPlan = await getTodaysPlan(); if (todaysPlan.length === 0) return; const todaysSets = await getTodaysSets(); @@ -115,15 +117,14 @@ export default function SetList() { const count = todaysSets.filter( s => s.name === todaysSets[0].name, ).length; - const maxSets = await AsyncStorage.getItem('maxSets'); nextWorkout = todaysSets[0].name; - if (count >= Number(maxSets)) + if (count >= Number(settings.sets)) nextWorkout = todaysWorkouts[todaysWorkouts.indexOf(todaysSets[0].name!) + 1]; } const best = await getBest(nextWorkout); setNextSet({...best}); - }, [getTodaysSets, getTodaysPlan, getBest]); + }, [getTodaysSets, getTodaysPlan, getBest, db]); useFocusEffect( useCallback(() => { diff --git a/SettingsPage.tsx b/SettingsPage.tsx index ea5c8670..e411f847 100644 --- a/SettingsPage.tsx +++ b/SettingsPage.tsx @@ -1,9 +1,8 @@ -import AsyncStorage from '@react-native-async-storage/async-storage'; import React, { ReactNode, useCallback, + useContext, useEffect, - useMemo, useState, } from 'react'; import { @@ -14,10 +13,10 @@ import { View, } from 'react-native'; import {Searchbar, TextInput} from 'react-native-paper'; +import {DatabaseContext} from './App'; import ConfirmDialog from './ConfirmDialog'; import MassiveSwitch from './MassiveSwitch'; - -const {getItem, setItem} = AsyncStorage; +import Settings from './settings'; export default function SettingsPage() { const [vibrate, setVibrate] = useState(true); @@ -29,25 +28,36 @@ export default function SettingsPage() { const [battery, setBattery] = useState(false); const [ignoring, setIgnoring] = useState(false); const [search, setSearch] = useState(''); + const db = useContext(DatabaseContext); const refresh = useCallback(async () => { - setMinutes((await getItem('minutes')) || ''); - setSeconds((await getItem('seconds')) || ''); - setAlarm((await getItem('alarmEnabled')) === 'true'); - setPredictive((await getItem('predictiveSets')) === 'true'); - setMaxSets((await getItem('maxSets')) || ''); + const [result] = await db.executeSql(`SELECT * FROM settings LIMIT 1`); + const settings: Settings = result.rows.item(0); + console.log('SettingsPage.refresh:', {settings}); + setMinutes(settings.minutes.toString()); + setSeconds(settings.seconds.toString()); + setAlarm(!!settings.alarm); + setPredictive(!!settings.predict); + setMaxSets(settings.sets.toString()); + setVibrate(!!settings.vibrate); NativeModules.AlarmModule.ignoringBattery(setIgnoring); - }, []); + }, [db]); useEffect(() => { refresh(); }, [refresh]); + useEffect(() => { + db.executeSql( + `UPDATE settings SET vibrate=?,minutes=?,sets=?,seconds=?,alarm=?,predict=?`, + [vibrate, minutes, maxSets, seconds, alarm, predictive], + ); + }, [vibrate, minutes, maxSets, seconds, alarm, predictive, db]); + const changeAlarmEnabled = useCallback( (enabled: boolean) => { setAlarm(enabled); if (enabled && !ignoring) setBattery(true); - setItem('alarmEnabled', enabled ? 'true' : 'false'); }, [setBattery, ignoring], ); @@ -55,7 +65,6 @@ export default function SettingsPage() { const changePredictive = useCallback( (enabled: boolean) => { setPredictive(enabled); - setItem('predictiveSets', enabled ? 'true' : 'false'); ToastAndroid.show( 'Predictive sets guess whats next based on todays plan.', ToastAndroid.LONG, @@ -67,7 +76,6 @@ export default function SettingsPage() { const changeVibrate = useCallback( (value: boolean) => { setVibrate(value); - setItem('vibrate', value ? 'true' : 'false'); }, [setVibrate], ); @@ -82,7 +90,6 @@ export default function SettingsPage() { keyboardType="numeric" onChangeText={value => { setMaxSets(value); - setItem('maxSets', value); }} style={styles.text} selectTextOnFocus @@ -99,7 +106,6 @@ export default function SettingsPage() { placeholder="30" onChangeText={s => { setSeconds(s); - setItem('seconds', s); }} style={styles.text} selectTextOnFocus @@ -116,7 +122,6 @@ export default function SettingsPage() { placeholder="3" onChangeText={text => { setMinutes(text); - setItem('minutes', text); }} style={styles.text} selectTextOnFocus @@ -166,7 +171,12 @@ export default function SettingsPage() { return ( - + {items .filter(item => item.name.toLowerCase().includes(search.toLowerCase())) .map(item => ( diff --git a/db.ts b/db.ts index 2a7c602e..62994c8b 100644 --- a/db.ts +++ b/db.ts @@ -21,3 +21,14 @@ export const createPlans = ` workouts TEXT NOT NULL ); `; + +export const createSettings = ` + CREATE TABLE IF NOT EXISTS settings ( + minutes INTEGER NOT NULL DEFAULT 3, + seconds INTEGER NOT NULL DEFAULT 30, + alarm BOOLEAN NOT NULL DEFAULT false, + vibrate BOOLEAN NOT NULL DEFAULT true, + predict BOOLEAN NOT NULL DEFAULT true, + sets INTEGER NOT NULL DEFAULT 3 + ); +`; diff --git a/settings.ts b/settings.ts new file mode 100644 index 00000000..c1856651 --- /dev/null +++ b/settings.ts @@ -0,0 +1,8 @@ +export default interface Settings { + minutes: number; + seconds: number; + alarm: number; + vibrate: number; + predict: number; + sets: number; +}