diff --git a/src/components/map/GpxExport.tsx b/src/components/map/GpxExport.tsx index 3f88560..df4b996 100644 --- a/src/components/map/GpxExport.tsx +++ b/src/components/map/GpxExport.tsx @@ -1,28 +1,39 @@ import { IonButton, IonIcon } from '@ionic/react'; 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 { 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 hiddenLinkElement = useRef(null); - const [fileDownloadUrl, setFileDownloadUrl] = useState(''); + var downloadName; - useLayoutEffect(() => { - if (fileDownloadUrl !== '') { - hiddenLinkElement.current?.click(); - URL.revokeObjectURL(fileDownloadUrl); - setFileDownloadUrl(''); - } - }, [fileDownloadUrl]); + if (props.gpx.metadata.name !== undefined) { + 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 = (event: any) => { + const download = async (event: any) => { event.preventDefault(); - const blob = new Blob([''], { type: 'application/gpx+xml' }); + 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); - setFileDownloadUrl(fileDownloadUrl); + console.log(`fileDownloadUrl: ${fileDownloadUrl}`); + console.log(`hiddenLinkElement.current: ${hiddenLinkElement.current}`); + hiddenLinkElement.current!.href = fileDownloadUrl; + hiddenLinkElement.current?.click(); + URL.revokeObjectURL(fileDownloadUrl); + hiddenLinkElement.current!.href = ''; }; return ( @@ -30,13 +41,8 @@ const GpxExport: React.FC<{ gpxId: string }> = (props: { gpxId: string }) => { - - download it + + download ); diff --git a/src/components/map/TracksBrowser.tsx b/src/components/map/TracksBrowser.tsx index abc40eb..47c6b4d 100644 --- a/src/components/map/TracksBrowser.tsx +++ b/src/components/map/TracksBrowser.tsx @@ -58,7 +58,7 @@ const TrackBrowser: React.FC<{}> = () => { {gpx.gpx.metadata.time} - + { deleteGps(db, { _id: gpx._id, _rev: gpx._rev }); diff --git a/src/db/gpx.ts b/src/db/gpx.ts index 5d6aa76..1561620 100644 --- a/src/db/gpx.ts +++ b/src/db/gpx.ts @@ -3,7 +3,7 @@ import { string_to_bytes, bytes_to_base64, } from '@openpgp/asmcrypto.js'; -import { documentSharp } from 'ionicons/icons'; +import GPX from '../lib/gpx-parser-builder'; export const pushGpx = async (db: any, payload: any) => { const gpxString = JSON.stringify(payload.gpx); @@ -170,3 +170,27 @@ export const deleteCurrent = async (db: any) => { 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({}); +};