Huge refactoring: split readonly and writable stores

This commit is contained in:
Pieter Vander Vennet 2022-06-05 02:24:14 +02:00
parent 0946d8ac9c
commit 4283b76f36
95 changed files with 819 additions and 625 deletions

View file

@ -1,14 +1,14 @@
import BaseLayer from "../../Models/BaseLayer";
import {UIEventSource} from "../UIEventSource";
import {ImmutableStore, Store, UIEventSource} from "../UIEventSource";
import Loc from "../../Models/Loc";
export interface AvailableBaseLayersObj {
readonly osmCarto: BaseLayer;
layerOverview: BaseLayer[];
AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]>
AvailableLayersAt(location: Store<Loc>): Store<BaseLayer[]>
SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer>;
SelectBestLayerAccordingTo(location: Store<Loc>, preferedCategory: Store<string | string[]>): Store<BaseLayer>;
}
@ -24,12 +24,12 @@ export default class AvailableBaseLayers {
private static implementation: AvailableBaseLayersObj
static AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
return AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? new UIEventSource<BaseLayer[]>([]);
static AvailableLayersAt(location: Store<Loc>): Store<BaseLayer[]> {
return AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? new ImmutableStore<BaseLayer[]>([]);
}
static SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
return AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo(location, preferedCategory) ?? new UIEventSource<BaseLayer>(undefined);
static SelectBestLayerAccordingTo(location: Store<Loc>, preferedCategory: UIEventSource<string | string[]>): Store<BaseLayer> {
return AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo(location, preferedCategory) ?? new ImmutableStore<BaseLayer>(undefined);
}

View file

@ -1,5 +1,5 @@
import BaseLayer from "../../Models/BaseLayer";
import {UIEventSource} from "../UIEventSource";
import {Store, Stores} from "../UIEventSource";
import Loc from "../../Models/Loc";
import {GeoOperations} from "../GeoOperations";
import * as editorlayerindex from "../../assets/editor-layer-index.json";
@ -29,7 +29,7 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
public readonly layerOverview = AvailableBaseLayersImplementation.LoadRasterIndex().concat(AvailableBaseLayersImplementation.LoadProviderIndex());
public readonly globalLayers = this.layerOverview.filter(layer => layer.feature?.geometry === undefined || layer.feature?.geometry === null)
public readonly localLayers = this.layerOverview.filter(layer => layer.feature?.geometry !== undefined && layer.featuer?.geometry !== null)
public readonly localLayers = this.layerOverview.filter(layer => layer.feature?.geometry !== undefined && layer.feature?.geometry !== null)
private static LoadRasterIndex(): BaseLayer[] {
const layers: BaseLayer[] = []
@ -202,8 +202,8 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
});
}
public AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
return UIEventSource.ListStabilized(location.map(
public AvailableLayersAt(location: Store<Loc>): Store<BaseLayer[]> {
return Stores.ListStabilized(location.map(
(currentLocation) => {
if (currentLocation === undefined) {
return this.layerOverview;
@ -212,7 +212,7 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
}));
}
public SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
public SelectBestLayerAccordingTo(location: Store<Loc>, preferedCategory: Store<string | string[]>): Store<BaseLayer> {
return this.AvailableLayersAt(location)
.map(available => {
// First float all 'best layers' to the top
@ -264,7 +264,7 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
if (lon === undefined || lat === undefined) {
return availableLayers.concat(this.globalLayers);
}
const lonlat = [lon, lat];
const lonlat : [number, number] = [lon, lat];
for (const layerOverviewItem of this.localLayers) {
const layer = layerOverviewItem;
const bbox = BBox.get(layer.feature)

View file

@ -1,12 +1,12 @@
import {UIEventSource} from "../UIEventSource";
import {Store, UIEventSource} from "../UIEventSource";
import Svg from "../../Svg";
import {LocalStorageSource} from "../Web/LocalStorageSource";
import {VariableUiElement} from "../../UI/Base/VariableUIElement";
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
import {QueryParameters} from "../Web/QueryParameters";
import FeatureSource from "../FeatureSource/FeatureSource";
import {BBox} from "../BBox";
import Constants from "../../Models/Constants";
import SimpleFeatureSource from "../FeatureSource/Sources/SimpleFeatureSource";
export interface GeoLocationPointProperties {
id: "gps",
@ -22,7 +22,7 @@ export interface GeoLocationPointProperties {
export default class GeoLocationHandler extends VariableUiElement {
private readonly currentLocation?: FeatureSource
private readonly currentLocation?: SimpleFeatureSource
/**
* Wether or not the geolocation is active, aka the user requested the current location
@ -43,7 +43,7 @@ export default class GeoLocationHandler extends VariableUiElement {
* Literally: _currentGPSLocation.data != undefined
* @private
*/
private readonly _hasLocation: UIEventSource<boolean>;
private readonly _hasLocation: Store<boolean>;
private readonly _currentGPSLocation: UIEventSource<Coordinates>;
/**
* Kept in order to update the marker
@ -70,7 +70,7 @@ export default class GeoLocationHandler extends VariableUiElement {
constructor(
state: {
selectedElement: UIEventSource<any>;
currentUserLocation?: FeatureSource,
currentUserLocation?: SimpleFeatureSource,
leafletMap: UIEventSource<any>,
layoutToUse: LayoutConfig,
featureSwitchGeolocation: UIEventSource<boolean>
@ -236,12 +236,9 @@ export default class GeoLocationHandler extends VariableUiElement {
self.currentLocation?.features?.setData([{feature, freshness: new Date()}])
const timeSinceRequest =
(new Date().getTime() - (self._lastUserRequest.data?.getTime() ?? 0)) / 1000;
if (willFocus.data) {
console.log("Zooming to user location: willFocus is set")
willFocus.setData(false)
lastClick.setData(undefined);
autozoomDone = true;
self.MoveToCurrentLocation(16);
} else if (self._isLocked.data) {

View file

@ -1,4 +1,4 @@
import {UIEventSource} from "../UIEventSource";
import {Store, UIEventSource} from "../UIEventSource";
import {Or} from "../Tags/Or";
import {Overpass} from "../Osm/Overpass";
import FeatureSource from "../FeatureSource/FeatureSource";
@ -34,13 +34,13 @@ export default class OverpassFeatureSource implements FeatureSource {
private readonly retries: UIEventSource<number> = new UIEventSource<number>(0);
private readonly state: {
readonly locationControl: UIEventSource<Loc>,
readonly locationControl: Store<Loc>,
readonly layoutToUse: LayoutConfig,
readonly overpassUrl: UIEventSource<string[]>;
readonly overpassTimeout: UIEventSource<number>;
readonly currentBounds: UIEventSource<BBox>
readonly overpassUrl: Store<string[]>;
readonly overpassTimeout: Store<number>;
readonly currentBounds: Store<BBox>
}
private readonly _isActive: UIEventSource<boolean>
private readonly _isActive: Store<boolean>
/**
* Callback to handle all the data
*/
@ -54,16 +54,16 @@ export default class OverpassFeatureSource implements FeatureSource {
constructor(
state: {
readonly locationControl: UIEventSource<Loc>,
readonly locationControl: Store<Loc>,
readonly layoutToUse: LayoutConfig,
readonly overpassUrl: UIEventSource<string[]>;
readonly overpassTimeout: UIEventSource<number>;
readonly overpassMaxZoom: UIEventSource<number>,
readonly currentBounds: UIEventSource<BBox>
readonly overpassUrl: Store<string[]>;
readonly overpassTimeout: Store<number>;
readonly overpassMaxZoom: Store<number>,
readonly currentBounds: Store<BBox>
},
options: {
padToTiles: UIEventSource<number>,
isActive?: UIEventSource<boolean>,
padToTiles: Store<number>,
isActive?: Store<boolean>,
relationTracker: RelationsTracker,
onBboxLoaded?: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void,
freshnesses?: Map<string, TileFreshnessCalculator>

View file

@ -1,5 +1,4 @@
import {UIEventSource} from "../UIEventSource";
import Translations from "../../UI/i18n/Translations";
import {Store, UIEventSource} from "../UIEventSource";
import Locale from "../../UI/i18n/Locale";
import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer";
import Combine from "../../UI/Base/Combine";
@ -9,11 +8,11 @@ import {Utils} from "../../Utils";
export default class TitleHandler {
constructor(state: {
selectedElement: UIEventSource<any>,
selectedElement: Store<any>,
layoutToUse: LayoutConfig,
allElements: ElementStorage
}) {
const currentTitle: UIEventSource<string> = state.selectedElement.map(
const currentTitle: Store<string> = state.selectedElement.map(
selected => {
const layout = state.layoutToUse
const defaultTitle = layout?.title?.txt ?? "MapComplete"