diff --git a/README.md b/README.md index 5884029..952c78f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,15 @@ # Dyomedea +## License + +GPL 3.0. + ## Branches -* master: dev branch (started as a React project; now using dolidjs) -* multi-layers: attempt to create a native React map components. Went pretty far but there was still so many things to implement that I switched to: -* openlayers: an attempt to use React with Openlayers. Wasn't that easy because Openlayers is heavily based on the DOM while React uses a "pseudo-dom". That has been one of the reasons why I switched (again) to: -* solid: a SolidJS / Openlayers implementation that has replaced the master branch on Feb 5th, 2023. +* master: dev (and only active) branch (started as a React project, now using solidjs) +* multi-layers: (deprecated) attempt to create a native React map components. Went pretty far but there was still so many things to implement that I switched to: +* openlayers: (deprecated) an attempt to use React with Openlayers. Wasn't that easy because Openlayers is heavily based on the DOM while React uses a "pseudo-dom". That has been one of the reasons why I switched (again) to: +* solid: (merged into master and deprecated) a SolidJS / Openlayers implementation that has replaced the master branch on Feb 5th, 2023. ## Hiking app. @@ -350,6 +354,9 @@ Requires esrun (`sudo npm i -g @digitak/esrun`) ### Patches +``` + + * suid: https://github.com/swordev/suid/issues/89 ### NPM updates: use npm-check-updates ! diff --git a/src/components/rte/Rte.tsx b/src/components/rte/Rte.tsx index b56bbf7..22fe664 100644 --- a/src/components/rte/Rte.tsx +++ b/src/components/rte/Rte.tsx @@ -1,6 +1,5 @@ import { Component, createEffect, createSignal, onCleanup } from 'solid-js'; -import dispatch, { cancelDispatch } from '../../workers/dispatcher-main'; import VectorSource from 'ol/source/Vector'; import GeoJSON from 'ol/format/GeoJSON'; import { @@ -36,7 +35,7 @@ export const Rte: Component = ({ vectorSource, rteId, context }) => { createEffect(() => { console.log({ caller: 'Rte', vectorSource, rteId, rte: rte() }); - if (rte()) { + if (rte() && rte().rtept && rte().rtept.length > 0) { let geo: any = { type: 'FeatureCollection', features: [ diff --git a/src/components/rte/RteViewer.tsx b/src/components/rte/RteViewer.tsx index 3a73d88..962c98e 100644 --- a/src/components/rte/RteViewer.tsx +++ b/src/components/rte/RteViewer.tsx @@ -1,4 +1,4 @@ -import { Component, createSignal } from 'solid-js'; +import { Component, createSignal, Show } from 'solid-js'; import { peekCachedSignal } from '../../workers/cached-signals'; import RteIcon from '../../icons/directions-svgrepo-com.svg?component-solid'; import { useI18n } from '@solid-primitives/i18n'; @@ -74,11 +74,13 @@ const RteViewer: Component = ({ rteId }) => { <>
{getFormatedLength(lineString)} {t('from')}{' '} - rte().rtept.at(0)} - putAction='putRtept' - putParamName='rtept' - />{' '} + + rte().rtept.at(0)} + putAction='putRtept' + putParamName='rtept' + />{' '} + {t('to')}{' '} rte().rtept.at(-1)} diff --git a/src/components/trkseg/Trkseg.tsx b/src/components/trkseg/Trkseg.tsx index 591d28b..4c839eb 100644 --- a/src/components/trkseg/Trkseg.tsx +++ b/src/components/trkseg/Trkseg.tsx @@ -49,7 +49,7 @@ export const Trkseg: Component = ({ createEffect(() => { console.log({ caller: 'Trkseg', vectorSource, trksegId, trkseg: trkseg() }); - if (trkseg()) { + if (trkseg() && trkseg().trkpt && trkseg().trkpt.length > 0) { let geo: any = { type: 'FeatureCollection', features: [ diff --git a/src/db/gpx.ts b/src/db/gpx.ts index 367d463..ebe674f 100644 --- a/src/db/gpx.ts +++ b/src/db/gpx.ts @@ -84,15 +84,15 @@ const prune = ( if ( key === 'wpt' || key === 'rte' || - key === 'rtept' || + // key === 'rtept' || key === 'trk' || - key === 'trkseg' || - key === 'trkpt' + key === 'trkseg' + // key === 'trkpt' ) { const subObjects = object[key]; for (const index in subObjects) { const subId = { ...id }; - if (key === 'trkpt') { + /* if (key === 'trkpt') { // fix buggy times in GPX tracks const normalId = intToTrkptId( new Date(object[key][index].time).valueOf() @@ -101,10 +101,10 @@ const prune = ( normalId > previousIds.trk ? normalId : previousIds.trk + 1; subId[key] = id; previousIds.trk = id; - } else { - previousIds[key] = previousIds[key] + 1; - subId[key] = previousIds[key]; - } + } else { */ + previousIds[key] = previousIds[key] + 1; + subId[key] = previousIds[key]; + /* } */ // console.log({ // caller: 'prune', // id, diff --git a/src/db/rte.ts b/src/db/rte.ts index be150ca..49284cb 100644 --- a/src/db/rte.ts +++ b/src/db/rte.ts @@ -1,3 +1,5 @@ +import { debounce, memoize, property, wrap } from 'lodash'; +import { delay } from '../lib/delay'; import getUri from '../lib/ids'; import { appendToArray, putNewGpx } from './gpx'; import { getFamily, put } from './lib'; @@ -32,9 +34,43 @@ export const putNewRte = async (id?: IdRte | IdGpx) => { return finalId as IdRte; }; -export const getRte = async (params: any) => { +// See https://stackoverflow.com/questions/28787436/debounce-a-function-with-argument +const debounceByParam = ( + targetFunc: (params: any) => any, + resolver: (params: any) => any, + ...debounceParams: any +) => + wrap( + memoize(() => debounce(targetFunc, ...debounceParams), resolver), + (getMemoizedFunc, ...params) => getMemoizedFunc(...params)(...params) + ); + +const compactRteOrTrkseg = (params: any) => { + const { getDocs } = params; + getDocs(params).then(({ docs }) => { + if (docs.rows.length > 1) { + const compactedDocs = docs.rows.map((row: any) => { + if (['rte', 'trkseg'].includes(row.doc.type)) { + return row.doc; + } + return { ...row.doc, doc: undefined, _deleted: true }; + }); + db.bulkDocs(compactedDocs); + } + console.log({ caller: 'compactRteOrTrkseg', params, compactedDocs }); + }); +}; + +export const compactRteOrTrksegDebounced = debounceByParam( + compactRteOrTrkseg, + property('id'), + 3600000 * (1 + Math.random()) +); + +const getRteDocs = async (params: any) => { const { id } = params; const docs = await getFamily(id, { include_docs: true }); + // console.log({ caller: 'getRte', id, docs }); let target: any[]; let rte: Rte | undefined = undefined; docs.rows.every((row: any) => { @@ -56,12 +92,21 @@ export const getRte = async (params: any) => { //level 1 if (row.doc.type === 'rtept') { target.splice(1); - row.doc.doc.id = row.doc._id; + // row.doc.doc.id = row.doc._id; appendToArray(target.at(-1), row.doc.type, row.doc.doc); target.push(row.doc.doc); } return true; }); + return { docs, rte }; +}; + +export const getRte = async (params: any) => { + const { id } = params; + const { docs, rte } = await getRteDocs(params); + if (docs.rows.length > 1) { + compactRteOrTrksegDebounced({ id, getDocs: getRteDocs }); + } return rte; }; diff --git a/src/db/rtept.ts b/src/db/rtept.ts index 7868773..1e7c26d 100644 --- a/src/db/rtept.ts +++ b/src/db/rtept.ts @@ -1,6 +1,3 @@ -import getUri from '../lib/ids'; -import { put } from './lib'; -import { putNewRte } from './rte'; export const emptyRtept: Wpt = { $: { lat: 0, lon: 0 }, @@ -24,28 +21,3 @@ export const emptyRtept: Wpt = { dgpsid: undefined, extensions: undefined, }; - -export const putNewRtept = async (id?: IdGpx | IdRte | IdRtept) => { - let finalId = { ...id }; - if (!('rtept' in finalId)) { - const rteId = await putNewRte(id); - finalId = { ...rteId, rtept: 0 }; - } - const uri = getUri('rtept', finalId); - await put( - uri, - 'rtept', - (rtept) => { - return rtept; - }, - emptyRtept - ); - return finalId as IdRtept; -}; - -export const putRtept = async (params: any) => { - const { id, rtept } = params; - rtept.id = undefined; - await put(id, 'rtept', (doc) => rtept, rtept); - return rtept; -}; diff --git a/src/db/trkpt.ts b/src/db/trkpt.ts index 8d8851b..24c7af3 100644 --- a/src/db/trkpt.ts +++ b/src/db/trkpt.ts @@ -1,6 +1,5 @@ import getUri, { intToTrkptId } from '../lib/ids'; import { put } from './lib'; -import { putNewTrkseg } from './trkseg'; const emptyTrkpt: Wpt = { $: { lat: 0, lon: 0 }, @@ -31,24 +30,6 @@ const emptyTrkpt: Wpt = { }, }; -export const putNewTrkpt = async (id?: IdTrk | IdGpx | IdTrkseg | IdTrkpt) => { - let finalId = { ...id }; - if (!('trkpt' in finalId)) { - const trksegId = await putNewTrkseg(id); - finalId = { ...trksegId, trkpt: intToTrkptId(Date.now()) }; - } - const uri = getUri('trkpt', finalId); - await put( - uri, - 'trkpt', - (trkpt) => { - return trkpt; - }, - emptyTrkpt - ); - return finalId; -}; - export const putTrkpt = async (params: any) => { const { id, trkpt } = params; diff --git a/src/db/trkseg.ts b/src/db/trkseg.ts index a788911..22c9c8c 100644 --- a/src/db/trkseg.ts +++ b/src/db/trkseg.ts @@ -1,6 +1,7 @@ import getUri, { intToTrkptId } from '../lib/ids'; import { appendToArray } from './gpx'; import { getFamily, put } from './lib'; +import { compactRteOrTrksegDebounced } from './rte'; import { putNewTrk } from './trk'; import { emptyWpt } from './wpt'; @@ -9,27 +10,10 @@ const emptyTrkseg: Trkseg = { extensions: undefined, }; -export const putNewTrkseg = async (id?: IdTrk | IdGpx | IdTrkseg) => { - let finalId = { ...id }; - if (!('trkseg' in finalId)) { - const trkId = await putNewTrk(id); - finalId = { ...trkId, trkseg: 0 }; - } - const uri = getUri('trkseg', finalId); - await put( - uri, - 'trkseg', - (trkseg) => { - return trkseg; - }, - emptyTrkseg - ); - return finalId as IdTrkseg; -}; - -export const getTrkseg = async (params: any) => { +const getTrksegDocs = async (params: any) => { const { id } = params; const docs = await getFamily(id, { include_docs: true }); + console.log({ caller: 'getTrksegDocs', id, docs }); let target: any[]; let trkseg: Trkseg | undefined = undefined; docs.rows.every((row: any) => { @@ -37,13 +21,12 @@ export const getTrkseg = async (params: any) => { if (row.doc.type === 'trkseg') { if (!!trkseg) { console.error({ - caller: 'getTrkseg', + caller: 'getTrksegDocs', id, row, target, trkseg, }); - return false; // Hack to stop if getFamily fails } target = [row.doc.doc]; @@ -52,12 +35,21 @@ export const getTrkseg = async (params: any) => { //level 1 if (row.doc.type === 'trkpt') { target.splice(1); - row.doc.doc.id = row.doc._id; + // row.doc.doc.id = row.doc._id; appendToArray(target.at(-1), row.doc.type, row.doc.doc); target.push(row.doc.doc); } return true; }); + return { trkseg, docs }; +}; + +export const getTrkseg = async (params: any) => { + const { id } = params; + const { docs, trkseg } = await getTrksegDocs(params); + if (docs.rows.length > 1) { + compactRteOrTrksegDebounced({ id, getDocs: getTrksegDocs }); + } return trkseg; }; diff --git a/src/workers/dispatcher-worker.ts b/src/workers/dispatcher-worker.ts index f0c07be..7e77e8e 100644 --- a/src/workers/dispatcher-worker.ts +++ b/src/workers/dispatcher-worker.ts @@ -14,7 +14,6 @@ import { } from '../db/gpx'; import { putOverlays } from '../db/overlays'; import { deleteRte, putRte } from '../db/rte'; -import { putRtept } from '../db/rtept'; import { getSettings, putSettings } from '../db/settings'; import { getState, setState } from '../db/state'; import { deleteTrk, getTrk, putNewTrk } from '../db/trk'; @@ -52,7 +51,6 @@ onmessage = async function (e) { putWpt, putRte, - putRtept, putTrkpt, deleteTrk,