dyomedea/src/components/map/GpxRecord.tsx

215 lines
5.3 KiB
TypeScript

import React, { Fragment, useRef, useState } from 'react';
import { useDB, useFind } from 'react-pouchdb';
import '../../theme/get-location.css';
import {
IonButton,
IonButtons,
IonContent,
IonIcon,
IonModal,
IonTitle,
IonToolbar,
} from '@ionic/react';
import {
recordingOutline,
recording,
closeCircle,
pauseCircle,
stop,
} from 'ionicons/icons';
import {
startBackgroundGeolocation,
stopBackgroundGeolocation,
} from '../../lib/background-geolocation';
import { appendTrkpt, deleteCurrent, saveCurrent } from '../../db/gpx';
import { enterAnimation, leaveAnimation } from '../../lib/animation';
import { useDispatch, useSelector } from 'react-redux';
import { mapActions } from '../../store/map';
import { SettingsState } from '../../store/settings';
import i18n, { setI18nLanguage } from '../../i18n/index';
declare global {
var $lastValidLocationTime: number;
}
const GpxRecord: React.FC<{}> = () => {
const language = useSelector(
(state: { settings: SettingsState }) => state.settings.language
);
setI18nLanguage(language);
const db = useDB();
const [isRecording, setIsRecording] = useState(false);
const [watcher_id, setWatcher_id] = useState();
const geolocationsSettingsState = useSelector(
(state: { settings: SettingsState }) => state.settings.geolocation
);
const gpxes = useFind({
selector: {
type: 'gpx',
subtype: 'current',
},
});
const hasCurrentTrack = gpxes.length > 0;
console.log(
`GpxRecord, hasCurrentTrack:${hasCurrentTrack}, gpxes: ${JSON.stringify(
gpxes
)}`
);
const modal = useRef<HTMLIonModalElement>(null);
const dismiss = () => {
modal.current?.dismiss();
};
const dispatch = useDispatch();
const newLocationHandler = (location: any) => {
console.log(
`Location filtering, elapsed time: ${
location.time - globalThis.$lastValidLocationTime
}`
);
if (
location.time - globalThis.$lastValidLocationTime >
geolocationsSettingsState.minTimeInterval
) {
globalThis.$lastValidLocationTime = location.time;
appendTrkpt(db, {
$: {
lat: location.latitude,
lon: location.longitude,
},
ele: location.altitude,
time: new Date(location.time).toISOString(),
extensions: {
speed: location.speed,
accuracy: location.accuracy,
},
});
dispatch(
mapActions.setCurrent({
lat: location.latitude,
lon: location.longitude,
})
);
}
};
const startRecording = () => {
globalThis.$lastValidLocationTime = 0;
startBackgroundGeolocation(
newLocationHandler,
geolocationsSettingsState.minDistance
).then((result) => {
setWatcher_id(result);
});
setIsRecording(true);
dismiss();
};
const pauseRecording = () => {
if (isRecording) {
stopBackgroundGeolocation(watcher_id);
}
setIsRecording(false);
dismiss();
};
const stopRecording = () => {
saveCurrent(db);
pauseRecording();
};
const deleteRecording = () => {
deleteCurrent(db);
pauseRecording();
};
return (
<Fragment>
<IonButton id='open-RecordDialog'>
{isRecording && (
<IonIcon slot='icon-only' icon={recording} style={{ color: 'red' }} />
)}
{!isRecording && <IonIcon slot='icon-only' icon={recordingOutline} />}
</IonButton>
<IonModal
ref={modal}
trigger='open-RecordDialog'
enterAnimation={enterAnimation}
leaveAnimation={leaveAnimation}
>
<IonToolbar>
<IonTitle>{i18n.trackRecording}</IonTitle>
<IonButtons slot='end'>
<IonButton onClick={() => dismiss()}>{i18n.close}</IonButton>
</IonButtons>
</IonToolbar>
<IonContent>
{!isRecording && (
<IonButton
expand='block'
color='primary'
size='large'
onClick={startRecording}
>
<IonIcon slot='start' icon={recording}></IonIcon>
{hasCurrentTrack ? (
<span>{i18n.resumeRecording}</span>
) : (
<span>{i18n.startRecording}</span>
)}
</IonButton>
)}
{isRecording && (
<IonButton
expand='block'
color='primary'
size='large'
onClick={pauseRecording}
>
<IonIcon slot='start' icon={pauseCircle}></IonIcon>{i18n.pauseRecording}
</IonButton>
)}
{hasCurrentTrack && (
<>
<IonButton
expand='block'
color='danger'
size='large'
onClick={stopRecording}
>
<IonIcon slot='start' icon={stop}></IonIcon>{i18n.stopRecording}
</IonButton>
<IonButton
expand='block'
color='danger'
size='large'
onClick={deleteRecording}
>
<IonIcon slot='start' icon={closeCircle}></IonIcon>{i18n.cancelRecording}
</IonButton>
</>
)}
</IonContent>
</IonModal>
</Fragment>
);
};
export default GpxRecord;