import { getThemeById } from '@grafana/data/src/themes/registry'; import { ThemeChangedEvent } from '@grafana/runtime'; import appEvents from '../app_events'; import { config } from '../config'; import { contextSrv } from '../core'; import { PreferencesService } from './PreferencesService'; export async function changeTheme(themeId: string, runtimeOnly?: boolean) { const oldTheme = config.theme2; const newTheme = getThemeById(themeId); appEvents.publish(new ThemeChangedEvent(newTheme)); // Add css file for new theme if (oldTheme.colors.mode !== newTheme.colors.mode) { const newCssLink = document.createElement('link'); newCssLink.rel = 'stylesheet'; newCssLink.href = config.bootData.themePaths[newTheme.colors.mode]; newCssLink.onload = () => { // Remove old css file const bodyLinks = document.getElementsByTagName('link'); for (let i = 0; i < bodyLinks.length; i++) { const link = bodyLinks[i]; if (link.href && link.href.includes(`build/grafana.${oldTheme.colors.mode}`)) { // Remove existing link once the new css has loaded to avoid flickering // If we add new css at the same time we remove current one the page will be rendered without css // As the new css file is loading link.remove(); } } }; document.head.insertBefore(newCssLink, document.head.firstChild); } if (runtimeOnly) { return; } if (!contextSrv.isSignedIn) { return; } // Persist new theme const service = new PreferencesService('user'); const currentPref = await service.load(); await service.update({ ...currentPref, theme: newTheme.colors.mode, }); } export async function toggleTheme(runtimeOnly: boolean) { const currentTheme = config.theme2; changeTheme(currentTheme.isDark ? 'light' : 'dark', runtimeOnly); }