| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  | import FeatureSource, {Tiled} from "../FeatureSource"; | 
					
						
							| 
									
										
										
										
											2021-10-25 21:08:44 +02:00
										 |  |  | import {Tiles} from "../../../Models/TileRange"; | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  | import {IdbLocalStorage} from "../../Web/IdbLocalStorage"; | 
					
						
							|  |  |  | import {UIEventSource} from "../../UIEventSource"; | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  | import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"; | 
					
						
							|  |  |  | import {BBox} from "../../BBox"; | 
					
						
							|  |  |  | import SimpleFeatureSource from "../Sources/SimpleFeatureSource"; | 
					
						
							|  |  |  | import FilteredLayer from "../../../Models/FilteredLayer"; | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | import Loc from "../../../Models/Loc"; | 
					
						
							| 
									
										
										
										
											2021-09-21 02:10:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 20:34:04 +01:00
										 |  |  | /*** | 
					
						
							|  |  |  |  * Saves all the features that are passed in to localstorage, so they can be retrieved on the next run | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Technically, more an Actor then a featuresource, but it fits more neatly this ay | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-09-22 05:02:09 +02:00
										 |  |  | export default class SaveTileToLocalStorageActor { | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |     private readonly visitedTiles: UIEventSource<Map<number, Date>> | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |     private readonly _layer: LayerConfig; | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |     private readonly _flayer: FilteredLayer | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |     private readonly initializeTime = new Date() | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |     constructor(layer: FilteredLayer) { | 
					
						
							|  |  |  |         this._flayer = layer | 
					
						
							|  |  |  |         this._layer = layer.layerDef | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |         this.visitedTiles = IdbLocalStorage.Get("visited_tiles_" + this._layer.id, | 
					
						
							|  |  |  |             {defaultValue: new Map<number, Date>(),}) | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |         this.visitedTiles.stabilized(100).addCallbackAndRunD(tiles => { | 
					
						
							|  |  |  |             for (const key of Array.from(tiles.keys())) { | 
					
						
							|  |  |  |                 const tileFreshness = tiles.get(key) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |                 const toOld = (this.initializeTime.getTime() - tileFreshness.getTime()) > 1000 * this._layer.maxAgeOfCache | 
					
						
							|  |  |  |                 if (toOld) { | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |                     // Purge this tile
 | 
					
						
							|  |  |  |                     this.SetIdb(key, undefined) | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |                     console.debug("Purging tile", this._layer.id, key) | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |                     tiles.delete(key) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             this.visitedTiles.ping() | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |     public LoadTilesFromDisk(currentBounds: UIEventSource<BBox>, location: UIEventSource<Loc>, | 
					
						
							|  |  |  |                              registerFreshness: (tileId: number, freshness: Date) => void, | 
					
						
							|  |  |  |                              registerTile: ((src: FeatureSource & Tiled) => void)) { | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |         const self = this; | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |         const loadedTiles = new Set<number>() | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |         this.visitedTiles.addCallbackD(tiles => { | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |             if (tiles.size === 0) { | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |                 // We don't do anything yet as probably not yet loaded from disk
 | 
					
						
							|  |  |  |                 // We'll unregister later on
 | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |             currentBounds.addCallbackAndRunD(bbox => { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |                 if (self._layer.minzoomVisible > location.data.zoom) { | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |                     // Not enough zoom
 | 
					
						
							|  |  |  |                     return; | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 // Iterate over all available keys in the local storage, check which are needed and fresh enough
 | 
					
						
							|  |  |  |                 for (const key of Array.from(tiles.keys())) { | 
					
						
							|  |  |  |                     const tileFreshness = tiles.get(key) | 
					
						
							|  |  |  |                     if (tileFreshness > self.initializeTime) { | 
					
						
							|  |  |  |                         // This tile is loaded by another source
 | 
					
						
							|  |  |  |                         continue | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     registerFreshness(key, tileFreshness) | 
					
						
							|  |  |  |                     const tileBbox = BBox.fromTileIndex(key) | 
					
						
							|  |  |  |                     if (!bbox.overlapsWith(tileBbox)) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     if (loadedTiles.has(key)) { | 
					
						
							|  |  |  |                         // Already loaded earlier
 | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     loadedTiles.add(key) | 
					
						
							|  |  |  |                     this.GetIdb(key).then((features: { feature: any, freshness: Date }[]) => { | 
					
						
							|  |  |  |                         console.debug("Loaded tile " + self._layer.id + "_" + key + " from disk") | 
					
						
							|  |  |  |                         const src = new SimpleFeatureSource(self._flayer, key, new UIEventSource<{ feature: any; freshness: Date }[]>(features)) | 
					
						
							|  |  |  |                         registerTile(src) | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |             return true; // Remove the callback
 | 
					
						
							| 
									
										
										
										
											2021-09-30 04:13:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |         }) | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-25 21:08:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |     public addTile(tile: FeatureSource & Tiled) { | 
					
						
							| 
									
										
										
										
											2021-11-16 02:57:26 +01:00
										 |  |  |         const self = this | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |         tile.features.addCallbackAndRunD(features => { | 
					
						
							| 
									
										
										
										
											2021-09-30 04:13:23 +02:00
										 |  |  |             const now = new Date() | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |             if (features.length > 0) { | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |                 self.SetIdb(tile.tileIndex, features) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |             // We _still_ write the time to know that this tile is empty!
 | 
					
						
							|  |  |  |             this.MarkVisited(tile.tileIndex, now) | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |     public poison(lon: number, lat: number) { | 
					
						
							| 
									
										
										
										
											2021-10-25 21:08:44 +02:00
										 |  |  |         for (let z = 0; z < 25; z++) { | 
					
						
							|  |  |  |             const {x, y} = Tiles.embedded_tile(lat, lon, z) | 
					
						
							|  |  |  |             const tileId = Tiles.tile_index(z, x, y) | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |             this.visitedTiles.data.delete(tileId) | 
					
						
							| 
									
										
										
										
											2021-10-25 21:08:44 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     public MarkVisited(tileId: number, freshness: Date) { | 
					
						
							|  |  |  |         this.visitedTiles.data.set(tileId, freshness) | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |         this.visitedTiles.ping() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private SetIdb(tileIndex, data) { | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         try { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             IdbLocalStorage.SetDirectly(this._layer.id + "_" + tileIndex, data) | 
					
						
							| 
									
										
										
										
											2022-01-26 21:40:38 +01:00
										 |  |  |         } catch (e) { | 
					
						
							| 
									
										
										
										
											2021-12-13 02:05:34 +01:00
										 |  |  |             console.error("Could not save tile to indexed-db: ", e, "tileIndex is:", tileIndex, "for layer", this._layer.id) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-21 02:44:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private GetIdb(tileIndex) { | 
					
						
							|  |  |  |         return IdbLocalStorage.GetDirectly(this._layer.id + "_" + tileIndex) | 
					
						
							| 
									
										
										
										
											2021-11-15 11:51:32 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-20 17:14:55 +02:00
										 |  |  | } |