mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 05:06:16 -08:00
fix(backup): export and restore Xtream user state in the PWA (#1905)
* fix(backup): export and restore Xtream user state in the PWA Without an Electron bridge the backup wrote empty Xtream favorites, history and positions, and import only parked the state until the playlist was next opened. PwaXtreamBackupStateService reads and writes the four PWA maps through USER_DATA_STORAGE, so self-hosted server storage is covered as well. Export converts typed keys, resolves legacy ids only through their snapshot, and fails on an unreadable map instead of writing []. Import applies at once through applyAndConsume, remapped to the imported playlist id; a failed write keeps the snapshot parked for the store. Title snapshots travel in a new optional collectionItems field that older builds ignore. The storage key names are shared with the portal data source as XTREAM_USER_DATA_KEYS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(backup): write PWA title snapshots before the Xtream lists A browser restore that failed after its first list write kept the pending state parked for the Xtream store, but that replay carries no title snapshots, so they were lost. Merge them first; a damaged cache is replaced, while a storage that cannot be read still fails the entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(backup): keep the artwork of PWA recently viewed items The browser build saves a backdrop with each view and shows it ahead of the title snapshot's, but the export dropped it, so a restore showed older artwork. Carry it as an optional backdropUrl on the archive's recently viewed items; the desktop build ignores it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(xtream): keep view artwork in the PWA pending restore state A failed browser restore is replayed by PwaXtreamDataSource.restoreUserData, which rewrote recently viewed items without their backdropUrl; a refresh dropped it the same way in clearPlaylistContent. Both now carry it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(backup): restore PWA Xtream lists before the snapshot cache Writing the optional title snapshots first could take the storage space the favorites, history or positions needed, failing a restore that fits without them. The lists now go first, as the snapshot-storage contract asks; after a failed list write the snapshots are still merged for the store's replay, unless storage is full. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(backup): pick the Xtream backup path by the SQLite data source The backup chose its Xtream path by the mere presence of window.electron, while XTREAM_DATA_SOURCE falls back to the browser storage whenever the bridge lacks the Xtream SQLite API. On such a partial or stale preload the export read the wrong store and the restore took the SQLite path. Both now follow RuntimeCapabilitiesService.supportsXtreamSqliteDataSource. Also casts the test helper's prototype instance through unknown, which the spec typecheck requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(xtream): restore PWA playback positions under the target playlist A PWA restore that is replayed by the Xtream store kept each position's exported playlistId. When the backup was imported under another id, the VOD details page rejected those positions as belonging to a different playlist. restoreUserData now stamps the playlist it restores into. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ebb1ab3467
commit
8bf92f9d65
13 files changed
+1223
-81
No files matched your search
@@ -12,6 +12,8 @@ settings screen.
|
||||
- Manifest types: `libs/shared/interfaces/src/lib/playlist-backup.interface.ts`
|
||||
- Xtream pending restore storage:
|
||||
`libs/services/src/lib/xtream-pending-restore.service.ts`
|
||||
- Browser (PWA) Xtream user state:
|
||||
`libs/services/src/lib/pwa-xtream-backup-state.service.ts`
|
||||
|
||||
## Manifest Contract
|
||||
|
||||
@@ -61,9 +63,12 @@ Xtream backups export only connection metadata plus portable user state.
|
||||
- User state:
|
||||
- hidden categories by `{ categoryType, xtreamId }`
|
||||
- favorites by `{ contentType, xtreamId, addedAt?, position? }`
|
||||
- recently viewed by `{ contentType, xtreamId, viewedAt }`
|
||||
- recently viewed by `{ contentType, xtreamId, viewedAt, backdropUrl? }`
|
||||
(`backdropUrl` is written and read by the browser build only)
|
||||
- playback positions as `PlaybackPositionData[]`
|
||||
- optional VOD source pins by `{ matchKey, contentId, updatedAt? }`
|
||||
- optional title snapshots `collectionItems` (browser build only; see
|
||||
[Browser runtime](#browser-runtime))
|
||||
|
||||
An imported Xtream archive can wait for its catalog to download. Export reads
|
||||
that pending snapshot before consulting the catalog: its hidden categories,
|
||||
@@ -225,6 +230,47 @@ categories/favorites/history can
|
||||
remain after a later failure, but the snapshot remains available to retry the
|
||||
complete restore. It is consumed only after every restore step succeeds.
|
||||
|
||||
### Browser Runtime
|
||||
|
||||
Whenever `XTREAM_DATA_SOURCE` resolves to `PwaXtreamDataSource` — the
|
||||
browser, or a desktop bridge without the Xtream SQLite API
|
||||
(`RuntimeCapabilitiesService.supportsXtreamSqliteDataSource`) — Xtream
|
||||
favorites, recently viewed items, playback positions and title snapshots live
|
||||
in the `USER_DATA_STORAGE` maps owned by `PwaXtreamDataSource`
|
||||
(`XTREAM_USER_DATA_KEYS`; see
|
||||
[PWA portal user data](./pwa-self-hosted.md#pwa-portal-user-data)).
|
||||
`PwaXtreamBackupStateService` reads and writes them through that token, so the
|
||||
self-hosted server storage is covered too.
|
||||
|
||||
- Export converts each playlist's entries to the archive shape. Typed keys
|
||||
(`movie:42`) carry their identity; a legacy bare id resolves only through
|
||||
the snapshot stored under it, and is left out when none identifies it.
|
||||
Recently viewed keeps the newest view per title, with the artwork saved
|
||||
for that view as `backdropUrl`. `collectionItems` carries
|
||||
the snapshots of exported favorites and history, and is omitted when there
|
||||
are none. Hidden categories stay `[]` and `sourcePins` stays absent: the
|
||||
browser tracks neither.
|
||||
- An unreadable map (storage error, malformed JSON, a playlist entry that is
|
||||
not a list) fails the export instead of being written as an empty list.
|
||||
- A pending restore snapshot still wins over the stored maps, as on desktop.
|
||||
- Import parks the restore state like the desktop does, then applies it at
|
||||
once through `XtreamPendingRestoreService.applyAndConsume`: the browser has
|
||||
no catalog cache to wait for. Favorites, history and positions of the
|
||||
imported playlist id are replaced (positions get that id); other playlists'
|
||||
entries are untouched. `collectionItems` merge into the playlist's
|
||||
snapshots, keyed by typed identity; an archive without them leaves the
|
||||
snapshots alone, malformed items are skipped, a damaged cache is replaced,
|
||||
and a quota error on this cache does not fail the restore.
|
||||
- The lists are written before the optional title snapshots, so the cache
|
||||
never takes storage space they need (as for additions; see the
|
||||
[snapshot-storage contract](./xtream-portal-compatibility.md)). A failed
|
||||
write fails the entry and keeps the snapshot parked, so the Xtream store
|
||||
replays the complete state when the playlist next opens. That replay
|
||||
carries no title snapshots, so they are still merged after a failed list
|
||||
write, unless storage is full and they would take room the replay needs.
|
||||
|
||||
Older builds ignore `collectionItems`; the manifest version stays `1`.
|
||||
|
||||
## Current UX
|
||||
|
||||
The settings page now exports/imports “playlist backups” instead of the old
|
||||
|
||||
@@ -272,7 +272,11 @@ and sidecar state in localStorage:
|
||||
`PwaXtreamDataSource` and `PwaCollectionStorage` reach these keys through the
|
||||
`USER_DATA_STORAGE` token from `@iptvnator/services` (default:
|
||||
`localStorage`), never through `localStorage` directly, so a deployment can
|
||||
substitute a server-synced storage.
|
||||
substitute a server-synced storage. The key names are shared as
|
||||
`XTREAM_USER_DATA_KEYS` with the playlist backup, which exports and restores
|
||||
the favorites, recent items, positions and snapshots through the same token
|
||||
(`PwaXtreamBackupStateService`; see
|
||||
[backup/restore](./playlist-backup-restore.md#browser-runtime)).
|
||||
|
||||
Entries should include a content snapshot when the item is added. Global
|
||||
collection routes and the dashboard can then restore titles, posters, content
|
||||
|
||||
Reference in new issue
Block a user