packages/core: added localStorage support for AppThemeSelector
This commit is contained in:
@@ -45,4 +45,41 @@ describe('AppThemeSelector', () => {
|
||||
expect(selector.getInstalledThemes()).toEqual(themes);
|
||||
expect(selector.getInstalledThemes()).not.toBe(themes);
|
||||
});
|
||||
|
||||
it('should store theme in local storage', async () => {
|
||||
expect(AppThemeSelector.createWithStorage([]).getActiveThemeId()).toBe(
|
||||
undefined,
|
||||
);
|
||||
localStorage.setItem('theme', 'x');
|
||||
expect(AppThemeSelector.createWithStorage([]).getActiveThemeId()).toBe('x');
|
||||
localStorage.removeItem('theme');
|
||||
expect(AppThemeSelector.createWithStorage([]).getActiveThemeId()).toBe(
|
||||
undefined,
|
||||
);
|
||||
|
||||
const addListenerSpy = jest.spyOn(window, 'addEventListener');
|
||||
const selector = AppThemeSelector.createWithStorage([]);
|
||||
|
||||
expect(addListenerSpy).toHaveBeenCalledTimes(1);
|
||||
expect(addListenerSpy).toHaveBeenCalledWith(
|
||||
'storage',
|
||||
expect.any(Function),
|
||||
);
|
||||
|
||||
selector.setActiveThemeId('y');
|
||||
await 'wait a tick';
|
||||
expect(localStorage.getItem('theme')).toBe('y');
|
||||
|
||||
selector.setActiveThemeId(undefined);
|
||||
await 'wait a tick';
|
||||
expect(localStorage.getItem('theme')).toBe(null);
|
||||
|
||||
localStorage.setItem('theme', 'z');
|
||||
expect(selector.getActiveThemeId()).toBe(undefined);
|
||||
|
||||
const listener = addListenerSpy.mock.calls[0][1] as EventListener;
|
||||
listener({ key: 'theme' } as StorageEvent);
|
||||
|
||||
expect(selector.getActiveThemeId()).toBe('z');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,7 +17,35 @@
|
||||
import Observable from 'zen-observable';
|
||||
import { AppThemeApi, AppTheme } from '../../definitions';
|
||||
|
||||
const STORAGE_KEY = 'theme';
|
||||
|
||||
export class AppThemeSelector implements AppThemeApi {
|
||||
static createWithStorage(themes: AppTheme[]) {
|
||||
const selector = new AppThemeSelector(themes);
|
||||
|
||||
const initialThemeId =
|
||||
window?.localStorage.getItem(STORAGE_KEY) ?? undefined;
|
||||
|
||||
selector.setActiveThemeId(initialThemeId);
|
||||
|
||||
selector.activeThemeId$().subscribe((themeId) => {
|
||||
if (themeId) {
|
||||
window?.localStorage.setItem(STORAGE_KEY, themeId);
|
||||
} else {
|
||||
window?.localStorage.removeItem(STORAGE_KEY);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('storage', (event) => {
|
||||
if (event.key === STORAGE_KEY) {
|
||||
const themeId = localStorage.getItem(STORAGE_KEY) ?? undefined;
|
||||
selector.setActiveThemeId(themeId);
|
||||
}
|
||||
});
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
private readonly themes: AppTheme[];
|
||||
|
||||
private activeThemeId: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user