Re-implementing the map chooser

This commit is contained in:
Eric van der Vlist 2022-11-21 17:49:09 +01:00
parent 89fbb5d851
commit 9459622a95
6 changed files with 147 additions and 1 deletions

View File

@ -24,6 +24,7 @@
"ionicons": "^6.0.4", "ionicons": "^6.0.4",
"isomorphic-xml2js": "^0.1.3", "isomorphic-xml2js": "^0.1.3",
"jotai": "^1.10.0", "jotai": "^1.10.0",
"jotai-location": "^0.2.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pouchdb": "^7.3.1", "pouchdb": "^7.3.1",
"pouchdb-browser": "^7.3.1", "pouchdb-browser": "^7.3.1",

View File

@ -32,7 +32,7 @@ import dispatch from './workers/dispatcher-main';
import LiveMap from './components/map/LiveMap'; import LiveMap from './components/map/LiveMap';
import { atom, useAtom } from 'jotai'; import { atom, useAtom } from 'jotai';
import { atomWithHash } from 'jotai/utils'; import { atomWithHash } from 'jotai-location';
import { MapScope } from './components/map/types'; import { MapScope } from './components/map/types';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import GetLocation from './components/buttons/GetLocation'; import GetLocation from './components/buttons/GetLocation';
@ -42,6 +42,7 @@ import Forward from './components/buttons/Forward';
import CurrentLocation from './components/map/CurrentLocation'; import CurrentLocation from './components/map/CurrentLocation';
import GpxImport from './components/dialogs/GpxImport'; import GpxImport from './components/dialogs/GpxImport';
import Gpxes from './components/map/Gpxes'; import Gpxes from './components/map/Gpxes';
import MapChooser from './components/dialogs/MapChooser';
// import { initDb } from './db'; // import { initDb } from './db';
// import PouchDB from 'pouchdb'; // import PouchDB from 'pouchdb';
// import PouchDBFind from 'pouchdb-find'; // import PouchDBFind from 'pouchdb-find';
@ -93,6 +94,18 @@ export const setCenterAtom = atom(null, (get, set, center: geoPoint) => {
set(scopeAtom, newScope); 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 db = new PouchDB('dyomedea', { auto_compaction: true, revs_limit: 10 }); // const db = new PouchDB('dyomedea', { auto_compaction: true, revs_limit: 10 });
// initDb(db); // initDb(db);
@ -129,6 +142,7 @@ const App: React.FC = () => {
</IonButtons> </IonButtons>
<IonButtons slot='end'> <IonButtons slot='end'>
<GpxImport /> <GpxImport />
<MapChooser />
</IonButtons> </IonButtons>
</IonToolbar> </IonToolbar>
</IonHeader> </IonHeader>

View File

@ -0,0 +1,78 @@
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<MapChooserProperties> = (
props: MapChooserProperties
) => {
const modal = useRef<HTMLIonModalElement>(null);
const dismiss = () => {
modal.current?.dismiss();
};
const [tileProvider, setTileProvider] = useAtom(tileProviderAtom);
const changeHandler = (event: any) => {
setTileProvider(event.detail.value);
dismiss();
};
return (
<>
<IonButton id='open-TileServerChooser'>
<IonIcon slot='icon-only' icon={layersOutline} />
</IonButton>
<IonModal
trigger='open-TileServerChooser'
ref={modal}
className={cssDialog.modal}
>
<IonToolbar>
<IonTitle>{i18n.mapChooser.chooseYourMap}</IonTitle>
<IonButtons slot='end'>
<IonButton onClick={() => dismiss()}>{i18n.common.close}</IonButton>
</IonButtons>
</IonToolbar>
<IonContent>
<IonList>
<IonRadioGroup value={tileProvider} onIonChange={changeHandler}>
{Object.keys(nonFakeTileProviders).map((provider) => {
return (
<IonItem key={provider}>
<IonLabel> {nonFakeTileProviders[provider].name}</IonLabel>
<IonRadio slot='start' value={provider} />
</IonItem>
);
})}
</IonRadioGroup>
</IonList>
</IonContent>
</IonModal>
</>
);
};
export default MapChooser;

View File

@ -0,0 +1,15 @@
.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);
}

View File

@ -133,6 +133,8 @@ export const tileProviders: TileProviders = {
}, },
}; };
export const { fake, ...nonFakeTileProviders } = tileProviders;
const mod = (n: number, m: number) => { const mod = (n: number, m: number) => {
const jsMod = n % m; const jsMod = n % m;
return jsMod >= 0 ? jsMod : jsMod + m; return jsMod >= 0 ? jsMod : jsMod + m;

36
src/i18n/index.tsx Normal file
View File

@ -0,0 +1,36 @@
import LocalizedStrings from 'react-localization';
const strings = new LocalizedStrings({
en: {
colonize: (input: string): any => strings.formatString('{0}:', input),
common: { save: 'Save', cancel: 'Cancel', close: 'Close' },
mapChooser: {
chooseYourMap: 'Choose your map',
},
},
fr: {
colonize: (input: string): any => strings.formatString('{0} :', input),
common: {
save: 'Sauvegarder',
cancel: 'Annuler',
close: 'Fermer',
},
mapChooser: {
chooseYourMap: 'Choisissez votre carte',
},
},
});
export default strings;
export const setI18nLanguage = (language: string) => {
if (language === undefined || language === 'auto') {
strings.setLanguage(strings.getInterfaceLanguage());
} else {
strings.setLanguage(language);
}
};