2021-09-20 17:14:55 +02:00
import FilteredLayer from "../../../Models/FilteredLayer" ;
2021-09-21 02:10:42 +02:00
import { FeatureSourceForLayer , Tiled } from "../FeatureSource" ;
2021-09-20 17:14:55 +02:00
import { UIEventSource } from "../../UIEventSource" ;
import Loc from "../../../Models/Loc" ;
2021-09-21 02:10:42 +02:00
import TileHierarchy from "./TileHierarchy" ;
import { Utils } from "../../../Utils" ;
2021-09-22 05:02:09 +02:00
import SaveTileToLocalStorageActor from "../Actors/SaveTileToLocalStorageActor" ;
2021-09-26 17:36:39 +02:00
import { Tiles } from "../../../Models/TileRange" ;
2021-09-28 17:30:48 +02:00
import { BBox } from "../../BBox" ;
2021-09-21 02:10:42 +02:00
export default class TiledFromLocalStorageSource implements TileHierarchy < FeatureSourceForLayer & Tiled > {
public loadedTiles : Map < number , FeatureSourceForLayer & Tiled > = new Map < number , FeatureSourceForLayer & Tiled > ( ) ;
2021-09-28 17:30:48 +02:00
public tileFreshness : Map < number , Date > = new Map < number , Date > ( )
2021-09-20 17:14:55 +02:00
constructor ( layer : FilteredLayer ,
2021-09-21 02:10:42 +02:00
handleFeatureSource : ( src : FeatureSourceForLayer & Tiled , index : number ) = > void ,
2021-09-20 17:14:55 +02:00
state : {
locationControl : UIEventSource < Loc >
leafletMap : any
} ) {
2021-09-21 02:10:42 +02:00
2021-09-26 17:36:39 +02:00
const undefinedTiles = new Set < number > ( )
2021-09-22 05:02:09 +02:00
const prefix = SaveTileToLocalStorageActor . storageKey + "-" + layer . layerDef . id + "-"
2021-09-21 02:10:42 +02:00
// @ts-ignore
const indexes : number [ ] = Object . keys ( localStorage )
. filter ( key = > {
return key . startsWith ( prefix ) && ! key . endsWith ( "-time" ) ;
} )
. map ( key = > {
return Number ( key . substring ( prefix . length ) ) ;
} )
2021-09-28 17:30:48 +02:00
console . debug ( "Layer" , layer . layerDef . id , "has following tiles in available in localstorage" , indexes . map ( i = > Tiles . tile_from_index ( i ) . join ( "/" ) ) . join ( ", " ) )
for ( const index of indexes ) {
2021-09-29 19:56:59 +02:00
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 )
undefinedTiles . add ( index )
console . log ( "Dropped old format tile" , prefix )
continue
}
const data = Number ( localStorage . getItem ( prefix + "-time" ) )
2021-09-28 17:30:48 +02:00
const freshness = new Date ( )
freshness . setTime ( data )
this . tileFreshness . set ( index , freshness )
}
2021-09-21 02:10:42 +02:00
const zLevels = indexes . map ( i = > i % 100 )
const indexesSet = new Set ( indexes )
const maxZoom = Math . max ( . . . zLevels )
const minZoom = Math . min ( . . . zLevels )
const self = this ;
const neededTiles = state . locationControl . map (
location = > {
if ( ! layer . isDisplayed . data ) {
// No need to download! - the layer is disabled
return undefined ;
}
if ( location . zoom < layer . layerDef . minzoom ) {
// No need to download! - the layer is disabled
return undefined ;
}
// Yup, this is cheating to just get the bounds here
const bounds = state . leafletMap . data ? . getBounds ( )
if ( bounds === undefined ) {
// We'll retry later
return undefined
}
const needed = [ ]
for ( let z = minZoom ; z <= maxZoom ; z ++ ) {
2021-09-26 17:36:39 +02:00
const tileRange = Tiles . TileRangeBetween ( z , bounds . getNorth ( ) , bounds . getEast ( ) , bounds . getSouth ( ) , bounds . getWest ( ) )
const neededZ = Tiles . MapRange ( tileRange , ( x , y ) = > Tiles . tile_index ( z , x , y ) )
. filter ( i = > ! self . loadedTiles . has ( i ) && ! undefinedTiles . has ( i ) && indexesSet . has ( i ) )
2021-09-21 02:10:42 +02:00
needed . push ( . . . neededZ )
}
if ( needed . length === 0 ) {
return undefined
}
return needed
}
, [ layer . isDisplayed , state . leafletMap ] ) . stabilized ( 50 ) ;
2021-09-28 17:30:48 +02:00
neededTiles . addCallbackAndRun ( t = > console . debug ( "Tiles to load from localstorage:" , t ) )
2021-09-21 02:10:42 +02:00
neededTiles . addCallbackAndRunD ( neededIndexes = > {
for ( const neededIndex of neededIndexes ) {
// We load the features from localStorage
try {
2021-09-22 05:02:09 +02:00
const key = SaveTileToLocalStorageActor . storageKey + "-" + layer . layerDef . id + "-" + neededIndex
2021-09-21 02:10:42 +02:00
const data = localStorage . getItem ( key )
const features = JSON . parse ( data )
const src = {
layer : layer ,
features : new UIEventSource < { feature : any ; freshness : Date } [ ] > ( features ) ,
name : "FromLocalStorage(" + key + ")" ,
tileIndex : neededIndex ,
2021-09-26 17:36:39 +02:00
bbox : BBox.fromTileIndex ( neededIndex )
2021-09-21 02:10:42 +02:00
}
handleFeatureSource ( src , neededIndex )
self . loadedTiles . set ( neededIndex , src )
} catch ( e ) {
console . error ( "Could not load data tile from local storage due to" , e )
2021-09-26 17:36:39 +02:00
undefinedTiles . add ( neededIndex )
2021-09-21 02:10:42 +02:00
}
}
} )
2021-09-20 17:14:55 +02:00
}
2021-09-21 02:10:42 +02:00
2021-09-20 17:14:55 +02:00
}