allartk / leaflet.offline

Leaflet offline layer
https://allartk.github.io/leaflet.offline/
GNU Lesser General Public License v3.0
311 stars 76 forks source link

Data management #314

Open ghost opened 1 year ago

ghost commented 1 year ago

I’m developing an application that needs to cache the map as it is viewed to reduce server loads, and using the examples and documentation given so far I’ve got the following:

      const tileLayerOffline = L.tileLayer.offline(urlTemplate, {
        attribution:
          '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors',
        minZoom: 12,
      });

      tileLayerOffline.addTo(mapState);

      tileLayerOffline.on("tileload", (event) => {
        const { tile } = event;
        const url = tile.src;
        if (url.search("blob:") !== -1) {
         console.debug(`Loaded ${url} from idb`);
          return;
        }
        const { x, y, z } = event.coords;
        const { _url: urlTemplate } = event.target;
        const tileInfo = {
          key: url,
          url,
          x,
          y,
          z,
          urlTemplate,
          createdAt: Date.now(),
        };
        downloadTile(url)
          .then((dl) => saveTile(tileInfo, dl))
          .then(() => console.debug(`Saved ${url} in idb`));
      });

Which is basically a modified version of one of the examples to use tileLayer.offline

This works great for an individual session, but I’m struggling to understand where data is stored. In my case, I need to apply this to an ionic application where I can save data locally, and I would need to reload the database (I assume), to “resume” the download session instead of starting from scratch every time. That is, I want to save the map data that was loaded during a session, and then be able to load it on the next.

Is there a way to do this? And if so, where is this information stored and accessed from (loaded images/blobs, db)? Finally, is there any method to delete the oldest storage entries by date? So far the only method I could find is modifying:

async () => {
    const tiles = await getStorageInfo(urlTemplate);
    const minCreatedAt = new Date().setDate(-30);
    await Promise.all(
      tiles.map((tile) =>
        tile.createdAt < minCreatedAt ? removeTile(tile.key) : Promise.resolve()
      )
    );
  }

to sort tiles by date of creation, and deleting them that way, but I don’t know if that would be the recommended way.

Thanks for the excellent library btw!

JamesIde commented 9 months ago

Hey, I'm trying to get this working with Ionic and Angular, have you had any luck?

apiarysolutions commented 7 months ago

We are trying to get Caching working with Xamarin.Forms compiled to iOS and Android with no luck. It would be great if there was an example for mobile apps in Xamarin/MAUI.

disarticulate commented 4 months ago

The plugin uses idb: https://github.com/jakearchibald/idb

This uses Indexeddb: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

You can see the keys/data in this example: https://allartk.github.io/leaflet.offline/list.html

The hardcoded db name is leaflet.offline. The hardcoded table is tileStore. Two indexes are created called z and urlTemplate and you can filter on either.

When you pull a tile record based on your script, you get the following objectkeys { blob, createdAt, key, url, urlTemplate, x, y, z }

If you want to delete keys by time, you'd create an index on createdAt here: https://github.com/allartk/leaflet.offline/src/TileManager.ts as follows:

  dbPromise = openDB('leaflet.offline', 2, {
    upgrade(db, oldVersion) {
      deleteDB('leaflet_offline');
      deleteDB('leaflet_offline_areas');

      if (oldVersion < 1) {
        const tileStore = db.createObjectStore(tileStoreName, {
          keyPath: 'key',
        });
        tileStore.createIndex(urlTemplateIndex, 'urlTemplate');
        tileStore.createIndex('createdAt', 'createdAt');
        tileStore.createIndex('z', 'z');
      }
    },
  });

To get access to the DB, we need to expose the openTilesDataBase method in src/TileManager.ts.

I made a pull request to allow future development here: https://github.com/allartk/leaflet.offline/pull/369

Once openTilesDataBase is exposed, Clients could manage the data as needed.