Prevent race condition with database migrations
This commit is contained in:
parent
a1cd4e8080
commit
756a2089e9
41
App.tsx
41
App.tsx
|
@ -4,7 +4,7 @@ import {
|
||||||
DefaultTheme as NavigationDefaultTheme,
|
DefaultTheme as NavigationDefaultTheme,
|
||||||
NavigationContainer,
|
NavigationContainer,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import React, {useEffect, useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import {useColorScheme} from 'react-native';
|
import {useColorScheme} from 'react-native';
|
||||||
import {
|
import {
|
||||||
DarkTheme as PaperDarkTheme,
|
DarkTheme as PaperDarkTheme,
|
||||||
|
@ -12,19 +12,7 @@ import {
|
||||||
Provider,
|
Provider,
|
||||||
Snackbar,
|
Snackbar,
|
||||||
} from 'react-native-paper';
|
} from 'react-native-paper';
|
||||||
import {SQLiteDatabase} from 'react-native-sqlite-storage';
|
|
||||||
import Ionicon from 'react-native-vector-icons/Ionicons';
|
import Ionicon from 'react-native-vector-icons/Ionicons';
|
||||||
import {
|
|
||||||
addHidden,
|
|
||||||
addImage,
|
|
||||||
addNotify,
|
|
||||||
addSound,
|
|
||||||
createPlans,
|
|
||||||
createSets,
|
|
||||||
createSettings,
|
|
||||||
createWorkouts,
|
|
||||||
getDb,
|
|
||||||
} from './db';
|
|
||||||
import Routes from './Routes';
|
import Routes from './Routes';
|
||||||
|
|
||||||
export const Drawer = createDrawerNavigator<DrawerParamList>();
|
export const Drawer = createDrawerNavigator<DrawerParamList>();
|
||||||
|
@ -34,9 +22,9 @@ export type DrawerParamList = {
|
||||||
Best: {};
|
Best: {};
|
||||||
Plans: {};
|
Plans: {};
|
||||||
Workouts: {};
|
Workouts: {};
|
||||||
|
Loading: {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DatabaseContext = React.createContext<SQLiteDatabase>({} as any);
|
|
||||||
export const SnackbarContext = React.createContext<{
|
export const SnackbarContext = React.createContext<{
|
||||||
toast: (value: string, timeout: number) => void;
|
toast: (value: string, timeout: number) => void;
|
||||||
}>({toast: () => null});
|
}>({toast: () => null});
|
||||||
|
@ -61,32 +49,9 @@ export const CombinedDarkTheme = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [db, setDb] = useState<SQLiteDatabase | null>(null);
|
|
||||||
const [snackbar, setSnackbar] = useState('');
|
const [snackbar, setSnackbar] = useState('');
|
||||||
const dark = useColorScheme() === 'dark';
|
const dark = useColorScheme() === 'dark';
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const init = async () => {
|
|
||||||
const _db = await getDb();
|
|
||||||
setDb(_db);
|
|
||||||
await _db.executeSql(createPlans);
|
|
||||||
await _db.executeSql(createSets);
|
|
||||||
await _db.executeSql(createSettings);
|
|
||||||
await _db.executeSql(addSound).catch(() => null);
|
|
||||||
await _db.executeSql(createWorkouts);
|
|
||||||
await _db.executeSql(addHidden).catch(() => null);
|
|
||||||
await _db.executeSql(addNotify).catch(() => null);
|
|
||||||
await _db.executeSql(addImage).catch(() => null);
|
|
||||||
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();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const toast = (value: string, timeout: number) => {
|
const toast = (value: string, timeout: number) => {
|
||||||
setSnackbar(value);
|
setSnackbar(value);
|
||||||
setTimeout(() => setSnackbar(''), timeout);
|
setTimeout(() => setSnackbar(''), timeout);
|
||||||
|
@ -99,7 +64,7 @@ const App = () => {
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
theme={dark ? CombinedDarkTheme : CombinedDefaultTheme}>
|
theme={dark ? CombinedDarkTheme : CombinedDefaultTheme}>
|
||||||
<SnackbarContext.Provider value={{toast}}>
|
<SnackbarContext.Provider value={{toast}}>
|
||||||
<Routes db={db} />
|
<Routes />
|
||||||
</SnackbarContext.Provider>
|
</SnackbarContext.Provider>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
<Snackbar
|
<Snackbar
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {FlatList, StyleSheet, View} from 'react-native';
|
import {FlatList, StyleSheet, View} from 'react-native';
|
||||||
import {List, Searchbar} from 'react-native-paper';
|
import {List, Searchbar} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import Best from './best';
|
import Best from './best';
|
||||||
import {BestPageParams} from './BestPage';
|
import {BestPageParams} from './BestPage';
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,10 @@ 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 {DatabaseContext, DrawerParamList, SnackbarContext} from './App';
|
import {DrawerParamList, SnackbarContext} from './App';
|
||||||
import ConfirmDialog from './ConfirmDialog';
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
import {Plan} from './plan';
|
import {Plan} from './plan';
|
||||||
|
import {DatabaseContext} from './Routes';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
import {write} from './write';
|
import {write} from './write';
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {ScrollView, StyleSheet, Text, View} from 'react-native';
|
import {ScrollView, StyleSheet, Text, View} from 'react-native';
|
||||||
import {Button, IconButton} from 'react-native-paper';
|
import {Button, IconButton} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import MassiveSwitch from './MassiveSwitch';
|
import MassiveSwitch from './MassiveSwitch';
|
||||||
import {PlanPageParams} from './PlanPage';
|
import {PlanPageParams} from './PlanPage';
|
||||||
import {DAYS} from './time';
|
import {DAYS} from './time';
|
||||||
|
|
|
@ -7,8 +7,9 @@ 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 {DatabaseContext, SnackbarContext} from './App';
|
import {SnackbarContext} from './App';
|
||||||
import {HomePageParams} from './HomePage';
|
import {HomePageParams} from './HomePage';
|
||||||
|
import {DatabaseContext} from './Routes';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
import SetForm from './SetForm';
|
import SetForm from './SetForm';
|
||||||
import Settings from './settings';
|
import Settings from './settings';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {Image, ScrollView, View} from 'react-native';
|
||||||
import DocumentPicker from 'react-native-document-picker';
|
import DocumentPicker from 'react-native-document-picker';
|
||||||
import {Button, IconButton} from 'react-native-paper';
|
import {Button, IconButton} from 'react-native-paper';
|
||||||
import {set} from 'react-native-reanimated';
|
import {set} from 'react-native-reanimated';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import MassiveInput from './MassiveInput';
|
import MassiveInput from './MassiveInput';
|
||||||
import {WorkoutsPageParams} from './WorkoutsPage';
|
import {WorkoutsPageParams} from './WorkoutsPage';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import React, {useCallback, useContext, useState} from 'react';
|
import React, {useCallback, useContext, useState} from 'react';
|
||||||
import {GestureResponderEvent} from 'react-native';
|
import {GestureResponderEvent} from 'react-native';
|
||||||
import {List, Menu} from 'react-native-paper';
|
import {List, Menu} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import {Plan} from './plan';
|
import {Plan} from './plan';
|
||||||
import {PlanPageParams} from './PlanPage';
|
import {PlanPageParams} from './PlanPage';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {FlatList, StyleSheet, View} from 'react-native';
|
import {FlatList, StyleSheet, View} from 'react-native';
|
||||||
import {List, Searchbar} from 'react-native-paper';
|
import {List, Searchbar} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import DrawerMenu from './DrawerMenu';
|
import DrawerMenu from './DrawerMenu';
|
||||||
import MassiveFab from './MassiveFab';
|
import MassiveFab from './MassiveFab';
|
||||||
import {Plan} from './plan';
|
import {Plan} from './plan';
|
||||||
|
|
45
Routes.tsx
45
Routes.tsx
|
@ -1,9 +1,20 @@
|
||||||
import React from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {useColorScheme} from 'react-native';
|
import {useColorScheme} from 'react-native';
|
||||||
import {IconButton} from 'react-native-paper';
|
import {IconButton} from 'react-native-paper';
|
||||||
import {SQLiteDatabase} from 'react-native-sqlite-storage';
|
import {SQLiteDatabase} from 'react-native-sqlite-storage';
|
||||||
import {DatabaseContext, Drawer, DrawerParamList} from './App';
|
import {Drawer, DrawerParamList} from './App';
|
||||||
import BestPage from './BestPage';
|
import BestPage from './BestPage';
|
||||||
|
import {
|
||||||
|
addHidden,
|
||||||
|
addImage,
|
||||||
|
addNotify,
|
||||||
|
addSound,
|
||||||
|
createPlans,
|
||||||
|
createSets,
|
||||||
|
createSettings,
|
||||||
|
createWorkouts,
|
||||||
|
getDb,
|
||||||
|
} from './db';
|
||||||
import HomePage from './HomePage';
|
import HomePage from './HomePage';
|
||||||
import PlanPage from './PlanPage';
|
import PlanPage from './PlanPage';
|
||||||
import SettingsPage from './SettingsPage';
|
import SettingsPage from './SettingsPage';
|
||||||
|
@ -15,9 +26,37 @@ interface Route {
|
||||||
icon: string;
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Routes({db}: {db: SQLiteDatabase | null}) {
|
export const DatabaseContext = React.createContext<SQLiteDatabase>(null as any);
|
||||||
|
|
||||||
|
export default function Routes() {
|
||||||
|
const [db, setDb] = useState<SQLiteDatabase | null>(null);
|
||||||
const dark = useColorScheme() === 'dark';
|
const dark = useColorScheme() === 'dark';
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const init = async () => {
|
||||||
|
const _db = await getDb();
|
||||||
|
try {
|
||||||
|
await _db.executeSql(createPlans);
|
||||||
|
await _db.executeSql(createSets);
|
||||||
|
await _db.executeSql(createSettings);
|
||||||
|
await _db.executeSql(createWorkouts);
|
||||||
|
await _db.executeSql(addSound).catch(() => null);
|
||||||
|
await _db.executeSql(addHidden).catch(() => null);
|
||||||
|
await _db.executeSql(addNotify).catch(() => null);
|
||||||
|
await _db.executeSql(addImage).catch(() => null);
|
||||||
|
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);
|
||||||
|
`);
|
||||||
|
} finally {
|
||||||
|
setDb(_db);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (!db) return null;
|
if (!db) return null;
|
||||||
|
|
||||||
const routes: Route[] = [
|
const routes: Route[] = [
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, {useContext, useEffect, useRef, useState} from 'react';
|
import React, {useContext, useEffect, useRef, useState} from 'react';
|
||||||
import {ScrollView, Text} from 'react-native';
|
import {ScrollView, Text} from 'react-native';
|
||||||
import {Button} from 'react-native-paper';
|
import {Button} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import MassiveInput from './MassiveInput';
|
import MassiveInput from './MassiveInput';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import React, {useCallback, useContext, useState} from 'react';
|
import React, {useCallback, useContext, useState} from 'react';
|
||||||
import {GestureResponderEvent, Image, Text} from 'react-native';
|
import {GestureResponderEvent, Image, Text} from 'react-native';
|
||||||
import {Divider, List, Menu} from 'react-native-paper';
|
import {Divider, List, Menu} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import {HomePageParams} from './HomePage';
|
import {HomePageParams} from './HomePage';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {FlatList, StyleSheet, View} from 'react-native';
|
import {FlatList, StyleSheet, View} from 'react-native';
|
||||||
import {List, Searchbar} from 'react-native-paper';
|
import {List, Searchbar} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import DrawerMenu from './DrawerMenu';
|
import DrawerMenu from './DrawerMenu';
|
||||||
import {HomePageParams} from './HomePage';
|
import {HomePageParams} from './HomePage';
|
||||||
import MassiveFab from './MassiveFab';
|
import MassiveFab from './MassiveFab';
|
||||||
|
|
|
@ -8,10 +8,11 @@ import React, {
|
||||||
import {NativeModules, ScrollView, StyleSheet, Text, View} from 'react-native';
|
import {NativeModules, ScrollView, StyleSheet, Text, View} from 'react-native';
|
||||||
import DocumentPicker from 'react-native-document-picker';
|
import DocumentPicker from 'react-native-document-picker';
|
||||||
import {Button, Searchbar} from 'react-native-paper';
|
import {Button, Searchbar} from 'react-native-paper';
|
||||||
import {DatabaseContext, SnackbarContext} from './App';
|
import {SnackbarContext} from './App';
|
||||||
import ConfirmDialog from './ConfirmDialog';
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
import MassiveInput from './MassiveInput';
|
import MassiveInput from './MassiveInput';
|
||||||
import MassiveSwitch from './MassiveSwitch';
|
import MassiveSwitch from './MassiveSwitch';
|
||||||
|
import {DatabaseContext} from './Routes';
|
||||||
import Settings from './settings';
|
import Settings from './settings';
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
|
|
|
@ -18,8 +18,9 @@ import {IconButton} from 'react-native-paper';
|
||||||
import Share from 'react-native-share';
|
import Share from 'react-native-share';
|
||||||
import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts';
|
import {Grid, LineChart, XAxis, YAxis} from 'react-native-svg-charts';
|
||||||
import ViewShot from 'react-native-view-shot';
|
import ViewShot from 'react-native-view-shot';
|
||||||
import {CombinedDarkTheme, CombinedDefaultTheme, DatabaseContext} from './App';
|
import {CombinedDarkTheme, CombinedDefaultTheme} from './App';
|
||||||
import {BestPageParams} from './BestPage';
|
import {BestPageParams} from './BestPage';
|
||||||
|
import {DatabaseContext} from './Routes';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
import {formatMonth} from './time';
|
import {formatMonth} from './time';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {GestureResponderEvent, Image, Text} from 'react-native';
|
import {GestureResponderEvent, Image, Text} from 'react-native';
|
||||||
import {List, Menu} from 'react-native-paper';
|
import {List, Menu} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import ConfirmDialog from './ConfirmDialog';
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
import Workout from './workout';
|
import Workout from './workout';
|
||||||
import {WorkoutsPageParams} from './WorkoutsPage';
|
import {WorkoutsPageParams} from './WorkoutsPage';
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
import React, {useCallback, useContext, useEffect, useState} from 'react';
|
||||||
import {FlatList, StyleSheet, View} from 'react-native';
|
import {FlatList, StyleSheet, View} from 'react-native';
|
||||||
import {List, Searchbar} from 'react-native-paper';
|
import {List, Searchbar} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './Routes';
|
||||||
import MassiveFab from './MassiveFab';
|
import MassiveFab from './MassiveFab';
|
||||||
import SetList from './SetList';
|
import SetList from './SetList';
|
||||||
import Workout from './workout';
|
import Workout from './workout';
|
||||||
|
|
Loading…
Reference in New Issue
Block a user