import _ from 'lodash'; import angular from 'angular'; import { SNTheme, SFItemParams } from 'snjs'; import { StorageManager } from './storageManager'; import { APP_STATE_EVENT_DESKTOP_EXTS_READY } from '@/state'; export class ThemeManager { /* @ngInject */ constructor( componentManager, desktopManager, storageManager, lockManager, appState ) { this.componentManager = componentManager; this.storageManager = storageManager; this.desktopManager = desktopManager; this.activeThemes = []; ThemeManager.CachedThemesKey = "cachedThemes"; this.registerObservers(); if (desktopManager.isDesktop) { appState.addObserver((eventName, data) => { if (eventName === APP_STATE_EVENT_DESKTOP_EXTS_READY) { this.activateCachedThemes(); } }); } else { this.activateCachedThemes(); } } activateCachedThemes() { const cachedThemes = this.getCachedThemes(); const writeToCache = false; for (const theme of cachedThemes) { this.activateTheme(theme, writeToCache); } } registerObservers() { this.desktopManager.registerUpdateObserver((component) => { // Reload theme if active if (component.active && component.isTheme()) { this.deactivateTheme(component); setTimeout(() => { this.activateTheme(component); }, 10); } }); this.componentManager.registerHandler({ identifier: "themeManager", areas: ["themes"], activationHandler: (component) => { if (component.active) { this.activateTheme(component); } else { this.deactivateTheme(component); } } }); } hasActiveTheme() { return this.componentManager.getActiveThemes().length > 0; } deactivateAllThemes() { var activeThemes = this.componentManager.getActiveThemes(); for (var theme of activeThemes) { if (theme) { this.componentManager.deactivateComponent(theme); } } this.decacheThemes(); } activateTheme(theme, writeToCache = true) { if (_.find(this.activeThemes, { uuid: theme.uuid })) { return; } this.activeThemes.push(theme); var url = this.componentManager.urlForComponent(theme); var link = document.createElement("link"); link.href = url; link.type = "text/css"; link.rel = "stylesheet"; link.media = "screen,print"; link.id = theme.uuid; document.getElementsByTagName("head")[0].appendChild(link); if (writeToCache) { this.cacheThemes(); } } deactivateTheme(theme) { var element = document.getElementById(theme.uuid); if (element) { element.disabled = true; element.parentNode.removeChild(element); } _.remove(this.activeThemes, { uuid: theme.uuid }); this.cacheThemes(); } async cacheThemes() { const mapped = await Promise.all(this.activeThemes.map(async (theme) => { const transformer = new SFItemParams(theme); const params = await transformer.paramsForLocalStorage(); return params; })); const data = JSON.stringify(mapped); return this.storageManager.setItem(ThemeManager.CachedThemesKey, data, StorageManager.Fixed); } async decacheThemes() { return this.storageManager.removeItem(ThemeManager.CachedThemesKey, StorageManager.Fixed); } getCachedThemes() { const cachedThemes = this.storageManager.getItemSync(ThemeManager.CachedThemesKey, StorageManager.Fixed); if (cachedThemes) { const parsed = JSON.parse(cachedThemes); return parsed.map((theme) => { return new SNTheme(theme); }); } else { return []; } } }