Last active 1753446413

Revision 87545d0ffae985d87fca865b52c6c75360698511

local-storage.service.ts Raw
1import { Injectable } from '@angular/core';
2import { fromEvent, merge, Observable, Subject } from 'rxjs';
3import { filter, map, startWith } from 'rxjs/operators';
4
5export interface LocalStorageObject {
6 name: string;
7 value: string | null;
8}
9
10const deserializeValue = <T>(value: string): T => {
11 try {
12 return JSON.parse(value);
13 } catch {
14 return value as unknown as T;
15 }
16};
17
18@Injectable({
19 providedIn: 'root',
20})
21export class LocalStorageService {
22 private _storage = window.localStorage;
23
24 private _storageUpdateNotifier$ = new Subject<LocalStorageObject | null>();
25
26 storageUpdates$ = this._storageUpdateNotifier$.asObservable();
27
28 initLocalStorage(storageObjs: LocalStorageObject[]): void {
29 if (this._isLocalStorageEnabled()) {
30 storageObjs.forEach(({ name, value }) => {
31 this._storage.setItem(name, value);
32 });
33 }
34 }
35
36 setItem(key: string, value: string): void {
37 this._storage.setItem(key, value);
38 this._storageUpdateNotifier$.next({ name: key, value });
39 }
40
41 getItem(key: string): any {
42 const retrieved = this._storage.getItem(key);
43 try {
44 return deserializeValue(retrieved);
45 } catch {
46 return retrieved;
47 }
48 }
49
50 removeItem(key: string): void {
51 this._storage.removeItem(key);
52 this._storageUpdateNotifier$.next({ name: key, value: null });
53 }
54
55 clear(): void {
56 this._storage.clear();
57 this._storageUpdateNotifier$.next(null);
58 }
59
60 getUpdatesForKey<T>(key: string): Observable<T> {
61 return merge(
62 fromEvent(window, 'storage').pipe(
63 filter((event: StorageEvent) => event.key === key),
64 map(data => deserializeValue(data.newValue))
65 ),
66 this.storageUpdates$.pipe(
67 filter(update => update.name === key),
68 map(update => deserializeValue(update.value))
69 )
70 ).pipe(startWith(this.getItem(key) || false));
71 }
72
73 private _isLocalStorageEnabled(): boolean {
74 try {
75 const key = `__storage__test`;
76 this._storage.setItem(key, null);
77 this._storage.removeItem(key);
78 return true;
79 } catch (e) {
80 return false;
81 }
82 }
83}