Creating a mechanism to store settings both in the database and in redux.

This commit is contained in:
vdv committed 2022-10-03 21:08:27 +02:00
1 parent 07edc22d31
commit c0015a7cfa
10 files changed
+272 -18

No files matched your search

+11 -5
View File
@@ -25,10 +25,9 @@ import {
} from '../../lib/background-geolocation';
import { appendTrkpt, deleteCurrent, saveCurrent } from '../../db/gpx';
import { enterAnimation, leaveAnimation } from '../../lib/animation';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { mapActions } from '../../store/map';
const MIN_TIME_BETWEEN_LOCATIONS = 15 * 1000;
import { SettingsState } from '../../store/settings';
declare global {
var $lastValidLocationTime: number;
@@ -41,6 +40,10 @@ const GpxRecord: React.FC<{}> = () => {
const [watcher_id, setWatcher_id] = useState();
const geolocationsSettingsState = useSelector(
(state: { settings: SettingsState }) => state.settings.geolocation
);
const gpxes = useFind({
selector: {
type: 'gpx',
@@ -72,7 +75,7 @@ const GpxRecord: React.FC<{}> = () => {
);
if (
location.time - globalThis.$lastValidLocationTime >
MIN_TIME_BETWEEN_LOCATIONS
geolocationsSettingsState.minTimeInterval
) {
globalThis.$lastValidLocationTime = location.time;
appendTrkpt(db, {
@@ -98,7 +101,10 @@ const GpxRecord: React.FC<{}> = () => {
const startRecording = () => {
globalThis.$lastValidLocationTime = 0;
startBackgroundGeolocation(newLocationHandler).then((result) => {
startBackgroundGeolocation(
newLocationHandler,
geolocationsSettingsState.minDistance
).then((result) => {
setWatcher_id(result);
});
setIsRecording(true);
+177
View File
@@ -0,0 +1,177 @@
import React, { Fragment, useEffect, useRef, useState } from 'react';
import { useDB } from 'react-pouchdb';
import {
IonButton,
IonButtons,
IonContent,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonModal,
IonTitle,
IonToolbar,
} from '@ionic/react';
import { options, text } from 'ionicons/icons';
import { enterAnimation, leaveAnimation } from '../../lib/animation';
import { useDispatch, useSelector } from 'react-redux';
import { settingsActions, SettingsState } from '../../store/settings';
import uri from '../../lib/ids';
import _ from 'lodash';
const Settings: React.FC<{}> = () => {
const dispatch = useDispatch();
const db = useDB();
useEffect(() => {
const initFromDb = async () => {
try {
const settingsFromDb = await db.get(uri('settings', {}));
console.log(
`settingsFromDb: ${JSON.stringify(settingsFromDb.settings)}`
);
dispatch(settingsActions.saveSettings(settingsFromDb.settings));
} catch {}
};
initFromDb();
}, []);
const settingsState = useSelector(
(state: { settings: SettingsState }) => state.settings
);
useEffect(() => {
if (!settingsState.default) {
const settingsFromRedux = async () => {
const id = uri('settings', {});
var settingsFromDb;
try {
settingsFromDb = await db.get(id);
} catch (error) {
console.log(
`Error getting settings from db: ${JSON.stringify(error)}`
);
settingsFromDb = { _id: id, settings: {} };
}
if (!_.isEqual(settingsState, settingsFromDb.settings)) {
console.log(`settingsFromRedux: ${JSON.stringify(settingsState)}`);
settingsFromDb.settings = settingsState;
db.put(settingsFromDb);
}
};
settingsFromRedux();
}
}, [settingsState]);
const pseudo = useRef<HTMLIonInputElement>(null);
const minTimeInterval = useRef<HTMLIonInputElement>(null);
const minDistance = useRef<HTMLIonInputElement>(null);
const modal = useRef<HTMLIonModalElement>(null);
const dismiss = () => {
modal.current?.dismiss();
};
const save = () => {
dispatch(
settingsActions.saveSettings({
user: {
pseudo: pseudo.current?.value,
},
geolocation: {
minTimeInterval: minTimeInterval.current?.value,
minDistance: minDistance.current?.value,
},
})
);
dismiss();
};
return (
<Fragment>
<IonButton id='open-SettingsDialog'>
<IonIcon slot='icon-only' icon={options} />
</IonButton>
<IonModal
ref={modal}
trigger='open-SettingsDialog'
enterAnimation={enterAnimation}
leaveAnimation={leaveAnimation}
>
<IonToolbar>
<IonTitle>Settings</IonTitle>
<IonButtons slot='end'>
<IonButton onClick={() => dismiss()}>Close</IonButton>
</IonButtons>
</IonToolbar>
<IonContent>
<IonList lines='full' class='ion-no-margin'>
<IonListHeader lines='full'>
<IonLabel>User</IonLabel>
</IonListHeader>
<IonItem>
<IonLabel>Pseudo: </IonLabel>
<IonInput
ref={pseudo}
value={settingsState.user.pseudo}
autocomplete='nickname'
></IonInput>
</IonItem>
</IonList>
<IonList lines='full' class='ion-no-margin'>
<IonListHeader lines='full'>
<IonLabel>Geolocation</IonLabel>
</IonListHeader>
<IonItem>
<IonLabel>Minimal time interval (ms): </IonLabel>
<IonInput
value={settingsState.geolocation.minTimeInterval}
ref={minTimeInterval}
inputMode='numeric'
type='number'
></IonInput>
</IonItem>
<IonItem>
<IonLabel>Minimal distance (m): </IonLabel>
<IonInput
value={settingsState.geolocation.minDistance}
ref={minDistance}
inputMode='numeric'
type='number'
></IonInput>
</IonItem>
</IonList>
<IonItem>
<IonToolbar class='secondary'>
<IonButtons slot='secondary'>
<IonButton
shape='round'
fill='solid'
color='primary'
onClick={() => save()}
>
Save
</IonButton>
<IonButton
shape='round'
fill='outline'
color='primary'
onClick={() => dismiss()}
>
Cancel
</IonButton>
</IonButtons>
</IonToolbar>
</IonItem>
</IonContent>
</IonModal>
</Fragment>
);
};
export default Settings;
+2
View File
@@ -25,6 +25,7 @@ import { initDb } from '../../db';
import TileServerChooserButton from './TileServerChooserButton';
import TileServerChooserDialog from './TileServerChooserDialog';
import TrackBrowser from './TracksBrowser';
import Settings from './Settings';
const Map: react.FC<{}> = (props: {}) => {
const dispatch = useDispatch();
@@ -68,6 +69,7 @@ const Map: react.FC<{}> = (props: {}) => {
<TrackBrowser/>
<GpxRecord />
<TileServerChooserButton />
<Settings />
</IonButtons>
</IonToolbar>
</IonHeader>