import { useI18n } from '@solid-primitives/i18n'; import { Typography, Card, CardContent, CardActions, Button, Box, LinearProgress, CircularProgress, } from '@suid/material'; import { Component, createEffect, createSignal, Show } from 'solid-js'; import { findStartTime } from '../../lib/gpx'; import GPX from '../../lib/gpx-parser-builder/src/gpx'; import dispatch from '../../workers/dispatcher-main'; import GpxChooser from '../gpx-chooser'; import { currentGpxId } from '../gpx-dialog'; import { Filesystem as CapacitorFileSystem, Encoding, } from '@capacitor/filesystem'; import ExifReader from 'exifreader'; interface Props { file: File; } interface StatsAndGpx { gpx: Gpx; stats: any; } interface Picture { id: string; date: string; gpx: { Latitude: number; Longitude: number; Altitude: number }; thumbnailUrl: string; } const analyzeGpx = (gpx: Gpx | undefined) => { if (gpx === undefined) { return {}; } const stats = { creator: gpx.$.creator, nbWpts: gpx.wpt ? gpx.wpt?.length : 0, nbRtes: gpx.rte ? gpx.rte?.length : 0, nbTrks: gpx.trk ? gpx.trk?.length : 0, trkMaybeRte: gpx.trk && gpx.trk[0].trkseg && gpx.trk[0].trkseg[0] && gpx.trk[0].trkseg[0].trkpt && !gpx.trk[0].trkseg[0].trkpt[0].time, startTime: findStartTime(gpx), }; return stats; }; const ImportSingleFile: Component = ({ file: file }) => { const [t] = useI18n(); const [statsAndGpx, setStatsAndGpx] = createSignal(); const [picture, setPicture] = createSignal(); const [state, setState] = createSignal('init'); const [gpxId, setGpxId] = createSignal('new'); createEffect(() => { setGpxId(currentGpxId()); }); const parseGpx = (content: string) => { const gpx = GPX.parse(content); console.log({ caller: 'ImportSingleFile / JSON', gpxFile: file, gpx, gpxId: gpxId(), }); setStatsAndGpx({ gpx, stats: analyzeGpx(gpx) }); }; if (typeof file === 'string') { CapacitorFileSystem.requestPermissions().then((permissionStatus) => { console.log({ caller: 'ImportSingleFile / content', permissionStatus, }); }); CapacitorFileSystem.readFile({ path: file, encoding: Encoding.UTF8, }).then((content) => { console.log({ caller: 'ImportSingleFile / content', file, content, }); parseGpx(content.data); }); } else { const reader = new FileReader(); if (file.type === 'image/jpeg') { reader.readAsArrayBuffer(file); reader.addEventListener( 'load', async () => { const tags = ExifReader.load(reader.result, { expanded: true }); const exif = tags.exif; const dateSegments = exif?.DateTimeOriginal?.value[0].split(' '); const date = `${dateSegments[0].replaceAll(':', '-')}T${ dateSegments[1] }.${exif?.SubSecTimeOriginal?.value[0] || '0'}${ exif?.OffsetTimeOriginal?.value[0] }`; const id = exif?.ImageUniqueID?.value[0]; const gps = tags.gps; const thumbnail = tags.Thumbnail; const thumbnailUrl = `data:${thumbnail?.type};base64,${thumbnail?.base64}`; console.log({ caller: 'ImportSingleFile / Jpeg', file, type: file.type, result: reader.result, tags, date, id, gps, thumbnailUrl, }); setPicture({ id, gps, thumbnailUrl, date }); }, false ); } else { // GPX reader.readAsText(file); reader.addEventListener( 'load', async () => { // this will then display a text gpxfile console.log({ caller: 'ImportSingleFile / XML', file, type: file.type, result: reader.result, }); parseGpx(reader.result); }, false ); } } const doImport = async () => { setState('importing'); // console.log({ caller: 'GpxImport / JSON', file, gpx }); // if (gpx) { // const startTime = new Date(findStartTime(gpx)!); await dispatch({ action: 'pruneAndSaveImportedGpx', params: { id: gpxId(), gpx: statsAndGpx()?.gpx, tech: typeof file === 'string' ? { importDate: new Date().toISOString(), uri: file, } : { lastModified: new Date(file.lastModified).toISOString(), importDate: new Date().toISOString(), name: file.name, size: file.size, type: file.type, }, }, }); console.log({ caller: 'GpxImport / JSON / done', gpxFile: file, gpx: statsAndGpx()?.gpx, }); setState('done'); // } else { // console.error({ // message: "can't parse GPX file", // file, // xml: fileReader.result, // }); // } // // TODO: error handling // }, // false // ); // } }; const [selectedTrkTransform, setSelectedTrkTransform] = createSignal( 'importNonTimedTrksAsRtes' ); const handleTrkTransformChange = (event: any) => { setSelectedTrkTransform(event.target.value); }; const controlTrkTransformProps = (item: string) => ({ checked: selectedTrkTransform() === item, onChange: handleTrkTransformChange, value: item, name: 'trkTransform', label: t(item), inputProps: { 'aria-label': item }, }); return ( {t('file')} {file.name} {t('gpxStats', statsAndGpx().stats)}{' '} {statsAndGpx()?.stats.startTime ? t('gpxStartTime', statsAndGpx().stats) : t('gpxNoStartTime')} {t('trkMaybeRte')} ); }; export default ImportSingleFile;