packages/core: added localStorage support for AppThemeSelector

This commit is contained in:
Patrik Oldsberg
2020-05-15 01:03:56 +02:00
parent 05ac0bef26
commit 152aa51a28
2 changed files with 65 additions and 0 deletions
@@ -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;