Re-implementing the map chooser
This commit is contained in:
parent
89fbb5d851
commit
9459622a95
|
@ -24,6 +24,7 @@
|
|||
"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",
|
||||
|
|
16
src/App.tsx
16
src/App.tsx
|
@ -32,7 +32,7 @@ import dispatch from './workers/dispatcher-main';
|
|||
import LiveMap from './components/map/LiveMap';
|
||||
|
||||
import { atom, useAtom } from 'jotai';
|
||||
import { atomWithHash } from 'jotai/utils';
|
||||
import { atomWithHash } from 'jotai-location';
|
||||
import { MapScope } from './components/map/types';
|
||||
import { debounce } from 'lodash';
|
||||
import GetLocation from './components/buttons/GetLocation';
|
||||
|
@ -42,6 +42,7 @@ 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 { initDb } from './db';
|
||||
// import PouchDB from 'pouchdb';
|
||||
// import PouchDBFind from 'pouchdb-find';
|
||||
|
@ -93,6 +94,18 @@ export const setCenterAtom = atom(null, (get, set, center: geoPoint) => {
|
|||
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 });
|
||||
// initDb(db);
|
||||
|
||||
|
@ -129,6 +142,7 @@ const App: React.FC = () => {
|
|||
</IonButtons>
|
||||
<IonButtons slot='end'>
|
||||
<GpxImport />
|
||||
<MapChooser />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -133,6 +133,8 @@ export const tileProviders: TileProviders = {
|
|||
},
|
||||
};
|
||||
|
||||
export const { fake, ...nonFakeTileProviders } = tileProviders;
|
||||
|
||||
const mod = (n: number, m: number) => {
|
||||
const jsMod = n % m;
|
||||
return jsMod >= 0 ? jsMod : jsMod + m;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue