Basic dialog to start/pause/stop and clear track recording.
This commit is contained in:
parent
d71881dc02
commit
3235d9ae70
|
@ -1,15 +1,30 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
import { useDB } from 'react-pouchdb';
|
||||
import React, { Fragment, useRef, useState } from 'react';
|
||||
|
||||
import { useDB, useFind } from 'react-pouchdb';
|
||||
|
||||
import '../../theme/get-location.css';
|
||||
import { IonButton, IonIcon } from '@ionic/react';
|
||||
import { recordingOutline, recording } from 'ionicons/icons';
|
||||
import {
|
||||
createAnimation,
|
||||
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 { deleteCurrent, saveCurrent } from '../../db/gpx';
|
||||
|
||||
const GpxRecord: React.FC<{}> = () => {
|
||||
const db = useDB();
|
||||
|
@ -18,24 +33,152 @@ const GpxRecord: React.FC<{}> = () => {
|
|||
|
||||
const [watcher_id, setWatcher_id] = useState();
|
||||
|
||||
const toggleIsRecording = () => {
|
||||
if (isRecording) {
|
||||
stopBackgroundGeolocation(watcher_id);
|
||||
} else {
|
||||
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 startRecording = () => {
|
||||
startBackgroundGeolocation(db).then((result) => {
|
||||
setWatcher_id(result);
|
||||
});
|
||||
setIsRecording(true);
|
||||
dismiss();
|
||||
};
|
||||
|
||||
const pauseRecording = () => {
|
||||
if (isRecording) {
|
||||
stopBackgroundGeolocation(watcher_id);
|
||||
}
|
||||
setIsRecording(!isRecording);
|
||||
setIsRecording(false);
|
||||
dismiss();
|
||||
};
|
||||
|
||||
const stopRecording = () => {
|
||||
saveCurrent(db);
|
||||
pauseRecording();
|
||||
};
|
||||
|
||||
const deleteRecording = () => {
|
||||
deleteCurrent(db);
|
||||
pauseRecording();
|
||||
};
|
||||
|
||||
const enterAnimation = (baseEl: HTMLElement) => {
|
||||
const root = baseEl.shadowRoot;
|
||||
|
||||
const backdropAnimation = createAnimation()
|
||||
.addElement(root?.querySelector('ion-backdrop')!)
|
||||
.fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
|
||||
|
||||
const wrapperAnimation = createAnimation()
|
||||
.addElement(root?.querySelector('.modal-wrapper')!)
|
||||
.keyframes([
|
||||
{ offset: 0, opacity: '0', transform: 'scale(0)' },
|
||||
{ offset: 1, opacity: '0.99', transform: 'scale(1)' },
|
||||
]);
|
||||
|
||||
return createAnimation()
|
||||
.addElement(baseEl)
|
||||
.easing('ease-out')
|
||||
.duration(500)
|
||||
.addAnimation([backdropAnimation, wrapperAnimation]);
|
||||
};
|
||||
|
||||
const leaveAnimation = (baseEl: HTMLElement) => {
|
||||
return enterAnimation(baseEl).direction('reverse');
|
||||
};
|
||||
|
||||
return (
|
||||
<IonButton onClick={toggleIsRecording}>
|
||||
<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>Track recording</IonTitle>
|
||||
<IonButtons slot='end'>
|
||||
<IonButton onClick={() => dismiss()}>Close</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
<IonContent>
|
||||
{!isRecording && (
|
||||
<IonButton
|
||||
expand='block'
|
||||
color='primary'
|
||||
size='large'
|
||||
onClick={startRecording}
|
||||
>
|
||||
<IonIcon slot='start' icon={recording}></IonIcon>
|
||||
{hasCurrentTrack ? (
|
||||
<span>Resume recording</span>
|
||||
) : (
|
||||
<span>Start recording</span>
|
||||
)}
|
||||
</IonButton>
|
||||
)}
|
||||
{isRecording && (
|
||||
<IonButton
|
||||
expand='block'
|
||||
color='primary'
|
||||
size='large'
|
||||
onClick={pauseRecording}
|
||||
>
|
||||
<IonIcon slot='start' icon={pauseCircle}></IonIcon>Pause
|
||||
</IonButton>
|
||||
)}
|
||||
{hasCurrentTrack && (
|
||||
<>
|
||||
<IonButton
|
||||
expand='block'
|
||||
color='danger'
|
||||
size='large'
|
||||
onClick={stopRecording}
|
||||
>
|
||||
<IonIcon slot='start' icon={stop}></IonIcon>Stop recording
|
||||
<br />
|
||||
(and save track)
|
||||
</IonButton>
|
||||
<IonButton
|
||||
expand='block'
|
||||
color='danger'
|
||||
size='large'
|
||||
onClick={deleteRecording}
|
||||
>
|
||||
<IonIcon slot='start' icon={closeCircle}></IonIcon>Cancel
|
||||
recording
|
||||
<br />
|
||||
(and clear track)
|
||||
</IonButton>
|
||||
</>
|
||||
)}
|
||||
</IonContent>
|
||||
</IonModal>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { initDb } from '.';
|
||||
import PouchDB from 'pouchdb';
|
||||
import { appendTrkpt } from './gpx';
|
||||
import { appendTrkpt, deleteCurrent, saveCurrent } from './gpx';
|
||||
|
||||
import PouchDBFind from 'pouchdb-find';
|
||||
import { mkdtempSync, rmdirSync } from 'fs';
|
||||
|
@ -27,7 +27,7 @@ beforeEach(async () => {
|
|||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// await db.close();
|
||||
// await db.close();
|
||||
await db.destroy();
|
||||
});
|
||||
|
||||
|
@ -48,3 +48,54 @@ describe('Checking that trkpts are beeing inserted', () => {
|
|||
expect(docs.length).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Checking that saveCurrent() is working as expected', () => {
|
||||
test(', that we still have two documents after saving.', async () => {
|
||||
await appendTrkpt(db, {});
|
||||
await saveCurrent(db);
|
||||
const results = await db.find({
|
||||
selector: {},
|
||||
});
|
||||
const docs = results.docs;
|
||||
// console.log(`docs: ${JSON.stringify(docs)}`);
|
||||
expect(docs.length).toBe(2);
|
||||
});
|
||||
test("and that we don't have current tracks after saving.", async () => {
|
||||
await appendTrkpt(db, {});
|
||||
await saveCurrent(db);
|
||||
const results = await db.find({
|
||||
selector: {
|
||||
type: 'gpx',
|
||||
subtype: 'current',
|
||||
},
|
||||
});
|
||||
const docs = results.docs;
|
||||
// console.log(`docs: ${JSON.stringify(docs)}`);
|
||||
expect(docs.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Checking that deleteCurrent() is working as expected', () => {
|
||||
test(', that we have no more documents after deleting.', async () => {
|
||||
await appendTrkpt(db, { time: '' });
|
||||
await deleteCurrent(db);
|
||||
const results = await db.find({
|
||||
selector: {},
|
||||
});
|
||||
const docs = results.docs;
|
||||
// console.log(`docs: ${JSON.stringify(docs)}`);
|
||||
expect(docs.length).toBe(0);
|
||||
});
|
||||
test(', that we have two documents from a saved track after deleting the current one.', async () => {
|
||||
await appendTrkpt(db, { time: '' });
|
||||
await saveCurrent(db);
|
||||
await appendTrkpt(db, { time: '' });
|
||||
await deleteCurrent(db);
|
||||
const results = await db.find({
|
||||
selector: {},
|
||||
});
|
||||
const docs = results.docs;
|
||||
// console.log(`docs: ${JSON.stringify(docs)}`);
|
||||
expect(docs.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -93,8 +93,6 @@ const initialGpx = {
|
|||
};
|
||||
|
||||
export const appendTrkpt = async (db: any, trkpt: any) => {
|
||||
|
||||
|
||||
const currents = await db.find({
|
||||
selector: {
|
||||
type: 'gpx',
|
||||
|
@ -118,3 +116,49 @@ export const appendTrkpt = async (db: any, trkpt: any) => {
|
|||
await db.post(docPoint);
|
||||
console.log(JSON.stringify(docPoint));
|
||||
};
|
||||
|
||||
export const saveCurrent = async (db: any) => {
|
||||
const currents = await db.find({
|
||||
selector: {
|
||||
type: 'gpx',
|
||||
subtype: 'current',
|
||||
},
|
||||
});
|
||||
console.log(`saveCurrent - db.find() : ${JSON.stringify(currents)}`);
|
||||
if (currents.docs.length > 0) {
|
||||
const doc = currents.docs[0];
|
||||
doc.subtype = 'other';
|
||||
await db.put(doc);
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteCurrent = async (db: any) => {
|
||||
const currents = await db.find({
|
||||
selector: {
|
||||
type: 'gpx',
|
||||
subtype: 'current',
|
||||
},
|
||||
fields: ['_id', '_rev'],
|
||||
});
|
||||
console.log(`deleteCurrent - db.find(gpx) : ${JSON.stringify(currents)}`);
|
||||
const docs: { _id: string; _rev: string }[] = currents.docs;
|
||||
for (let i = 0; i < docs.length; i++) {
|
||||
console.log(`Deleting document ${JSON.stringify(docs[i])}`);
|
||||
await db.put({ _deleted: true, ...docs[i] });
|
||||
console.log(`done, id: ${docs[i]._id}`);
|
||||
const currentTrkpts = await db.find({
|
||||
selector: {
|
||||
type: 'trkpt',
|
||||
gpx: docs[i]._id,
|
||||
},
|
||||
fields: ['_id', '_rev', 'type'],
|
||||
});
|
||||
console.log(
|
||||
`deleteCurrent - db.find(trkpts) : ${JSON.stringify(currentTrkpts)}`
|
||||
);
|
||||
const trkpts: { _id: string; _rev: string }[] = currentTrkpts.docs;
|
||||
for (let j = 0; j < trkpts.length; j++) {
|
||||
await db.put({ _deleted: true, ...trkpts[j] });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -53,9 +53,9 @@ export const initDb = async (db: any, setDbReady: any) => {
|
|||
for (var index of existingIndexes) {
|
||||
if (index.type === 'json') {
|
||||
// Non system indexes
|
||||
console.log(`Checking existing index :${JSON.stringify(index)}`);
|
||||
// console.log(`Checking existing index :${JSON.stringify(index)}`);
|
||||
if (!findIndex(requiredIndexes, index)) {
|
||||
console.log(`db.deleteIndex(${JSON.stringify(index)})`);
|
||||
// console.log(`db.deleteIndex(${JSON.stringify(index)})`);
|
||||
await db.deleteIndex(index);
|
||||
}
|
||||
}
|
||||
|
@ -63,14 +63,14 @@ export const initDb = async (db: any, setDbReady: any) => {
|
|||
|
||||
for (var index of requiredIndexes) {
|
||||
if (!findIndex(existingIndexes, index)) {
|
||||
console.log(`db.createIndex(${JSON.stringify(index)})`);
|
||||
// console.log(`db.createIndex(${JSON.stringify(index)})`);
|
||||
await db.createIndex({ name: index.name, ...index.def });
|
||||
}
|
||||
}
|
||||
|
||||
setDbReady(true);
|
||||
|
||||
const indexes = await db.getIndexes();
|
||||
/* const indexes = await db.getIndexes();
|
||||
console.log(`indexes: ${JSON.stringify(indexes)}`);
|
||||
|
||||
const explain1 = await db.explain({
|
||||
|
@ -90,4 +90,5 @@ export const initDb = async (db: any, setDbReady: any) => {
|
|||
// use_index: 'type-trkpt-gpx-time',
|
||||
});
|
||||
console.log(`explain2: ${JSON.stringify(explain2)}`);
|
||||
*/
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue