diff --git a/capacitor.config.ts b/capacitor.config.ts index a2828a6..dd63cc4 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -1,8 +1,8 @@ import { CapacitorConfig } from '@capacitor/cli'; const config: CapacitorConfig = { - appId: 'com.dyomedea.dyomedea2', - appName: 'dyomedea2', + appId: 'io.ionic.starter', + appName: 'dyomedeaOl', webDir: 'build', bundledWebRuntime: false }; diff --git a/ionic.config.json b/ionic.config.json index 5d4a201..07e5a6a 100644 --- a/ionic.config.json +++ b/ionic.config.json @@ -1,5 +1,5 @@ { - "name": "dyomedea", + "name": "dyomedeaOl", "integrations": { "capacitor": {} }, diff --git a/package.json b/package.json index c0dca8f..8dfdf9f 100644 --- a/package.json +++ b/package.json @@ -1,55 +1,45 @@ { - "name": "dyomedea", - "version": "0.0.2", + "name": "dyomedeaOl", + "version": "0.0.1", "private": true, "dependencies": { - "@awesome-cordova-plugins/geolocation": "^6.2.0", - "@capacitor/android": "^4.5.0", - "@capacitor/app": "^4.1.1", - "@capacitor/core": "^4.5.0", - "@capacitor/haptics": "^4.1.0", - "@capacitor/keyboard": "^4.1.0", - "@capacitor/status-bar": "^4.1.0", - "@ionic/react": "^6.3.7", - "@ionic/react-router": "^6.3.7", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.4.0", - "@testing-library/user-event": "^14.4.3", - "@types/jest": "^29.2.3", - "@types/node": "^18.11.9", - "@types/react": "^18.0.25", - "@types/react-dom": "^18.0.9", - "@types/react-router": "^5.1.19", - "@types/react-router-dom": "^5.3.3", - "ionicons": "^6.0.4", - "isomorphic-xml2js": "^0.1.3", - "jotai": "^1.10.0", - "jotai-location": "^0.2.0", - "lodash": "^4.17.21", - "pouchdb": "^7.3.1", - "pouchdb-browser": "^7.3.1", - "pouchdb-find": "^7.3.1", + "@capacitor/app": "4.1.1", + "@capacitor/core": "4.5.0", + "@capacitor/haptics": "4.1.0", + "@capacitor/keyboard": "4.1.0", + "@capacitor/status-bar": "4.1.0", + "@ionic/react": "^6.0.0", + "@ionic/react-router": "^6.0.0", + "@testing-library/jest-dom": "^5.11.9", + "@testing-library/react": "^13.3.0", + "@testing-library/user-event": "^12.6.3", + "@types/jest": "^26.0.20", + "@types/node": "^12.19.15", + "@types/react": "^18.0.17", + "@types/react-dom": "^18.0.6", + "@types/react-router": "^5.1.11", + "@types/react-router-dom": "^5.1.7", + "history": "^4.9.0", + "ionicons": "^6.0.3", "react": "^18.2.0", - "react-cool-dimensions": "^2.0.7", "react-dom": "^18.2.0", - "react-localization": "^1.0.19", - "react-router": "^6.4.3", - "react-router-dom": "^6.4.3", - "react-scripts": "^5.0.1", - "typedoc": "^0.23.21", - "typescript": "^4.9.3", - "web-vitals": "^3.1.0", - "workbox-background-sync": "^6.5.4", - "workbox-broadcast-update": "^6.5.4", - "workbox-cacheable-response": "^6.5.4", - "workbox-core": "^6.5.4", - "workbox-expiration": "^6.5.4", - "workbox-navigation-preload": "^6.5.4", - "workbox-precaching": "^6.5.4", - "workbox-range-requests": "^6.5.4", - "workbox-routing": "^6.5.4", - "workbox-strategies": "^6.5.4", - "workbox-streams": "^6.5.4" + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", + "react-scripts": "^5.0.0", + "typescript": "^4.1.3", + "web-vitals": "^0.2.4", + "workbox-background-sync": "^5.1.4", + "workbox-broadcast-update": "^5.1.4", + "workbox-cacheable-response": "^5.1.4", + "workbox-core": "^5.1.4", + "workbox-expiration": "^5.1.4", + "workbox-google-analytics": "^5.1.4", + "workbox-navigation-preload": "^5.1.4", + "workbox-precaching": "^5.1.4", + "workbox-range-requests": "^5.1.4", + "workbox-routing": "^5.1.4", + "workbox-strategies": "^5.1.4", + "workbox-streams": "^5.1.4" }, "scripts": { "start": "react-scripts start", @@ -76,10 +66,7 @@ ] }, "devDependencies": { - "@capacitor/cli": "^4.5.0", - "@ionic/cli": "^6.20.4", - "@types/lodash": "^4.14.189", - "@types/pouchdb": "^6.4.0" + "@capacitor/cli": "4.5.0" }, "description": "An Ionic project" } diff --git a/public/assets/test.svg b/public/assets/test.svg deleted file mode 100644 index ddcc8ed..0000000 --- a/public/assets/test.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/src/App.test.tsx b/src/App.test.tsx index b7b15cb..8c927a8 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -3,6 +3,6 @@ import { render } from '@testing-library/react'; import App from './App'; test('renders without crashing', () => { -// const { baseElement } = render(); -// expect(baseElement).toBeDefined(); + const { baseElement } = render(); + expect(baseElement).toBeDefined(); }); diff --git a/src/App.tsx b/src/App.tsx index b1cf815..6033a6a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,12 +1,7 @@ -import { - IonApp, - IonButtons, - IonContent, - IonFooter, - IonHeader, - IonToolbar, - setupIonicReact, -} from '@ionic/react'; +import { Redirect, Route } from 'react-router-dom'; +import { IonApp, IonRouterOutlet, setupIonicReact } from '@ionic/react'; +import { IonReactRouter } from '@ionic/react-router'; +import Home from './pages/Home'; /* Core CSS required for Ionic components to work properly */ import '@ionic/react/css/core.css'; @@ -27,136 +22,21 @@ import '@ionic/react/css/display.css'; /* Theme variables */ import './theme/variables.css'; -import dispatch from './workers/dispatcher-main'; - -import LiveMap from './components/map/LiveMap'; - -import { atom, useAtom } from 'jotai'; -import { atomWithHash } from 'jotai-location'; -import { MapScope } from './components/map/types'; -import { debounce } from 'lodash'; -import GetLocation from './components/buttons/GetLocation'; -import { geoPoint } from './components/map/types'; -import Back from './components/buttons/Back'; -import Forward from './components/buttons/Forward'; -import CurrentLocation from './components/map/CurrentLocation'; -import GpxImport from './components/dialogs/GpxImport'; -import Gpxes from './components/map/Gpxes'; -import MapChooser from './components/dialogs/MapChooser'; -import Explorer from './components/dialogs/Explorer'; -// import { initDb } from './db'; -// import PouchDB from 'pouchdb'; -// import PouchDBFind from 'pouchdb-find'; -// PouchDB.plugin(PouchDBFind); - setupIonicReact(); -// See https://stackoverflow.com/questions/71538643/property-wakelock-does-not-exist-on-type-navigator -const requestWakeLock = async () => { - const anyNav: any = navigator; - if ('wakeLock' in navigator) { - try { - const wakeLock = await anyNav['wakeLock'].request('screen'); - } catch (err: any) { - // The wake lock request fails - usually system-related, such as low battery. - console.log(`Wake lock request failed: ${err.name}, ${err.message}`); - } - } else { - console.log('No wake lock support here...'); - } -}; - -const handleVisibilityChange = () => { - if (document.hidden) { - console.log('Application hidden'); - } else { - console.log('Application visible'); - requestWakeLock(); - } -}; - -// See https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API -document.addEventListener('visibilitychange', handleVisibilityChange, false); -requestWakeLock(); - -const initialScope: MapScope = { - center: { lat: -37.8403508, lon: 77.5539501 }, - zoom: 13, - tileProvider: 'osm', -}; -const scopeAtom = atomWithHash('scope', initialScope); - -export const setCenterAtom = atom(null, (get, set, center: geoPoint) => { - const previousScope = get(scopeAtom); - const newScope: MapScope = { - ...previousScope, - center: center, - }; - set(scopeAtom, newScope); -}); - -export const tileProviderAtom = atom( - (get) => get(scopeAtom).tileProvider, - (get, set, tileProvider: string) => { - const previousScope = get(scopeAtom); - const newScope: MapScope = { - ...previousScope, - tileProvider, - }; - set(scopeAtom, newScope); - } +const App: React.FC = () => ( + + + + + + + + + + + + ); -// const db = new PouchDB('dyomedea', { auto_compaction: true, revs_limit: 10 }); -// initDb(db); - -dispatch({ action: 'initDb' }); -//dispatch({ action: 'getGpxesForViewport', params: { type: 'tech' } }); -/** - * - * @returns The root app component - */ -const App: React.FC = () => { - const [scope, setScope] = useAtom(scopeAtom); - - console.log(`App, scope: ${JSON.stringify(scope)}`); - return ( - - - - , - , - ]} - /> - - - - - - - - - - - - - - - - - - - - - - - - ); -}; - export default App; diff --git a/src/components/ExploreContainer.css b/src/components/ExploreContainer.css new file mode 100644 index 0000000..e99f514 --- /dev/null +++ b/src/components/ExploreContainer.css @@ -0,0 +1,24 @@ +.container { + text-align: center; + position: absolute; + left: 0; + right: 0; + top: 50%; + transform: translateY(-50%); +} + +.container strong { + font-size: 20px; + line-height: 26px; +} + +.container p { + font-size: 16px; + line-height: 22px; + color: #8c8c8c; + margin: 0; +} + +.container a { + text-decoration: none; +} \ No newline at end of file diff --git a/src/components/ExploreContainer.tsx b/src/components/ExploreContainer.tsx new file mode 100644 index 0000000..1b4b3c0 --- /dev/null +++ b/src/components/ExploreContainer.tsx @@ -0,0 +1,14 @@ +import './ExploreContainer.css'; + +interface ContainerProps { } + +const ExploreContainer: React.FC = () => { + return ( +
+ Ready to create an app? +

Start with Ionic UI Components

+
+ ); +}; + +export default ExploreContainer; diff --git a/src/components/buttons/Back.tsx b/src/components/buttons/Back.tsx deleted file mode 100644 index 0d8cf03..0000000 --- a/src/components/buttons/Back.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import react from 'react'; -import { IonButton, IonIcon } from '@ionic/react'; -import { arrowBackCircleOutline } from 'ionicons/icons'; -import './BackForward.css'; - -export interface BackProperties {} - -export const Back: react.FC = (props: BackProperties) => { - const onClickHandler = (event: any) => { - window.history.back(); - }; - - return ( - - - - ); -}; - -export default Back; diff --git a/src/components/buttons/BackForward.css b/src/components/buttons/BackForward.css deleted file mode 100644 index 045043c..0000000 --- a/src/components/buttons/BackForward.css +++ /dev/null @@ -1,5 +0,0 @@ -ion-button.back-forward { - --opacity: 0.6; - --ion-background-color: white; - --ionicon-stroke-width: 48px; -} diff --git a/src/components/buttons/Forward.tsx b/src/components/buttons/Forward.tsx deleted file mode 100644 index ea4f453..0000000 --- a/src/components/buttons/Forward.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import react from 'react'; -import { IonButton, IonIcon } from '@ionic/react'; -import { arrowForwardCircleOutline } from 'ionicons/icons'; -import './BackForward.css'; - -export interface ForwardProperties {} - -export const Forward: react.FC = (props: ForwardProperties) => { - const onClickHandler = (event: any) => { - window.history.forward(); - }; - - return ( - - - - ); -}; - -export default Forward; diff --git a/src/components/buttons/GetLocation.css b/src/components/buttons/GetLocation.css deleted file mode 100644 index 22d4564..0000000 --- a/src/components/buttons/GetLocation.css +++ /dev/null @@ -1,6 +0,0 @@ -ion-button.get-location { - --opacity: 0.6; - --ion-background-color: white; - margin-left: calc(50% - 20px); -} - diff --git a/src/components/buttons/GetLocation.tsx b/src/components/buttons/GetLocation.tsx deleted file mode 100644 index 27195aa..0000000 --- a/src/components/buttons/GetLocation.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; - -import { Geolocation } from '@awesome-cordova-plugins/geolocation'; - -import './GetLocation.css'; -import { IonButton, IonIcon } from '@ionic/react'; -import { locateOutline } from 'ionicons/icons'; -import { useAtom } from 'jotai'; -import { setCenterAtom } from '../../App'; -import { locationAtom } from '../map/CurrentLocation'; - -const GetLocation: React.FC<{}> = () => { - const [, setCenter] = useAtom(setCenterAtom); - const [, setLocation] = useAtom(locationAtom); - - const onClickHandler = (event: any) => { - console.log('Click handler'); - Geolocation.getCurrentPosition().then((position) => { - console.log( - `Click handler, position: ${position.coords.latitude}, ${position.coords.longitude}` - ); - setCenter({ - lat: position.coords.latitude, - lon: position.coords.longitude, - }); - setLocation({ - lat: position.coords.latitude, - lon: position.coords.longitude, - }); - }); - }; - - return ( - - - - ); -}; - -export default GetLocation; diff --git a/src/components/dialogs/Explorer.tsx b/src/components/dialogs/Explorer.tsx deleted file mode 100644 index dd5aea5..0000000 --- a/src/components/dialogs/Explorer.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { - IonModal, - IonToolbar, - IonTitle, - IonButtons, - IonButton, - IonContent, - IonList, -} from '@ionic/react'; -import react, { useRef, useState } from 'react'; -import { atom, useAtom } from 'jotai'; -import i18n from '../../i18n'; - -import cssDialog from './dialogs.module.css'; - -export interface ExplorerProperties {} - -export const isOpenAtom = atom(false); - -export const Explorer: react.FC = ( - props: ExplorerProperties -) => { - const modal = useRef(null); - const [isOpen, setIsOpen] = useAtom(isOpenAtom); - - const dismiss = () => { - setIsOpen(false); - }; - - return ( - - - {i18n.explorer.nearBy} - - {i18n.common.close} - - - - - - - ); -}; - -export default Explorer; diff --git a/src/components/dialogs/GpxImport.module.css b/src/components/dialogs/GpxImport.module.css deleted file mode 100644 index 440c9c1..0000000 --- a/src/components/dialogs/GpxImport.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.inputFile { - width: 0.1px; - height: 0.1px; - opacity: 0; - overflow: hidden; - position: absolute; - z-index: -1; -} \ No newline at end of file diff --git a/src/components/dialogs/GpxImport.tsx b/src/components/dialogs/GpxImport.tsx deleted file mode 100644 index bcb577b..0000000 --- a/src/components/dialogs/GpxImport.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; - -import GPX from '../../lib/gpx-parser-builder/src/gpx'; - -import css from './GpxImport.module.css'; -import { IonIcon, IonItem } from '@ionic/react'; -import { cloudUpload } from 'ionicons/icons'; -import { findStartTime } from '../../lib/gpx'; -import dispatch from '../../workers/dispatcher-main'; -import { intToGpxId } from '../../lib/ids'; - -const GpxImport: React.FC<{}> = () => { - const onChangeHandler = (event: any) => { - console.log('On change handler'); - const file: File = event.target.files[0]; - const fileReader = new FileReader(); - fileReader.readAsText(file); - - fileReader.addEventListener( - 'load', - () => { - // this will then display a text file - console.log(fileReader.result); - const gpx = GPX.parse(fileReader.result); - console.log(`gpx: ${JSON.stringify(gpx)}`); - const startTime = new Date(findStartTime(gpx)!); - dispatch({ - action: 'pruneAndSaveImportedGpx', - params: { - id: { gpx: intToGpxId(startTime.valueOf()) }, - gpx: gpx, - tech: { - lastModified: new Date(file.lastModified).toISOString(), - importDate: new Date().toISOString(), - name: file.name, - size: file.size, - type: file.type, - }, - }, - }); - // pushGpx(db, { - // gpx, - // metadata: { - // lastModified: new Date(file.lastModified).toISOString(), - // importDate: new Date().toISOString(), - // name: file.name, - // size: file.size, - // type: file.type, - // }, - // }); - }, - false - ); - }; - - return ( - - - - - ); -}; - -export default GpxImport; diff --git a/src/components/dialogs/MapChooser.tsx b/src/components/dialogs/MapChooser.tsx deleted file mode 100644 index 3fae7d6..0000000 --- a/src/components/dialogs/MapChooser.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import react, { useRef } from 'react'; - -import { - IonButton, - IonButtons, - IonContent, - IonIcon, - IonItem, - IonLabel, - IonList, - IonModal, - IonRadio, - IonRadioGroup, - IonTitle, - IonToolbar, -} from '@ionic/react'; -import { layersOutline } from 'ionicons/icons'; -import { nonFakeTileProviders } from '../map/tile-providers'; -import { tileProviderAtom } from '../../App'; -import i18n from '../../i18n/index'; -import { useAtom } from 'jotai'; - -import cssDialog from './dialogs.module.css'; - -export interface MapChooserProperties {} - -export const MapChooser: react.FC = ( - props: MapChooserProperties -) => { - const modal = useRef(null); - - const dismiss = () => { - modal.current?.dismiss(); - }; - - const [tileProvider, setTileProvider] = useAtom(tileProviderAtom); - - const changeHandler = (event: any) => { - setTileProvider(event.detail.value); - dismiss(); - }; - - return ( - <> - - - - - - {i18n.mapChooser.chooseYourMap} - - dismiss()}>{i18n.common.close} - - - - - - {Object.keys(nonFakeTileProviders).map((provider) => { - return ( - - {nonFakeTileProviders[provider].name} - - - ); - })} - - - - - - ); -}; - -export default MapChooser; diff --git a/src/components/dialogs/dialogs.module.css b/src/components/dialogs/dialogs.module.css deleted file mode 100644 index a5d5493..0000000 --- a/src/components/dialogs/dialogs.module.css +++ /dev/null @@ -1,15 +0,0 @@ -.modal { - --height: 100%; - --border-radius: 16px; - --box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), - 0 4px 6px -4px rgb(0 0 0 / 0.1); -} - -.modal ion-toolbar { - --background: rgba(14, 116, 144, 0.7); - --color: white; -} - -.modal ion-content { - background-color: rgba(255, 255, 255, 0.7); -} diff --git a/src/components/map/CurrentLocation.tsx b/src/components/map/CurrentLocation.tsx deleted file mode 100644 index 022cca3..0000000 --- a/src/components/map/CurrentLocation.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { atom, useAtom } from 'jotai'; -import react from 'react'; -import Marker from './Marker'; -import { geoPoint, Rectangle, TileKeyObject } from './types'; - -export interface CurrentLocationProperties { - keyObject?: TileKeyObject; - zoom?: number; - viewPort?: Rectangle; -} - -const initialLocation: geoPoint | null = null; -export const locationAtom = atom(initialLocation); - -export const CurrentLocation: react.FC = ( - props: CurrentLocationProperties -) => { - const [location] = useAtom(locationAtom); - console.log( - `Rendering CurrentLocation, location:${JSON.stringify(location)}` - ); - - return location !== null ? ( - - } - keyObject={props.keyObject} - zoom={props.zoom} - viewPort={props.viewPort} - /> - ) : null; -}; - -export default CurrentLocation; diff --git a/src/components/map/Gpx.tsx b/src/components/map/Gpx.tsx deleted file mode 100644 index 141e66a..0000000 --- a/src/components/map/Gpx.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import react, { startTransition, useEffect, useState } from 'react'; -import dispatch from '../../workers/dispatcher-main'; -import Trk from './Trk'; -import { TileKeyObject, Rectangle } from './types'; -import getUri from '../../lib/ids'; - -export interface GpxProperties { - id: string; - keyObject: TileKeyObject; - zoom: number; - viewPort: Rectangle; -} - -export const Gpx: react.FC = (props: GpxProperties) => { - const [gpx, setGpx] = useState([]); - useEffect(() => { - const getGpx = async () => { - const gpx = await dispatch({ - action: 'getGpx', - params: { - id: props.id, - }, - }); - console.log(`, gpx: ${JSON.stringify(gpx)}`); - startTransition(() => setGpx(gpx)); - }; - getGpx(); - }, [props.id]); - - return ( - - {gpx - .filter((row: any) => row.doc.type === 'trk') - .map((row: any) => ( - - ))} - - ); -}; - -export default Gpx; diff --git a/src/components/map/Gpxes.tsx b/src/components/map/Gpxes.tsx deleted file mode 100644 index 5f435ea..0000000 --- a/src/components/map/Gpxes.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import react, { startTransition, useEffect, useState } from 'react'; -import dispatch from '../../workers/dispatcher-main'; -import Gpx from './Gpx'; -import { TileKeyObject, Rectangle } from './types'; - -export interface GpxesProperties { - keyObject?: TileKeyObject; - zoom?: number; - viewPort?: Rectangle; -} - -export const Gpxes: react.FC = (props: GpxesProperties) => { - const [visibleGpxes, setVisibleGpxes] = useState([]); - useEffect(() => { - const getVisibleGpxes = async () => { - const gpxes = await dispatch({ - action: 'getGpxesForViewport', - params: { - viewport: props.viewPort, - zoomLevel: props.keyObject?.zoomLevel, - }, - }); - console.log(`Gpxes, visibles: ${JSON.stringify(gpxes)}`); - startTransition(() => setVisibleGpxes(gpxes)); - }; - if (props.viewPort !== undefined) { - getVisibleGpxes(); - } - }, [ - props.viewPort?.bottomRight.x, - props.viewPort?.bottomRight.y, - props.viewPort?.topLeft.x, - props.viewPort?.topLeft.y, - props.keyObject?.zoomLevel, - ]); - return ( - <> - {visibleGpxes.map((id: string) => ( - - ))} - - ); -}; - -export default Gpxes; diff --git a/src/components/map/Handler.css b/src/components/map/Handler.css deleted file mode 100644 index f72bca6..0000000 --- a/src/components/map/Handler.css +++ /dev/null @@ -1,5 +0,0 @@ -.handler { - position: fixed; - height: 100%; - width: 100%; -} diff --git a/src/components/map/Handlers.test.tsx b/src/components/map/Handlers.test.tsx deleted file mode 100644 index 77d9eb3..0000000 --- a/src/components/map/Handlers.test.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import { createEvent, fireEvent, render, screen } from '@testing-library/react'; -import { Handlers } from './Handlers'; -import { Transformation } from './LiveMap'; -import { Point } from './types'; -describe('The Handlers component ', () => { - test('is just an empty div', () => { - const transformMap = (t: Transformation) => {}; - render(); - // screen.debug(); - const handlers = screen.getByRole('presentation'); - // screen.debug(); - expect(handlers).toMatchInlineSnapshot(` -