First version with a GPX export (#9) that works in a browser but, unfortunately, doesn't wotk on Adroid !

This commit is contained in:
Eric van der Vlist 2022-10-02 12:45:08 +02:00
parent 93054115a5
commit cb4a257003
3 changed files with 52 additions and 22 deletions

View File

@ -1,28 +1,39 @@
import { IonButton, IonIcon } from '@ionic/react'; import { IonButton, IonIcon } from '@ionic/react';
import { cloudDownload } from 'ionicons/icons'; import { cloudDownload } from 'ionicons/icons';
import React, { Fragment, useLayoutEffect, useRef, useState } from 'react'; import React, { Fragment, useRef } from 'react';
import { useDB } from 'react-pouchdb'; import { useDB } from 'react-pouchdb';
import { getGpxAsXmlString } from '../../db/gpx';
const GpxExport: React.FC<{ gpxId: string }> = (props: { gpxId: string }) => { const GpxExport: React.FC<{ gpx: any }> = (props: { gpx: any }) => {
const db = useDB(); const db = useDB();
const hiddenLinkElement = useRef<HTMLAnchorElement>(null); const hiddenLinkElement = useRef<HTMLAnchorElement>(null);
const [fileDownloadUrl, setFileDownloadUrl] = useState(''); var downloadName;
useLayoutEffect(() => { if (props.gpx.metadata.name !== undefined) {
if (fileDownloadUrl !== '') { downloadName = props.gpx.metadata.name;
} else if (props.gpx.gpx.metadata.name !== undefined) {
downloadName = `${props.gpx.gpx.metadata.name}.gpx`;
} else {
downloadName = `track-${props.gpx.metadata.lastModified}.gpx`;
}
const download = async (event: any) => {
event.preventDefault();
console.log('download()');
const gpxAsXml = await getGpxAsXmlString(db, props.gpx._id);
console.log(`gpxAsXml: ${gpxAsXml}`);
const blob = new Blob([gpxAsXml], {
type: 'application/gpx+xml',
});
const fileDownloadUrl = URL.createObjectURL(blob);
console.log(`fileDownloadUrl: ${fileDownloadUrl}`);
console.log(`hiddenLinkElement.current: ${hiddenLinkElement.current}`);
hiddenLinkElement.current!.href = fileDownloadUrl;
hiddenLinkElement.current?.click(); hiddenLinkElement.current?.click();
URL.revokeObjectURL(fileDownloadUrl); URL.revokeObjectURL(fileDownloadUrl);
setFileDownloadUrl(''); hiddenLinkElement.current!.href = '';
}
}, [fileDownloadUrl]);
const download = (event: any) => {
event.preventDefault();
const blob = new Blob(['<gpx/>'], { type: 'application/gpx+xml' });
const fileDownloadUrl = URL.createObjectURL(blob);
setFileDownloadUrl(fileDownloadUrl);
}; };
return ( return (
@ -30,13 +41,8 @@ const GpxExport: React.FC<{ gpxId: string }> = (props: { gpxId: string }) => {
<IonButton id='gpx-export-button' onClick={download}> <IonButton id='gpx-export-button' onClick={download}>
<IonIcon icon={cloudDownload} title='Export' slot='icon-only' /> <IonIcon icon={cloudDownload} title='Export' slot='icon-only' />
</IonButton> </IonButton>
<a <a className='hidden' download={downloadName} ref={hiddenLinkElement}>
className='hidden' download
download={props.gpxId + '.gpx'}
href={fileDownloadUrl}
ref={hiddenLinkElement}
>
download it
</a> </a>
</Fragment> </Fragment>
); );

View File

@ -58,7 +58,7 @@ const TrackBrowser: React.FC<{}> = () => {
<IonItem key={gpx._id}> <IonItem key={gpx._id}>
<span>{gpx.gpx.metadata.time}</span> <span>{gpx.gpx.metadata.time}</span>
<IonButtons slot='end'> <IonButtons slot='end'>
<GpxExport gpxId={gpx._id} /> <GpxExport gpx={gpx} />
<IonButton <IonButton
onClick={() => { onClick={() => {
deleteGps(db, { _id: gpx._id, _rev: gpx._rev }); deleteGps(db, { _id: gpx._id, _rev: gpx._rev });

View File

@ -3,7 +3,7 @@ import {
string_to_bytes, string_to_bytes,
bytes_to_base64, bytes_to_base64,
} from '@openpgp/asmcrypto.js'; } from '@openpgp/asmcrypto.js';
import { documentSharp } from 'ionicons/icons'; import GPX from '../lib/gpx-parser-builder';
export const pushGpx = async (db: any, payload: any) => { export const pushGpx = async (db: any, payload: any) => {
const gpxString = JSON.stringify(payload.gpx); const gpxString = JSON.stringify(payload.gpx);
@ -170,3 +170,27 @@ export const deleteCurrent = async (db: any) => {
await deleteGps(db, docs[i]); await deleteGps(db, docs[i]);
} }
}; };
export const getGpx = async (db: any, gpxId: string) => {
var gpxResult = await db.get(gpxId);
var gpx = gpxResult.gpx;
var trkptResults = await db.find({
selector: {
type: 'trkpt',
gpx: gpx._id,
},
});
var trkpts = trkptResults.docs;
trkpts.sort((first: any, second: any) =>
first.trkpt.time.localeCompare(second.trkpt.time)
);
trkpts.map((trkptDoc: any) => {
gpx.trk[0].trkseg[0].trkpt.push(trkptDoc.trkpt);
});
return gpx;
};
export const getGpxAsXmlString = async (db: any, gpxId: string) => {
const gpx = new GPX(await getGpx(db, gpxId));
return gpx.toString({});
};