Re-implementing the map chooser
This commit is contained in:
parent
89fbb5d851
commit
9459622a95
|
@ -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",
|
||||||
|
|
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 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>
|
||||||
|
|
|
@ -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 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;
|
||||||
|
|
|
@ -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