forked from MapComplete/MapComplete
Refactoring: split 'ThemeViewState' into many classes
This commit is contained in:
parent
2b858bd2aa
commit
dbcbf2787d
34 changed files with 1503 additions and 1227 deletions
|
|
@ -2,18 +2,17 @@ import { QueryParameters } from "../Web/QueryParameters"
|
|||
import { BBox } from "../BBox"
|
||||
import Constants from "../../Models/Constants"
|
||||
import { GeoLocationState } from "../State/GeoLocationState"
|
||||
import { UIEventSource } from "../UIEventSource"
|
||||
import { Store, UIEventSource } from "../UIEventSource"
|
||||
import { Feature, LineString, Point } from "geojson"
|
||||
import { FeatureSource, WritableFeatureSource } from "../FeatureSource/FeatureSource"
|
||||
import { LocalStorageSource } from "../Web/LocalStorageSource"
|
||||
import { GeoOperations } from "../GeoOperations"
|
||||
import { OsmTags } from "../../Models/OsmFeature"
|
||||
import StaticFeatureSource, {
|
||||
WritableStaticFeatureSource,
|
||||
} from "../FeatureSource/Sources/StaticFeatureSource"
|
||||
import StaticFeatureSource, { WritableStaticFeatureSource } from "../FeatureSource/Sources/StaticFeatureSource"
|
||||
import { MapProperties } from "../../Models/MapProperties"
|
||||
import { Orientation } from "../../Sensors/Orientation"
|
||||
;("use strict")
|
||||
|
||||
("use strict")
|
||||
/**
|
||||
* The geolocation-handler takes a map-location and a geolocation state.
|
||||
* It'll move the map as appropriate given the state of the geolocation-API
|
||||
|
|
@ -45,14 +44,14 @@ export default class GeoLocationHandler {
|
|||
public readonly mapHasMoved: UIEventSource<Date | undefined> = new UIEventSource<
|
||||
Date | undefined
|
||||
>(undefined)
|
||||
private readonly selectedElement: UIEventSource<Feature>
|
||||
private readonly mapProperties?: MapProperties
|
||||
private readonly selectedElement: Store<object>
|
||||
private readonly mapProperties: MapProperties
|
||||
private readonly gpsLocationHistoryRetentionTime?: UIEventSource<number>
|
||||
|
||||
constructor(
|
||||
geolocationState: GeoLocationState,
|
||||
selectedElement: UIEventSource<Feature>,
|
||||
mapProperties?: MapProperties,
|
||||
selectedElement: Store<object>,
|
||||
mapProperties: MapProperties,
|
||||
gpsLocationHistoryRetentionTime?: UIEventSource<number>
|
||||
) {
|
||||
this.geolocationState = geolocationState
|
||||
|
|
@ -62,7 +61,7 @@ export default class GeoLocationHandler {
|
|||
this.gpsLocationHistoryRetentionTime = gpsLocationHistoryRetentionTime
|
||||
// Did an interaction move the map?
|
||||
const initTime = new Date()
|
||||
mapLocation.addCallbackD(() => {
|
||||
mapLocation?.addCallbackD(() => {
|
||||
if (new Date().getTime() - initTime.getTime() < 250) {
|
||||
return
|
||||
}
|
||||
|
|
@ -139,7 +138,7 @@ export default class GeoLocationHandler {
|
|||
}
|
||||
}
|
||||
|
||||
mapLocation.setData({
|
||||
mapLocation?.setData({
|
||||
lon: newLocation.longitude,
|
||||
lat: newLocation.latitude,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { BBox } from "../BBox"
|
||||
import { Store } from "../UIEventSource"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import Constants from "../../Models/Constants"
|
||||
import { WithChangesState } from "../../Models/ThemeViewState/WithChangesState"
|
||||
|
||||
export type FeatureViewState =
|
||||
| "no-data"
|
||||
|
|
@ -11,7 +11,7 @@ export type FeatureViewState =
|
|||
export default class NoElementsInViewDetector {
|
||||
public readonly hasFeatureInView: Store<FeatureViewState>
|
||||
|
||||
constructor(themeViewState: ThemeViewState) {
|
||||
constructor(themeViewState: WithChangesState) {
|
||||
const state = themeViewState
|
||||
const minZoom = Math.min(
|
||||
...themeViewState.theme.layers
|
||||
|
|
@ -32,7 +32,6 @@ export default class NoElementsInViewDetector {
|
|||
return "zoom-to-low"
|
||||
}
|
||||
|
||||
let minzoomWithData = 9999
|
||||
|
||||
for (const [layerName, source] of themeViewState.perLayerFiltered) {
|
||||
if (priviliged.has(layerName)) {
|
||||
|
|
@ -45,7 +44,6 @@ export default class NoElementsInViewDetector {
|
|||
}
|
||||
const layer = themeViewState.theme.getLayer(layerName)
|
||||
if (mapProperties.zoom.data < layer.minzoom) {
|
||||
minzoomWithData = Math.min(layer.minzoom)
|
||||
continue
|
||||
}
|
||||
if (!state.layerState.filteredLayers.get(layerName).isDisplayed.data) {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
import SimpleMetaTagger from "../SimpleMetaTagger"
|
||||
import { OsmTags } from "../../Models/OsmFeature"
|
||||
import { Utils } from "../../Utils"
|
||||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import { BBox } from "../BBox"
|
||||
import { Feature } from "geojson"
|
||||
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
|
||||
import { Changes } from "../Osm/Changes"
|
||||
import ThemeConfig from "../../Models/ThemeConfig/ThemeConfig"
|
||||
import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore"
|
||||
import { WithChangesState } from "../../Models/ThemeViewState/WithChangesState"
|
||||
|
||||
export default class SelectedElementTagsUpdater {
|
||||
private static readonly metatags = new Set([
|
||||
|
|
@ -18,9 +20,9 @@ export default class SelectedElementTagsUpdater {
|
|||
"uid",
|
||||
"id",
|
||||
])
|
||||
private readonly state: ThemeViewState
|
||||
private readonly state: WithChangesState
|
||||
|
||||
constructor(state: ThemeViewState) {
|
||||
constructor(state: WithChangesState) {
|
||||
this.state = state
|
||||
state.osmConnection.isLoggedIn.addCallbackAndRun((isLoggedIn) => {
|
||||
if (!isLoggedIn && !Utils.runningFromConsole) {
|
||||
|
|
@ -32,7 +34,11 @@ export default class SelectedElementTagsUpdater {
|
|||
})
|
||||
}
|
||||
|
||||
public static applyUpdate(latestTags: OsmTags, id: string, state: SpecialVisualizationState) {
|
||||
public static applyUpdate(latestTags: OsmTags, id: string, state: {
|
||||
theme: ThemeConfig,
|
||||
changes: Changes,
|
||||
featureProperties: FeaturePropertiesStore
|
||||
}) {
|
||||
try {
|
||||
const leftRightSensitive = state.theme.isLeftRightSensitive()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ import { OsmId } from "../../../Models/OsmFeature"
|
|||
import { GeoOperations } from "../../GeoOperations"
|
||||
import { IndexedFeatureSource } from "../FeatureSource"
|
||||
import OsmObjectDownloader from "../../Osm/OsmObjectDownloader"
|
||||
import { SpecialVisualizationState } from "../../../UI/SpecialVisualization"
|
||||
import SelectedElementTagsUpdater from "../../Actors/SelectedElementTagsUpdater"
|
||||
import FeaturePropertiesStore from "../Actors/FeaturePropertiesStore"
|
||||
import ThemeConfig from "../../../Models/ThemeConfig/ThemeConfig"
|
||||
import { Changes } from "../../Osm/Changes"
|
||||
import { WithChangesState } from "../../../Models/ThemeViewState/WithChangesState"
|
||||
|
||||
/**
|
||||
* Generates the favourites from the preferences and marks them as favourite
|
||||
|
|
@ -22,7 +25,7 @@ export default class FavouritesFeatureSource extends StaticFeatureSource {
|
|||
*/
|
||||
public readonly allFavourites: Store<Feature[]>
|
||||
|
||||
constructor(state: SpecialVisualizationState) {
|
||||
constructor(state: WithChangesState) {
|
||||
const features: Store<Feature[]> = Stores.ListStabilized(
|
||||
state.osmConnection.preferencesHandler.allPreferences.map((prefs) => {
|
||||
const feats: Feature[] = []
|
||||
|
|
@ -71,7 +74,7 @@ export default class FavouritesFeatureSource extends StaticFeatureSource {
|
|||
|
||||
this.allFavourites.addCallbackD((features) => {
|
||||
for (const feature of features) {
|
||||
this.updateFeature(feature, state.osmObjectDownloader, state)
|
||||
this.updateFeature(feature, state)
|
||||
}
|
||||
|
||||
return true
|
||||
|
|
@ -80,11 +83,15 @@ export default class FavouritesFeatureSource extends StaticFeatureSource {
|
|||
|
||||
private async updateFeature(
|
||||
feature: Feature,
|
||||
osmObjectDownloader: OsmObjectDownloader,
|
||||
state: SpecialVisualizationState
|
||||
state: {
|
||||
theme: ThemeConfig,
|
||||
changes: Changes,
|
||||
featureProperties: FeaturePropertiesStore,
|
||||
osmObjectDownloader: OsmObjectDownloader,
|
||||
}
|
||||
) {
|
||||
const id = feature.properties.id
|
||||
const upstream = await osmObjectDownloader.DownloadObjectAsync(id)
|
||||
const upstream = await state.osmObjectDownloader.DownloadObjectAsync(id)
|
||||
if (upstream === "deleted") {
|
||||
this.removeFavourite(feature)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export class Changes {
|
|||
|
||||
constructor(
|
||||
state: {
|
||||
featureSwitches: {
|
||||
featureSwitches?: {
|
||||
featureSwitchMorePrivacy?: Store<boolean>
|
||||
featureSwitchIsTesting?: Store<boolean>
|
||||
}
|
||||
|
|
@ -56,8 +56,7 @@ export class Changes {
|
|||
historicalUserLocations?: FeatureSource
|
||||
allElements?: IndexedFeatureSource
|
||||
},
|
||||
leftRightSensitive: boolean = false,
|
||||
reportError?: (string: string | Error, extramessage?: string) => void
|
||||
leftRightSensitive: boolean = false
|
||||
) {
|
||||
this._leftRightSensitive = leftRightSensitive
|
||||
// We keep track of all changes just as well
|
||||
|
|
@ -73,7 +72,7 @@ export class Changes {
|
|||
}
|
||||
this.state = state
|
||||
this.backend = state.osmConnection.Backend()
|
||||
this._reportError = reportError
|
||||
this._reportError = state.reportError
|
||||
this._changesetHandler = new ChangesetHandler(
|
||||
state.featureSwitches?.featureSwitchIsTesting ?? new ImmutableStore(false),
|
||||
state.osmConnection,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { Store, UIEventSource } from "../UIEventSource"
|
||||
import GeocodingProvider, { GeocodingOptions, GeocodeResult } from "./GeocodingProvider"
|
||||
import GeocodingProvider, { GeocodeResult, GeocodingOptions } from "./GeocodingProvider"
|
||||
import { OsmId } from "../../Models/OsmFeature"
|
||||
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
|
||||
import { Utils } from "../../Utils"
|
||||
import OsmObjectDownloader from "../Osm/OsmObjectDownloader"
|
||||
|
||||
export default class OpenStreetMapIdSearch implements GeocodingProvider {
|
||||
private static readonly regex =
|
||||
|
|
@ -13,11 +13,11 @@ export default class OpenStreetMapIdSearch implements GeocodingProvider {
|
|||
w: "way",
|
||||
r: "relation",
|
||||
}
|
||||
private readonly _osmObjectDownloader: OsmObjectDownloader
|
||||
|
||||
private readonly _state: SpecialVisualizationState
|
||||
|
||||
constructor(state: SpecialVisualizationState) {
|
||||
this._state = state
|
||||
constructor(osmObjectDownloader: OsmObjectDownloader) {
|
||||
this._osmObjectDownloader = osmObjectDownloader
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,7 +49,7 @@ export default class OpenStreetMapIdSearch implements GeocodingProvider {
|
|||
|
||||
private async getInfoAbout(id: OsmId): Promise<GeocodeResult> {
|
||||
const [osm_type, osm_id] = id.split("/")
|
||||
const obj = await this._state.osmObjectDownloader.DownloadObjectAsync(id)
|
||||
const obj = await this._osmObjectDownloader.DownloadObjectAsync(id)
|
||||
if (obj === "deleted") {
|
||||
return {
|
||||
display_name: id + " was deleted",
|
||||
|
|
@ -74,13 +74,13 @@ export default class OpenStreetMapIdSearch implements GeocodingProvider {
|
|||
}
|
||||
}
|
||||
|
||||
async search(query: string, options?: GeocodingOptions): Promise<GeocodeResult[]> {
|
||||
async search(query: string, _: GeocodingOptions): Promise<GeocodeResult[]> {
|
||||
if (!isNaN(Number(query))) {
|
||||
const n = Number(query)
|
||||
return Utils.NoNullInplace(
|
||||
await Promise.all([
|
||||
this.getInfoAbout(`node/${n}`).catch((x) => undefined),
|
||||
this.getInfoAbout(`way/${n}`).catch((x) => undefined),
|
||||
this.getInfoAbout(`node/${n}`).catch(() => undefined),
|
||||
this.getInfoAbout(`way/${n}`).catch(() => undefined),
|
||||
this.getInfoAbout(`relation/${n}`).catch(() => undefined),
|
||||
])
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,9 +39,9 @@ export default class SearchState {
|
|||
new LocalElementSearch(state, 5),
|
||||
new CoordinateSearch(),
|
||||
new OpenLocationCodeSearch(),
|
||||
new OpenStreetMapIdSearch(state),
|
||||
new OpenStreetMapIdSearch(state.osmObjectDownloader),
|
||||
new PhotonSearch(true, 2),
|
||||
new PhotonSearch(),
|
||||
new PhotonSearch()
|
||||
// new NominatimGeocoding(),
|
||||
]
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ export default class SearchState {
|
|||
|
||||
const layersToShow = payload.map((fsr) => fsr.layer.id)
|
||||
console.log("Layers to show are", layersToShow)
|
||||
for (const [name, otherLayer] of state.layerState.filteredLayers) {
|
||||
for (const otherLayer of state.layerState.filteredLayers.values()) {
|
||||
const layer = otherLayer.layerDef
|
||||
if (!layer.isNormal()) {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import FeatureSwitchState from "./FeatureSwitchState"
|
|||
import Constants from "../../Models/Constants"
|
||||
import { QueryParameters } from "../Web/QueryParameters"
|
||||
import { ThemeMetaTagging } from "./UserSettingsMetaTagging"
|
||||
import { MapProperties } from "../../Models/MapProperties"
|
||||
import Showdown from "showdown"
|
||||
import { LocalStorageSource } from "../Web/LocalStorageSource"
|
||||
import { GeocodeResult } from "../Search/GeocodingProvider"
|
||||
|
|
@ -53,7 +52,7 @@ export class OptionallySyncedHistory<T> {
|
|||
))
|
||||
this.syncPreference.addCallback((syncmode) => {
|
||||
if (syncmode === "sync") {
|
||||
let list = [...thisSession.data, ...synced.data].slice(0, maxHistory)
|
||||
const list = [...thisSession.data, ...synced.data].slice(0, maxHistory)
|
||||
if (this._isSame) {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
for (let j = i + 1; j < list.length; j++) {
|
||||
|
|
@ -178,7 +177,6 @@ export default class UserRelatedState {
|
|||
* Note: these are linked via OsmConnection.preferences which exports all preferences as UIEventSource
|
||||
*/
|
||||
public readonly preferencesAsTags: UIEventSource<Record<string, string>>
|
||||
private readonly _mapProperties: MapProperties
|
||||
|
||||
public readonly recentlyVisitedThemes: OptionallySyncedHistory<string>
|
||||
public readonly recentlyVisitedSearch: OptionallySyncedHistory<GeocodeResult>
|
||||
|
|
@ -187,10 +185,9 @@ export default class UserRelatedState {
|
|||
osmConnection: OsmConnection,
|
||||
layout?: ThemeConfig,
|
||||
featureSwitches?: FeatureSwitchState,
|
||||
mapProperties?: MapProperties
|
||||
currentRasterLayer?: Store<{ properties: { id: string } }>
|
||||
) {
|
||||
this.osmConnection = osmConnection
|
||||
this._mapProperties = mapProperties
|
||||
|
||||
this.showAllQuestionsAtOnce = UIEventSource.asBoolean(
|
||||
this.osmConnection.getPreference("show-all-questions", "false")
|
||||
|
|
@ -224,7 +221,7 @@ export default class UserRelatedState {
|
|||
this.translationMode = this.initTranslationMode()
|
||||
this.homeLocation = this.initHomeLocation()
|
||||
|
||||
this.preferencesAsTags = this.initAmendedPrefs(layout, featureSwitches)
|
||||
this.preferencesAsTags = this.initAmendedPrefs(layout, featureSwitches, currentRasterLayer)
|
||||
|
||||
this.recentlyVisitedThemes = new OptionallySyncedHistory<string>(
|
||||
"theme",
|
||||
|
|
@ -405,7 +402,8 @@ export default class UserRelatedState {
|
|||
* */
|
||||
private initAmendedPrefs(
|
||||
layout?: ThemeConfig,
|
||||
featureSwitches?: FeatureSwitchState
|
||||
featureSwitches?: FeatureSwitchState,
|
||||
currentRasterLayer?: Store<{ properties: { id: string } }>
|
||||
): UIEventSource<Record<string, string>> {
|
||||
const amendedPrefs = new UIEventSource<Record<string, string>>({
|
||||
_theme: layout?.id,
|
||||
|
|
@ -541,7 +539,7 @@ export default class UserRelatedState {
|
|||
if (tags[key] === null) {
|
||||
continue
|
||||
}
|
||||
let pref = this.osmConnection.GetPreference(key, undefined, { prefix: "" })
|
||||
const pref = this.osmConnection.GetPreference(key, undefined, { prefix: "" })
|
||||
|
||||
pref.set(tags[key])
|
||||
}
|
||||
|
|
@ -560,7 +558,7 @@ export default class UserRelatedState {
|
|||
}
|
||||
}
|
||||
|
||||
this._mapProperties?.rasterLayer?.addCallbackAndRun((l) => {
|
||||
currentRasterLayer?.addCallbackAndRun((l) => {
|
||||
amendedPrefs.data["__current_background"] = l?.properties?.id
|
||||
amendedPrefs.ping()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,16 @@
|
|||
import ThemeViewState from "../../Models/ThemeViewState"
|
||||
import Hash from "./Hash"
|
||||
import { MenuState } from "../../Models/MenuState"
|
||||
import { IndexedFeatureSource } from "../FeatureSource/FeatureSource"
|
||||
import { Feature } from "geojson"
|
||||
import { UIEventSource } from "../UIEventSource"
|
||||
|
||||
export default class ThemeViewStateHashActor {
|
||||
private readonly _state: ThemeViewState
|
||||
private readonly _state: {
|
||||
indexedFeatures: IndexedFeatureSource,
|
||||
selectedElement: UIEventSource<Feature>,
|
||||
guistate: MenuState,
|
||||
previewedImage: UIEventSource<object>
|
||||
}
|
||||
private isUpdatingHash = false
|
||||
|
||||
public static readonly documentation = [
|
||||
|
|
@ -16,7 +23,7 @@ export default class ThemeViewStateHashActor {
|
|||
"",
|
||||
"The possible hashes are:",
|
||||
"",
|
||||
MenuState.pageNames.map((tab) => "`" + tab + "`").join(","),
|
||||
MenuState.pageNames.map((tab) => "`" + tab + "`").join(",")
|
||||
]
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +35,12 @@ export default class ThemeViewStateHashActor {
|
|||
* As such, we use a change in the hash to close the appropriate windows
|
||||
*
|
||||
*/
|
||||
constructor(state: ThemeViewState) {
|
||||
constructor(state: {
|
||||
indexedFeatures: IndexedFeatureSource,
|
||||
selectedElement: UIEventSource<Feature>,
|
||||
guistate: MenuState,
|
||||
previewedImage: UIEventSource<object>
|
||||
}) {
|
||||
this._state = state
|
||||
|
||||
const hashOnLoad = Hash.hash.data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue