mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 00:12:39 +00:00
feat: tell plugins when the colour scheme or theme changes
This commit is contained in:
@@ -37,7 +37,7 @@ const sources = ['app', 'components', 'hooks', 'lib', 'stores'].flatMap((d) => s
|
||||
|
||||
/** A call site that fires the hook: `xHooks.onFoo.emit(` and friends. */
|
||||
function isFired(hookName: string, groupName: string): boolean {
|
||||
const re = new RegExp(`\\b${groupName}\\.${hookName}\\.(emit|emitSync|emitTo|intercept|interceptOutcome|transform|takeOver)\\b`);
|
||||
const re = new RegExp(`\\b${groupName}\\.${hookName}\\s*\\.(emit|emitSync|emitTo|intercept|interceptOutcome|transform|takeOver)\\b`);
|
||||
return re.test(sources);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ function isFired(hookName: string, groupName: string): boolean {
|
||||
const NOT_YET_WIRED = new Set<HookGroup>([
|
||||
'mail-list', 'mail-read', 'mail-compose', 'mail-send', 'mail-organize', 'mail-mailboxes', 'mail-search',
|
||||
'mail-sync', 'calendar', 'contacts', 'tasks', 'files', 'settings', 'identities',
|
||||
'filters', 'vacation', 'templates', 'auth', 'security', 'theme', 'notifications', 'ui', 'keyboard',
|
||||
'filters', 'vacation', 'templates', 'auth', 'security', 'notifications', 'ui', 'keyboard',
|
||||
]);
|
||||
|
||||
describe('hook catalogue', () => {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { clearAllHooks, themeHooks } from '@/lib/plugin-hooks';
|
||||
import { useThemeStore } from '@/stores/theme-store';
|
||||
|
||||
beforeEach(() => {
|
||||
clearAllHooks();
|
||||
useThemeStore.setState({ theme: 'light', resolvedTheme: 'light', activeThemeId: null });
|
||||
});
|
||||
|
||||
describe('theme hooks', () => {
|
||||
it('tells plugins when the colour scheme changes', () => {
|
||||
const fn = vi.fn();
|
||||
themeHooks.onThemeChange.register('t', fn);
|
||||
|
||||
useThemeStore.getState().setTheme('dark');
|
||||
|
||||
expect(fn).toHaveBeenCalledWith({ theme: 'dark', resolved: 'dark' });
|
||||
});
|
||||
|
||||
it('tells plugins when another theme is activated, and not when nothing changed', () => {
|
||||
const fn = vi.fn();
|
||||
themeHooks.onCustomThemeChange.register('t', fn);
|
||||
|
||||
useThemeStore.setState({ activeThemeId: 'ocean' });
|
||||
useThemeStore.setState({ activeThemeId: 'ocean' });
|
||||
|
||||
expect(fn).toHaveBeenCalledTimes(1);
|
||||
expect(fn).toHaveBeenCalledWith({ themeId: 'ocean' });
|
||||
});
|
||||
});
|
||||
+11
-1
@@ -644,4 +644,14 @@ async function downloadThemeAsset(theme: ServerThemeInfo, kind: 'css' | 'skin'):
|
||||
console.warn(`[theme-store] Failed to download ${kind} for theme "${theme.id}"`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Plugins hear about every change of scheme or theme, whichever path made it
|
||||
// (settings, the system switching to dark, a forced admin theme).
|
||||
useThemeStore.subscribe((state, prev) => {
|
||||
if (state.theme !== prev.theme || state.resolvedTheme !== prev.resolvedTheme) {
|
||||
void themeHooks.onThemeChange.emit({ theme: state.theme, resolved: state.resolvedTheme });
|
||||
}
|
||||
if (state.activeThemeId !== prev.activeThemeId) {
|
||||
void themeHooks.onCustomThemeChange.emit({ themeId: state.activeThemeId });
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user