mirror of
https://github.com/maputnik/editor.git
synced 2026-01-01 11:00:00 +00:00
Migrate all the non react components code to typescript (#847)
This completes the migration to typescript of all the non react components code. The only changes introduced besides types are the type checks using `"something" in object` which narrows down types in typescript.
This commit is contained in:
@@ -9,7 +9,7 @@ import InputUrl from './InputUrl'
|
||||
import {MdFileUpload} from 'react-icons/md'
|
||||
import {MdAddCircleOutline} from 'react-icons/md'
|
||||
|
||||
import style from '../libs/style.js'
|
||||
import style from '../libs/style'
|
||||
import publicStyles from '../config/styles.json'
|
||||
|
||||
class PublicStyle extends React.Component {
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import style from './style.js'
|
||||
import {format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {StyleSpecification, format} from '@maplibre/maplibre-gl-style-spec'
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket'
|
||||
|
||||
export type ApiStyleStoreOptions = {
|
||||
port?: string
|
||||
host?: string
|
||||
onLocalStyleChange?: (style: any) => void
|
||||
}
|
||||
|
||||
export class ApiStyleStore {
|
||||
|
||||
constructor(opts) {
|
||||
localUrl: string;
|
||||
websocketUrl: string;
|
||||
latestStyleId: string | undefined = undefined;
|
||||
onLocalStyleChange: (style: any) => void;
|
||||
|
||||
constructor(opts: ApiStyleStoreOptions) {
|
||||
this.onLocalStyleChange = opts.onLocalStyleChange || (() => {})
|
||||
const port = opts.port || '8000'
|
||||
const host = opts.host || 'localhost'
|
||||
@@ -13,7 +24,7 @@ export class ApiStyleStore {
|
||||
this.init = this.init.bind(this)
|
||||
}
|
||||
|
||||
init(cb) {
|
||||
init(cb: (...args: any[]) => void) {
|
||||
fetch(this.localUrl + '/styles', {
|
||||
mode: 'cors',
|
||||
})
|
||||
@@ -26,7 +37,7 @@ export class ApiStyleStore {
|
||||
this.notifyLocalChanges()
|
||||
cb(null)
|
||||
})
|
||||
.catch(function(e) {
|
||||
.catch(() => {
|
||||
cb(new Error('Can not connect to style API'))
|
||||
})
|
||||
}
|
||||
@@ -47,7 +58,7 @@ export class ApiStyleStore {
|
||||
}
|
||||
}
|
||||
|
||||
latestStyle(cb) {
|
||||
latestStyle(cb: (...args: any[]) => void) {
|
||||
if(this.latestStyleId) {
|
||||
fetch(this.localUrl + '/styles/' + this.latestStyleId, {
|
||||
mode: 'cors',
|
||||
@@ -64,7 +75,7 @@ export class ApiStyleStore {
|
||||
}
|
||||
|
||||
// Save current style replacing previous version
|
||||
save(mapStyle) {
|
||||
save(mapStyle: StyleSpecification & { id: string }) {
|
||||
const styleJSON = format(
|
||||
style.stripAccessTokens(
|
||||
style.replaceAccessTokens(mapStyle)
|
||||
@@ -1,17 +1,20 @@
|
||||
// @ts-ignore
|
||||
import stylegen from 'mapbox-gl-inspect/lib/stylegen'
|
||||
// @ts-ignore
|
||||
import colors from 'mapbox-gl-inspect/lib/colors'
|
||||
import {FilterSpecification,LayerSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||
|
||||
export function colorHighlightedLayer(layer) {
|
||||
export function colorHighlightedLayer(layer: LayerSpecification) {
|
||||
if(!layer || layer.type === 'background' || layer.type === 'raster') return null
|
||||
|
||||
function changeLayer(l) {
|
||||
function changeLayer(l: LayerSpecification & {filter?: FilterSpecification}) {
|
||||
if(l.type === 'circle') {
|
||||
l.paint['circle-radius'] = 3
|
||||
l.paint!['circle-radius'] = 3
|
||||
} else if(l.type === 'line') {
|
||||
l.paint['line-width'] = 2
|
||||
l.paint!['line-width'] = 2
|
||||
}
|
||||
|
||||
if(layer.filter) {
|
||||
if("filter" in layer) {
|
||||
l.filter = layer.filter
|
||||
} else {
|
||||
delete l['filter']
|
||||
@@ -21,8 +24,7 @@ export function colorHighlightedLayer(layer) {
|
||||
}
|
||||
|
||||
const sourceLayerId = layer['source-layer'] || ''
|
||||
const color = colors.brightColor(sourceLayerId, 1)
|
||||
const layers = []
|
||||
const color = colors.brightColor(sourceLayerId, 1);
|
||||
|
||||
if(layer.type === "fill" || layer.type === 'fill-extrusion') {
|
||||
return changeLayer(stylegen.polygonLayer(color, color, layer.source, layer['source-layer']))
|
||||
@@ -1,17 +1,18 @@
|
||||
import {latest} from '@maplibre/maplibre-gl-style-spec'
|
||||
import { LayerSpecification } from 'maplibre-gl'
|
||||
|
||||
export function changeType(layer, newType) {
|
||||
const changedPaintProps = { ...layer.paint }
|
||||
export function changeType(layer: LayerSpecification, newType: string) {
|
||||
const changedPaintProps: LayerSpecification["paint"] = { ...layer.paint }
|
||||
Object.keys(changedPaintProps).forEach(propertyName => {
|
||||
if(!(propertyName in latest['paint_' + newType])) {
|
||||
delete changedPaintProps[propertyName]
|
||||
delete changedPaintProps[propertyName as keyof LayerSpecification["paint"]]
|
||||
}
|
||||
})
|
||||
|
||||
const changedLayoutProps = { ...layer.layout }
|
||||
const changedLayoutProps: LayerSpecification["layout"] = { ...layer.layout }
|
||||
Object.keys(changedLayoutProps).forEach(propertyName => {
|
||||
if(!(propertyName in latest['layout_' + newType])) {
|
||||
delete changedLayoutProps[propertyName]
|
||||
delete changedLayoutProps[propertyName as keyof LayerSpecification["layout"]]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -26,15 +27,15 @@ export function changeType(layer, newType) {
|
||||
/** A {@property} in either the paint our layout {@group} has changed
|
||||
* to a {@newValue}.
|
||||
*/
|
||||
export function changeProperty(layer, group, property, newValue) {
|
||||
export function changeProperty(layer: LayerSpecification, group: keyof LayerSpecification, property: string, newValue: any) {
|
||||
// Remove the property if undefined
|
||||
if(newValue === undefined) {
|
||||
if(group) {
|
||||
const newLayer = {
|
||||
const newLayer: any = {
|
||||
...layer,
|
||||
// Change object so the diff works in ./src/components/map/MaplibreGlMap.jsx
|
||||
[group]: {
|
||||
...layer[group]
|
||||
...layer[group] as any
|
||||
}
|
||||
};
|
||||
delete newLayer[group][property];
|
||||
@@ -45,7 +46,7 @@ export function changeProperty(layer, group, property, newValue) {
|
||||
}
|
||||
return newLayer;
|
||||
} else {
|
||||
const newLayer = {
|
||||
const newLayer: any = {
|
||||
...layer
|
||||
};
|
||||
delete newLayer[property];
|
||||
@@ -57,7 +58,7 @@ export function changeProperty(layer, group, property, newValue) {
|
||||
return {
|
||||
...layer,
|
||||
[group]: {
|
||||
...layer[group],
|
||||
...layer[group] as any,
|
||||
[property]: newValue
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,22 @@
|
||||
import throttle from 'lodash.throttle'
|
||||
import isEqual from 'lodash.isequal'
|
||||
import { Map } from 'maplibre-gl';
|
||||
|
||||
export type LayerWatcherOptions = {
|
||||
onSourcesChange?: (sources: { [sourceId: string]: string[] }) => void;
|
||||
onVectorLayersChange?: (vectorLayers: { [vectorLayerId: string]: { [propertyName: string]: { [propertyValue: string]: {} } } }) => void;
|
||||
}
|
||||
|
||||
/** Listens to map events to build up a store of available vector
|
||||
* layers contained in the tiles */
|
||||
export default class LayerWatcher {
|
||||
constructor(opts = {}) {
|
||||
onSourcesChange: (sources: { [sourceId: string]: string[] }) => void;
|
||||
onVectorLayersChange: (vectorLayers: { [vectorLayerId: string]: { [propertyName: string]: { [propertyValue: string]: {} } } }) => void;
|
||||
throttledAnalyzeVectorLayerFields: (map: any) => void;
|
||||
_sources: { [sourceId: string]: string[] };
|
||||
_vectorLayers: { [vectorLayerId: string]: { [propertyName: string]: { [propertyValue: string]: {} } } };
|
||||
|
||||
constructor(opts: LayerWatcherOptions = {}) {
|
||||
this.onSourcesChange = opts.onSourcesChange || (() => {})
|
||||
this.onVectorLayersChange = opts.onVectorLayersChange || (() => {})
|
||||
|
||||
@@ -17,13 +29,13 @@ export default class LayerWatcher {
|
||||
this.throttledAnalyzeVectorLayerFields = throttle(this.analyzeVectorLayerFields, 5000)
|
||||
}
|
||||
|
||||
analyzeMap(map) {
|
||||
analyzeMap(map: Map) {
|
||||
const previousSources = { ...this._sources }
|
||||
|
||||
Object.keys(map.style.sourceCaches).forEach(sourceId => {
|
||||
//NOTE: This heavily depends on the internal API of Maplibre GL
|
||||
//so this breaks between Maplibre GL JS releases
|
||||
this._sources[sourceId] = map.style.sourceCaches[sourceId]._source.vectorLayerIds
|
||||
this._sources[sourceId] = map.style.sourceCaches[sourceId]._source.vectorLayerIds as string[];
|
||||
})
|
||||
|
||||
if(!isEqual(previousSources, this._sources)) {
|
||||
@@ -33,14 +45,14 @@ export default class LayerWatcher {
|
||||
this.throttledAnalyzeVectorLayerFields(map)
|
||||
}
|
||||
|
||||
analyzeVectorLayerFields(map) {
|
||||
analyzeVectorLayerFields(map: Map) {
|
||||
const previousVectorLayers = { ...this._vectorLayers }
|
||||
|
||||
Object.keys(this._sources).forEach(sourceId => {
|
||||
(this._sources[sourceId] || []).forEach(vectorLayerId => {
|
||||
const knownProperties = this._vectorLayers[vectorLayerId] || {}
|
||||
const params = { sourceLayer: vectorLayerId }
|
||||
map.querySourceFeatures(sourceId, params).forEach(feature => {
|
||||
map.querySourceFeatures(sourceId, params as any).forEach(feature => {
|
||||
Object.keys(feature.properties).forEach(propertyName => {
|
||||
const knownPropertyValues = knownProperties[propertyName] || {}
|
||||
knownPropertyValues[feature.properties[propertyName]] = {}
|
||||
@@ -1,3 +1,3 @@
|
||||
import MapLibreGl from "maplibre-gl"
|
||||
|
||||
MapLibreGl.setRTLTextPlugin('https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js');
|
||||
MapLibreGl.setRTLTextPlugin('https://unpkg.com/@mapbox/mapbox-gl-rtl-text@0.2.3/mapbox-gl-rtl-text.min.js', () => {});
|
||||
@@ -1,6 +1,6 @@
|
||||
import npmurl from 'url'
|
||||
|
||||
function loadJSON(url, defaultValue, cb) {
|
||||
function loadJSON(url: string, defaultValue: any, cb: (...args: any[]) => void) {
|
||||
fetch(url, {
|
||||
mode: 'cors',
|
||||
credentials: "same-origin"
|
||||
@@ -17,7 +17,7 @@ function loadJSON(url, defaultValue, cb) {
|
||||
})
|
||||
}
|
||||
|
||||
export function downloadGlyphsMetadata(urlTemplate, cb) {
|
||||
export function downloadGlyphsMetadata(urlTemplate: string, cb: (...args: any[]) => void) {
|
||||
if(!urlTemplate) return cb([])
|
||||
|
||||
// Special handling because Tileserver GL serves the fontstacks metadata differently
|
||||
@@ -27,14 +27,14 @@ export function downloadGlyphsMetadata(urlTemplate, cb) {
|
||||
if(urlObj.pathname === normPathPart) {
|
||||
urlObj.pathname = '/fontstacks.json';
|
||||
} else {
|
||||
urlObj.pathname = urlObj.pathname.replace(normPathPart, '.json');
|
||||
urlObj.pathname = urlObj.pathname!.replace(normPathPart, '.json');
|
||||
}
|
||||
let url = npmurl.format(urlObj);
|
||||
|
||||
loadJSON(url, [], cb)
|
||||
}
|
||||
|
||||
export function downloadSpriteMetadata(baseUrl, cb) {
|
||||
export function downloadSpriteMetadata(baseUrl: string, cb: (...args: any[]) => void) {
|
||||
if(!baseUrl) return cb([])
|
||||
const url = baseUrl + '.json'
|
||||
loadJSON(url, {}, glyphs => cb(Object.keys(glyphs)))
|
||||
@@ -1,4 +1,10 @@
|
||||
import type {StyleSpecification} from "@maplibre/maplibre-gl-style-spec";
|
||||
|
||||
export class RevisionStore {
|
||||
revisions: StyleSpecification[];
|
||||
currentIdx: number;
|
||||
|
||||
|
||||
constructor(initialRevisions=[]) {
|
||||
this.revisions = initialRevisions
|
||||
this.currentIdx = initialRevisions.length - 1
|
||||
@@ -12,7 +18,7 @@ export class RevisionStore {
|
||||
return this.revisions[this.currentIdx]
|
||||
}
|
||||
|
||||
addRevision(revision) {
|
||||
addRevision(revision: StyleSpecification) {
|
||||
//TODO: compare new revision style id with old ones
|
||||
//and ensure that it is always the same id
|
||||
this.revisions.push(revision)
|
||||
@@ -21,15 +27,15 @@ export class RevisionStore {
|
||||
|
||||
undo() {
|
||||
if(this.currentIdx > 0) {
|
||||
this.currentIdx--
|
||||
this.currentIdx--;
|
||||
}
|
||||
return this.current
|
||||
return this.current;
|
||||
}
|
||||
|
||||
redo() {
|
||||
if(this.currentIdx < this.revisions.length - 1) {
|
||||
this.currentIdx++
|
||||
}
|
||||
return this.current
|
||||
return this.current;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
export function deleteSource(mapStyle, sourceId) {
|
||||
const remainingSources = { ...mapStyle.sources}
|
||||
delete remainingSources[sourceId]
|
||||
return {
|
||||
...mapStyle,
|
||||
sources: remainingSources
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function addSource(mapStyle, sourceId, source) {
|
||||
return changeSource(mapStyle, sourceId, source)
|
||||
}
|
||||
|
||||
export function changeSource(mapStyle, sourceId, source) {
|
||||
const changedSources = {
|
||||
...mapStyle.sources,
|
||||
[sourceId]: source
|
||||
}
|
||||
return {
|
||||
...mapStyle,
|
||||
sources: changedSources
|
||||
}
|
||||
}
|
||||
|
||||
27
src/libs/source.ts
Normal file
27
src/libs/source.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type {StyleSpecification, SourceSpecification} from "@maplibre/maplibre-gl-style-spec";
|
||||
|
||||
export function deleteSource(mapStyle: StyleSpecification, sourceId: string) {
|
||||
const remainingSources = { ...mapStyle.sources}
|
||||
delete remainingSources[sourceId]
|
||||
return {
|
||||
...mapStyle,
|
||||
sources: remainingSources
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function addSource(mapStyle: StyleSpecification, sourceId: string, source: SourceSpecification) {
|
||||
return changeSource(mapStyle, sourceId, source)
|
||||
}
|
||||
|
||||
export function changeSource(mapStyle: StyleSpecification, sourceId: string, source: SourceSpecification) {
|
||||
const changedSources = {
|
||||
...mapStyle.sources,
|
||||
[sourceId]: source
|
||||
}
|
||||
return {
|
||||
...mapStyle,
|
||||
sources: changedSources
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {derefLayers} from '@maplibre/maplibre-gl-style-spec'
|
||||
import {derefLayers, StyleSpecification, LayerSpecification} from '@maplibre/maplibre-gl-style-spec'
|
||||
import tokens from '../config/tokens.json'
|
||||
|
||||
// Empty style is always used if no style could be restored or fetched
|
||||
@@ -9,18 +9,20 @@ const emptyStyle = ensureStyleValidity({
|
||||
})
|
||||
|
||||
function generateId() {
|
||||
return Math.random().toString(36).substr(2, 9)
|
||||
return Math.random().toString(36).substring(2, 9)
|
||||
}
|
||||
|
||||
function ensureHasId(style) {
|
||||
if('id' in style) return style
|
||||
style.id = generateId()
|
||||
return style
|
||||
function ensureHasId(style: StyleSpecification & { id?: string }): StyleSpecification & { id: string } {
|
||||
if(!('id' in style) || !style.id) {
|
||||
style.id = generateId();
|
||||
return style as StyleSpecification & { id: string };
|
||||
}
|
||||
return style as StyleSpecification & { id: string };
|
||||
}
|
||||
|
||||
function ensureHasNoInteractive(style) {
|
||||
function ensureHasNoInteractive(style: StyleSpecification & {id: string}) {
|
||||
const changedLayers = style.layers.map(layer => {
|
||||
const changedLayer = { ...layer }
|
||||
const changedLayer: LayerSpecification & { interactive?: any } = { ...layer }
|
||||
delete changedLayer.interactive
|
||||
return changedLayer
|
||||
})
|
||||
@@ -31,18 +33,18 @@ function ensureHasNoInteractive(style) {
|
||||
}
|
||||
}
|
||||
|
||||
function ensureHasNoRefs(style) {
|
||||
function ensureHasNoRefs(style: StyleSpecification & {id: string}) {
|
||||
return {
|
||||
...style,
|
||||
layers: derefLayers(style.layers)
|
||||
}
|
||||
}
|
||||
|
||||
function ensureStyleValidity(style) {
|
||||
function ensureStyleValidity(style: StyleSpecification): StyleSpecification & { id: string } {
|
||||
return ensureHasNoInteractive(ensureHasNoRefs(ensureHasId(style)))
|
||||
}
|
||||
|
||||
function indexOfLayer(layers, layerId) {
|
||||
function indexOfLayer(layers: LayerSpecification[], layerId: string) {
|
||||
for (let i = 0; i < layers.length; i++) {
|
||||
if(layers[i].id === layerId) {
|
||||
return i
|
||||
@@ -51,25 +53,25 @@ function indexOfLayer(layers, layerId) {
|
||||
return null
|
||||
}
|
||||
|
||||
function getAccessToken(sourceName, mapStyle, opts) {
|
||||
function getAccessToken(sourceName: string, mapStyle: StyleSpecification, opts: {allowFallback?: boolean}) {
|
||||
if(sourceName === "thunderforest_transport" || sourceName === "thunderforest_outdoors") {
|
||||
sourceName = "thunderforest"
|
||||
}
|
||||
|
||||
const metadata = mapStyle.metadata || {}
|
||||
const metadata = mapStyle.metadata || {} as any;
|
||||
let accessToken = metadata[`maputnik:${sourceName}_access_token`]
|
||||
|
||||
if(opts.allowFallback && !accessToken) {
|
||||
accessToken = tokens[sourceName]
|
||||
accessToken = tokens[sourceName as keyof typeof tokens]
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
function replaceSourceAccessToken(mapStyle, sourceName, opts={}) {
|
||||
function replaceSourceAccessToken(mapStyle: StyleSpecification, sourceName: string, opts={}) {
|
||||
const source = mapStyle.sources[sourceName]
|
||||
if(!source) return mapStyle
|
||||
if(!source.hasOwnProperty("url")) return mapStyle
|
||||
if(!("url" in source) || !source.url) return mapStyle
|
||||
|
||||
const accessToken = getAccessToken(sourceName, mapStyle, opts)
|
||||
|
||||
@@ -92,7 +94,7 @@ function replaceSourceAccessToken(mapStyle, sourceName, opts={}) {
|
||||
return changedStyle
|
||||
}
|
||||
|
||||
function replaceAccessTokens(mapStyle, opts={}) {
|
||||
function replaceAccessTokens(mapStyle: StyleSpecification, opts={}) {
|
||||
let changedStyle = mapStyle
|
||||
|
||||
Object.keys(mapStyle.sources).forEach((sourceName) => {
|
||||
@@ -112,9 +114,9 @@ function replaceAccessTokens(mapStyle, opts={}) {
|
||||
return changedStyle
|
||||
}
|
||||
|
||||
function stripAccessTokens(mapStyle) {
|
||||
function stripAccessTokens(mapStyle: StyleSpecification) {
|
||||
const changedMetadata = {
|
||||
...mapStyle.metadata
|
||||
...mapStyle.metadata as any
|
||||
};
|
||||
delete changedMetadata['maputnik:openmaptiles_access_token'];
|
||||
return {
|
||||
@@ -1,6 +1,7 @@
|
||||
import style from './style.js'
|
||||
import { loadStyleUrl } from './urlopen'
|
||||
import style from './style'
|
||||
import {loadStyleUrl} from './urlopen'
|
||||
import publicSources from '../config/styles.json'
|
||||
import { StyleSpecification } from '@maplibre/maplibre-gl-style-spec'
|
||||
|
||||
const storagePrefix = "maputnik"
|
||||
const stylePrefix = 'style'
|
||||
@@ -12,7 +13,7 @@ const storageKeys = {
|
||||
const defaultStyleUrl = publicSources[0].url
|
||||
|
||||
// Fetch a default style via URL and return it or a fallback style via callback
|
||||
export function loadDefaultStyle(cb) {
|
||||
export function loadDefaultStyle(cb: (...args: any[]) => void) {
|
||||
loadStyleUrl(defaultStyleUrl, cb)
|
||||
}
|
||||
|
||||
@@ -21,20 +22,20 @@ function loadStoredStyles() {
|
||||
const styles = []
|
||||
for (let i = 0; i < window.localStorage.length; i++) {
|
||||
const key = window.localStorage.key(i)
|
||||
if(isStyleKey(key)) {
|
||||
styles.push(fromKey(key))
|
||||
if(isStyleKey(key!)) {
|
||||
styles.push(fromKey(key!))
|
||||
}
|
||||
}
|
||||
return styles
|
||||
}
|
||||
|
||||
function isStyleKey(key) {
|
||||
function isStyleKey(key: string) {
|
||||
const parts = key.split(":")
|
||||
return parts.length === 3 && parts[0] === storagePrefix && parts[1] === stylePrefix
|
||||
}
|
||||
|
||||
// Load style id from key
|
||||
function fromKey(key) {
|
||||
function fromKey(key: string) {
|
||||
if(!isStyleKey(key)) {
|
||||
throw "Key is not a valid style key"
|
||||
}
|
||||
@@ -45,26 +46,31 @@ function fromKey(key) {
|
||||
}
|
||||
|
||||
// Calculate key that identifies the style with a version
|
||||
function styleKey(styleId) {
|
||||
function styleKey(styleId: string) {
|
||||
return [storagePrefix, stylePrefix, styleId].join(":")
|
||||
}
|
||||
|
||||
// Manages many possible styles that are stored in the local storage
|
||||
export class StyleStore {
|
||||
/**
|
||||
* List of style ids
|
||||
*/
|
||||
mapStyles: string[];
|
||||
|
||||
// Tile store will load all items from local storage and
|
||||
// assume they do not change will working on it
|
||||
constructor() {
|
||||
this.mapStyles = loadStoredStyles()
|
||||
this.mapStyles = loadStoredStyles();
|
||||
}
|
||||
|
||||
init(cb) {
|
||||
init(cb: (...args: any[]) => void) {
|
||||
cb(null)
|
||||
}
|
||||
|
||||
// Delete entire style history
|
||||
purge() {
|
||||
for (let i = 0; i < window.localStorage.length; i++) {
|
||||
const key = window.localStorage.key(i)
|
||||
const key = window.localStorage.key(i) as string;
|
||||
if(key.startsWith(storagePrefix)) {
|
||||
window.localStorage.removeItem(key)
|
||||
}
|
||||
@@ -72,9 +78,9 @@ export class StyleStore {
|
||||
}
|
||||
|
||||
// Find the last edited style
|
||||
latestStyle(cb) {
|
||||
latestStyle(cb: (...args: any[]) => void) {
|
||||
if(this.mapStyles.length === 0) return loadDefaultStyle(cb)
|
||||
const styleId = window.localStorage.getItem(storageKeys.latest)
|
||||
const styleId = window.localStorage.getItem(storageKeys.latest) as string;
|
||||
const styleItem = window.localStorage.getItem(styleKey(styleId))
|
||||
|
||||
if(styleItem) return cb(JSON.parse(styleItem))
|
||||
@@ -82,7 +88,7 @@ export class StyleStore {
|
||||
}
|
||||
|
||||
// Save current style replacing previous version
|
||||
save(mapStyle) {
|
||||
save(mapStyle: StyleSpecification & { id: string }) {
|
||||
mapStyle = style.ensureStyleValidity(mapStyle)
|
||||
const key = styleKey(mapStyle.id)
|
||||
window.localStorage.setItem(key, JSON.stringify(mapStyle))
|
||||
Reference in New Issue
Block a user