forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			134 lines
		
	
	
		
			No EOL
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			No EOL
		
	
	
		
			5.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import FilteredLayer from "../../../Models/FilteredLayer";
 | 
						|
import {FeatureSourceForLayer, Tiled} from "../FeatureSource";
 | 
						|
import {UIEventSource} from "../../UIEventSource";
 | 
						|
import TileHierarchy from "./TileHierarchy";
 | 
						|
import SaveTileToLocalStorageActor from "../Actors/SaveTileToLocalStorageActor";
 | 
						|
import {Tiles} from "../../../Models/TileRange";
 | 
						|
import {BBox} from "../../BBox";
 | 
						|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
 | 
						|
 | 
						|
export default class TiledFromLocalStorageSource implements TileHierarchy<FeatureSourceForLayer & Tiled> {
 | 
						|
    public readonly loadedTiles: Map<number, FeatureSourceForLayer & Tiled> = new Map<number, FeatureSourceForLayer & Tiled>();
 | 
						|
    private readonly layer: FilteredLayer;
 | 
						|
    private readonly handleFeatureSource: (src: FeatureSourceForLayer & Tiled, index: number) => void;
 | 
						|
    private readonly undefinedTiles: Set<number>;
 | 
						|
 | 
						|
    public static GetFreshnesses(layerId: string): Map<number, Date> {
 | 
						|
        const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layerId + "-"
 | 
						|
        const freshnesses = new Map<number, Date>()
 | 
						|
        for (const key of Object.keys(localStorage)) {
 | 
						|
            if (!(key.startsWith(prefix) && key.endsWith("-time"))) {
 | 
						|
                continue
 | 
						|
            }
 | 
						|
            const index = Number(key.substring(prefix.length, key.length - "-time".length))
 | 
						|
            const time = Number(localStorage.getItem(key))
 | 
						|
            const freshness = new Date()
 | 
						|
            freshness.setTime(time)
 | 
						|
            freshnesses.set(index, freshness)
 | 
						|
        }
 | 
						|
        return freshnesses
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    static cleanCacheForLayer(layer: LayerConfig) {
 | 
						|
        const now = new Date()
 | 
						|
        const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layer.id + "-"
 | 
						|
        console.log("Cleaning tiles of ", prefix, "with max age",layer.maxAgeOfCache)
 | 
						|
        for (const key of Object.keys(localStorage)) {
 | 
						|
            if (!(key.startsWith(prefix) && key.endsWith("-time"))) {
 | 
						|
                continue
 | 
						|
            }
 | 
						|
            const index = Number(key.substring(prefix.length, key.length - "-time".length))
 | 
						|
            const time = Number(localStorage.getItem(key))
 | 
						|
            const timeDiff = (now.getTime() - time) / 1000
 | 
						|
            
 | 
						|
            if(timeDiff >= layer.maxAgeOfCache){
 | 
						|
                const k = prefix+index;
 | 
						|
                localStorage.removeItem(k)
 | 
						|
                localStorage.removeItem(k+"-format")
 | 
						|
                localStorage.removeItem(k+"-time")
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    constructor(layer: FilteredLayer,
 | 
						|
                handleFeatureSource: (src: FeatureSourceForLayer & Tiled, index: number) => void,
 | 
						|
                state: {
 | 
						|
                    currentBounds: UIEventSource<BBox>
 | 
						|
                }) {
 | 
						|
        this.layer = layer;
 | 
						|
        this.handleFeatureSource = handleFeatureSource;
 | 
						|
 | 
						|
 | 
						|
        this.undefinedTiles = new Set<number>()
 | 
						|
        const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layer.layerDef.id + "-"
 | 
						|
        const knownTiles: number[] = Object.keys(localStorage)
 | 
						|
            .filter(key => {
 | 
						|
                return key.startsWith(prefix) && !key.endsWith("-time") && !key.endsWith("-format");
 | 
						|
            })
 | 
						|
            .map(key => {
 | 
						|
                return Number(key.substring(prefix.length));
 | 
						|
            })
 | 
						|
            .filter(i => !isNaN(i))
 | 
						|
 | 
						|
        console.debug("Layer", layer.layerDef.id, "has following tiles in available in localstorage", knownTiles.map(i => Tiles.tile_from_index(i).join("/")).join(", "))
 | 
						|
        for (const index of knownTiles) {
 | 
						|
 | 
						|
            const prefix = SaveTileToLocalStorageActor.storageKey + "-" + layer.layerDef.id + "-" + index;
 | 
						|
            const version = localStorage.getItem(prefix + "-format")
 | 
						|
            if (version === undefined || version !== SaveTileToLocalStorageActor.formatVersion) {
 | 
						|
                // Invalid version! Remove this tile from local storage
 | 
						|
                localStorage.removeItem(prefix)
 | 
						|
                localStorage.removeItem(prefix + "-time")
 | 
						|
                localStorage.removeItem(prefix + "-format")
 | 
						|
                this.undefinedTiles.add(index)
 | 
						|
                console.log("Dropped old format tile", prefix)
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        const self = this
 | 
						|
        state.currentBounds.map(bounds => {
 | 
						|
 | 
						|
            if (bounds === undefined) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            for (const knownTile of knownTiles) {
 | 
						|
 | 
						|
                if (this.loadedTiles.has(knownTile)) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                if (this.undefinedTiles.has(knownTile)) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
 | 
						|
                if (!bounds.overlapsWith(BBox.fromTileIndex(knownTile))) {
 | 
						|
                    continue;
 | 
						|
                }
 | 
						|
                self.loadTile(knownTile)
 | 
						|
            }
 | 
						|
        })
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    private loadTile(neededIndex: number) {
 | 
						|
        try {
 | 
						|
            const key = SaveTileToLocalStorageActor.storageKey + "-" + this.layer.layerDef.id + "-" + neededIndex
 | 
						|
            const data = localStorage.getItem(key)
 | 
						|
            const features = JSON.parse(data)
 | 
						|
            const src = {
 | 
						|
                layer: this.layer,
 | 
						|
                features: new UIEventSource<{ feature: any; freshness: Date }[]>(features),
 | 
						|
                name: "FromLocalStorage(" + key + ")",
 | 
						|
                tileIndex: neededIndex,
 | 
						|
                bbox: BBox.fromTileIndex(neededIndex)
 | 
						|
            }
 | 
						|
            this.handleFeatureSource(src, neededIndex)
 | 
						|
            this.loadedTiles.set(neededIndex, src)
 | 
						|
        } catch (e) {
 | 
						|
            console.error("Could not load data tile from local storage due to", e)
 | 
						|
            this.undefinedTiles.add(neededIndex)
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
} |