mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 21:26:15 -08:00
- The unconfirmed-writes registry stores each page load's record under its own key (iptvnator-server:unconfirmed:<instance>:<page>), listed through a new keys() on the user-data storage adapter, so tabs never overwrite each other's records. Saved writes without a fresh record, also when the record was lost, are adopted as a closed tab's (#1920). - PwaService sends the stored server token on its raw fetch calls only while server mode runs, and a backend that answers without server storage makes the browser forget the token. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import { InjectionToken } from '@angular/core';
|
|
|
|
/**
|
|
* The slice of the Web Storage API that PWA user-data stores rely on, plus
|
|
* the stored keys where the store can list them.
|
|
*/
|
|
export type UserDataStorage = Pick<
|
|
Storage,
|
|
'getItem' | 'setItem' | 'removeItem'
|
|
> & { keys?(): string[] };
|
|
|
|
/**
|
|
* `localStorage` behind an adapter that reads the global only inside each
|
|
* call: when the browser denies storage access, reading `localStorage`
|
|
* itself throws, and that must happen in the callers' guarded reads and
|
|
* writes, not while Angular constructs the service that injects this.
|
|
*/
|
|
export function createBrowserUserDataStorage(): UserDataStorage {
|
|
return {
|
|
getItem: (key) => globalThis.localStorage.getItem(key),
|
|
setItem: (key, value) => globalThis.localStorage.setItem(key, value),
|
|
removeItem: (key) => globalThis.localStorage.removeItem(key),
|
|
keys: () => {
|
|
const storage = globalThis.localStorage;
|
|
const keys: string[] = [];
|
|
for (let index = 0; index < storage.length; index += 1) {
|
|
const key = storage.key(index);
|
|
if (key !== null) {
|
|
keys.push(key);
|
|
}
|
|
}
|
|
return keys;
|
|
},
|
|
};
|
|
}
|
|
|
|
/** The same lazy adapter over `sessionStorage`: one per tab, kept on reload. */
|
|
export function createBrowserSessionStorage(): UserDataStorage {
|
|
return {
|
|
getItem: (key) => globalThis.sessionStorage.getItem(key),
|
|
setItem: (key, value) => globalThis.sessionStorage.setItem(key, value),
|
|
removeItem: (key) => globalThis.sessionStorage.removeItem(key),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The PWA Xtream user-data maps in USER_DATA_STORAGE, each a JSON object
|
|
* keyed by playlist id. Shared with the playlist backup, which reads and
|
|
* writes them directly.
|
|
*/
|
|
export const XTREAM_USER_DATA_KEYS = {
|
|
favorites: 'xtream-favorites',
|
|
recentItems: 'xtream-recent-items',
|
|
collectionItems: 'xtream-collection-items',
|
|
playbackPositions: 'xtream-playback-positions',
|
|
} as const;
|
|
|
|
/**
|
|
* Browser persistence for PWA user data such as Xtream favorites, recently
|
|
* viewed items and playback positions. Defaults to `localStorage`; the
|
|
* self-hosted server mode provides a server-synced implementation.
|
|
*/
|
|
export const USER_DATA_STORAGE = new InjectionToken<UserDataStorage>(
|
|
'USER_DATA_STORAGE',
|
|
{ providedIn: 'root', factory: createBrowserUserDataStorage }
|
|
);
|