Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data management #314

Open
ghost opened this issue Sep 15, 2023 · 3 comments
Open

Data management #314

ghost opened this issue Sep 15, 2023 · 3 comments

Comments

@ghost
Copy link

ghost commented Sep 15, 2023

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
Copy link

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

@apiarysolutions
Copy link

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
Copy link

disarticulate commented Jun 30, 2024

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: #369

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants