Handle QuotaExceededError in StyleStore (#1253)

## Launch Checklist

<!-- Thanks for the PR! Feel free to add or remove items from the
checklist. -->

When localStorage is full you start getting a "QuotaExceededError".
RIght now Maputnik does not handle this situation gracefully, it just
fails loading the style with a non-descriptive error message.

This PR purges localStorage and tries again when this particular error
happens.

It still does not show a descriptive error message. If you try to load a
style that is larger than what localStorage can handle, it will still
fail with a non-descriptive error message.

Increased the size of `example-style.json` so that it causes a
QuotaExceededError when running the regression test (try it before and
after this PR).


 - [x] Briefly describe the changes in this PR.
 - [x] Link to related issues. N/A
- [x] Include before/after visuals or gifs if this PR includes visual
changes. N/A
 - [x] Write tests for all new functionality.
 - [x] Add an entry to `CHANGELOG.md` under the `## main` section.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Bart Louwers
2025-07-04 10:27:00 +02:00
committed by GitHub
parent f5b7eccf52
commit 599240033a
5 changed files with 179 additions and 14 deletions

View File

@@ -91,8 +91,28 @@ export class StyleStore {
save(mapStyle: StyleSpecification & { id: string }) {
mapStyle = style.ensureStyleValidity(mapStyle)
const key = styleKey(mapStyle.id)
window.localStorage.setItem(key, JSON.stringify(mapStyle))
window.localStorage.setItem(storageKeys.latest, mapStyle.id)
const saveFn = () => {
window.localStorage.setItem(key, JSON.stringify(mapStyle))
window.localStorage.setItem(storageKeys.latest, mapStyle.id)
}
try {
saveFn()
} catch (e) {
// Handle quota exceeded error
if (e instanceof DOMException && (
e.code === 22 || // Firefox
e.code === 1014 || // Firefox
e.name === 'QuotaExceededError' ||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED'
)) {
this.purge()
saveFn() // Retry after clearing
} else {
throw e
}
}
return mapStyle
}
}