Storing imported tracks in local "forage".
This commit is contained in:
parent
bb2130793d
commit
d0bac1c509
File diff suppressed because it is too large
Load Diff
|
@ -15,7 +15,7 @@
|
|||
"@capacitor/status-bar": "4.0.1",
|
||||
"@ionic/react": "^6.2.6",
|
||||
"@ionic/react-router": "^6.2.6",
|
||||
"@ionic/storage": "^3.0.6",
|
||||
"@openpgp/asmcrypto.js": "^2.3.2",
|
||||
"@reduxjs/toolkit": "^1.8.5",
|
||||
"@testing-library/jest-dom": "^5.11.9",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
|
@ -27,18 +27,25 @@
|
|||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-router": "^5.1.11",
|
||||
"@types/react-router-dom": "^5.1.7",
|
||||
"buffer": "^6.0.3",
|
||||
"cordova-plugin-geolocation": "^4.1.0",
|
||||
"cordova-sqlite-storage": "^6.0.0",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"git": "^0.1.5",
|
||||
"ionicons": "^6.0.3",
|
||||
"isomorphic-xml2js": "^0.1.3",
|
||||
"localforage": "^1.10.0",
|
||||
"localforage-cordovasqlitedriver": "^1.8.0",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
"react-app-polyfill": "^3.0.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-redux": "^8.0.2",
|
||||
"react-router": "^6.3.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-scripts": "^5.0.0",
|
||||
"status": "^0.0.13",
|
||||
"stream-browserify": "^3.0.0",
|
||||
"typescript": "^4.8.3",
|
||||
"web-vitals": "^0.2.4",
|
||||
"workbox-background-sync": "^5.1.4",
|
||||
|
|
|
@ -22,13 +22,16 @@ import '@ionic/react/css/display.css';
|
|||
import './theme/variables.css';
|
||||
|
||||
import Map from './components/map/map';
|
||||
import DbContextProvider from './db/db-context-provider';
|
||||
|
||||
setupIonicReact();
|
||||
|
||||
const App: React.FC = () => (
|
||||
<IonApp>
|
||||
<Provider store={store}>
|
||||
<Map />
|
||||
<DbContextProvider>
|
||||
<Map />
|
||||
</DbContextProvider>
|
||||
</Provider>
|
||||
</IonApp>
|
||||
);
|
||||
|
|
|
@ -14,7 +14,7 @@ const GpxImport: React.FC<{}> = () => {
|
|||
|
||||
const onChangeHandler = (event: any) => {
|
||||
console.log('On change handler');
|
||||
const file = event.target.files[0];
|
||||
const file: File = event.target.files[0];
|
||||
const fileReader = new FileReader();
|
||||
fileReader.readAsText(file);
|
||||
|
||||
|
@ -24,7 +24,18 @@ const GpxImport: React.FC<{}> = () => {
|
|||
// this will then display a text file
|
||||
console.log(fileReader.result);
|
||||
const track = GPX.parse(fileReader.result);
|
||||
dispatch(tracksActions.push(JSON.parse(JSON.stringify(track))));
|
||||
dispatch(
|
||||
tracksActions.push({
|
||||
track: JSON.parse(JSON.stringify(track)),
|
||||
metadata: {
|
||||
lastModified: new Date(file.lastModified).toISOString(),
|
||||
importDate: new Date().toISOString(),
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type,
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
|
@ -1,11 +1,31 @@
|
|||
import React from 'react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
|
||||
import { DbContext } from '../../db/db-context-provider';
|
||||
import { lat2tile, lon2tile } from '../../lib/geo';
|
||||
import { zoom0 } from '../../store/map';
|
||||
|
||||
const Track: React.FC<{ track: any }> = (props) => {
|
||||
const trkseg = props.track.trk[0].trkseg[0];
|
||||
const Track: React.FC<{ track: any; id: string }> = (props) => {
|
||||
const dbContext = useContext(DbContext);
|
||||
|
||||
useEffect(() => {
|
||||
const store = dbContext.tracksStore;
|
||||
const checkDb = async () => {
|
||||
store.getItem(props.id).then((value) => {
|
||||
if (value === null) {
|
||||
store.setItem(props.id, props.track).then((value) => {
|
||||
console.log(
|
||||
`Track ${props.id} saved in the ${store.driver()} Database.`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
if (dbContext.ready) {
|
||||
checkDb();
|
||||
}
|
||||
}, [dbContext, props]);
|
||||
|
||||
const trkseg = props.track.track.trk[0].trkseg[0];
|
||||
const d = trkseg.trkpt.reduce(
|
||||
(previous: string, current: any, index: number) => {
|
||||
const action = index === 0 ? 'M' : index === 1 ? 'L' : '';
|
||||
|
|
|
@ -1,33 +1,15 @@
|
|||
import React, { Fragment, useEffect } from 'react';
|
||||
import React, { Fragment, useContext } from 'react';
|
||||
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { Drivers, Storage } from '@ionic/storage';
|
||||
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
|
||||
|
||||
import Track from './track';
|
||||
|
||||
var store: Storage;
|
||||
|
||||
const Tracks: React.FC<{}> = () => {
|
||||
useEffect(() => {
|
||||
store = new Storage({
|
||||
driverOrder: [
|
||||
CordovaSQLiteDriver._driver,
|
||||
Drivers.IndexedDB,
|
||||
Drivers.LocalStorage,
|
||||
],
|
||||
});
|
||||
store
|
||||
.defineDriver(CordovaSQLiteDriver)
|
||||
.then(() => console.log('CordovaSQLiteDriver registered'));
|
||||
}, []);
|
||||
|
||||
const tracks = useSelector((state: { tracks: any }) => state.tracks.tracks);
|
||||
return (
|
||||
<Fragment>
|
||||
{Object.keys(tracks).map((key: any) => (
|
||||
<Track key={key} track={tracks[key]} />
|
||||
<Track key={key} id={key} track={tracks[key]} />
|
||||
))}
|
||||
</Fragment>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import react, { useEffect, useState } from 'react';
|
||||
|
||||
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
|
||||
import localforage from 'localforage';
|
||||
|
||||
const initialDbContext = { ready: false, tracksStore: localforage };
|
||||
export const DbContext = react.createContext(initialDbContext);
|
||||
|
||||
const DbContextProvider: react.FC<{
|
||||
children?: JSX.Element;
|
||||
}> = (props: { children?: JSX.Element }) => {
|
||||
const [store, setStore] = useState(localforage);
|
||||
const [ready, setReady] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const config = {
|
||||
name: 'dyomedea',
|
||||
driver: [
|
||||
CordovaSQLiteDriver._driver,
|
||||
localforage.INDEXEDDB,
|
||||
localforage.WEBSQL,
|
||||
localforage.LOCALSTORAGE,
|
||||
],
|
||||
};
|
||||
const newStore = localforage.createInstance({
|
||||
storeName: 'tracks',
|
||||
...config,
|
||||
});
|
||||
setStore(newStore);
|
||||
setReady(true);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<DbContext.Provider value={{ ready, tracksStore: store }}>
|
||||
{props.children}
|
||||
</DbContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default DbContextProvider;
|
|
@ -1,5 +1,12 @@
|
|||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import {
|
||||
Sha256,
|
||||
Sha512,
|
||||
string_to_bytes,
|
||||
bytes_to_base64,
|
||||
} from '@openpgp/asmcrypto.js';
|
||||
|
||||
interface TracksState {
|
||||
tracks: { [index: string]: any };
|
||||
}
|
||||
|
@ -13,10 +20,29 @@ const tracksSlice = createSlice({
|
|||
initialState: initialTracks,
|
||||
reducers: {
|
||||
add: (state, action) => {
|
||||
state.tracks[action.payload.id] = action.payload.track;
|
||||
const { id, ...data } = action.payload;
|
||||
state.tracks[action.payload.id] = data;
|
||||
},
|
||||
push: (state, action) => {
|
||||
state.tracks[crypto.randomUUID()] = action.payload;
|
||||
const sha = new Sha512();
|
||||
const result = sha
|
||||
.process(string_to_bytes(JSON.stringify(action.payload.track)))
|
||||
.finish().result;
|
||||
var id;
|
||||
if (result === null) {
|
||||
console.log(`Can't hash`);
|
||||
id = crypto.randomUUID();
|
||||
} else {
|
||||
id = bytes_to_base64(result);
|
||||
console.log(`Digest: ${id}`);
|
||||
}
|
||||
if (state.tracks.hasOwnProperty(id)) {
|
||||
console.log('Track had already been imported');
|
||||
} else {
|
||||
state.tracks[id] = {
|
||||
...action.payload,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
|
@ -21,6 +17,10 @@
|
|||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
"src",
|
||||
"node_modules/gpx-parser-builder/src/gpx-parser-builder.d.ts"
|
||||
],
|
||||
"paths": {
|
||||
"crypto": ["node_modules/crypto-browserify"]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue