feat: show the colour mode as set by the organisation when its policy locks it

This commit is contained in:
Linus Rath
2026-10-31 15:22:15 +01:00
parent 2b3e84a5a0
commit b7b3dd4c4d
2 changed files with 23 additions and 1 deletions
@@ -7,6 +7,7 @@ import { useSettingsStore, type ThemeMode, type Density } from '../../stores/set
import { useLocaleStore } from '../../stores/locale-store'; import { useLocaleStore } from '../../stores/locale-store';
import { setPendingSettingsTab } from '../../navigation/pending-settings-tab'; import { setPendingSettingsTab } from '../../navigation/pending-settings-tab';
import { densityPreviewConfig } from './density-preview'; import { densityPreviewConfig } from './density-preview';
import { useSettingLocked } from '../../stores/policy-store';
type Theme = ThemeMode; type Theme = ThemeMode;
@@ -81,6 +82,8 @@ export function AppearanceSettings() {
const theme = useSettingsStore((s) => s.theme); const theme = useSettingsStore((s) => s.theme);
const t = useLocaleStore((s) => s.t); const t = useLocaleStore((s) => s.t);
const setTheme = useSettingsStore((s) => s.setTheme); const setTheme = useSettingsStore((s) => s.setTheme);
// The organisation's theme policy can pin the colour mode (#1280).
const themeLocked = useSettingLocked('theme');
const density = useSettingsStore((s) => s.density); const density = useSettingsStore((s) => s.density);
const setDensity = useSettingsStore((s) => s.setDensity); const setDensity = useSettingsStore((s) => s.setDensity);
const showToolbarLabels = useSettingsStore((s) => s.showToolbarLabels); const showToolbarLabels = useSettingsStore((s) => s.showToolbarLabels);
@@ -99,7 +102,7 @@ export function AppearanceSettings() {
title={t('settings.appearance.title', "Appearance")} title={t('settings.appearance.title', "Appearance")}
description={t('settings.appearance.description_mobile', 'Customize how the app looks')} description={t('settings.appearance.description_mobile', 'Customize how the app looks')}
> >
<SettingItem label={t('settings.appearance.theme.label', "Theme")} description={t('settings.appearance.theme.description', "Choose your preferred color scheme")}> <SettingItem label={t('settings.appearance.theme.label', "Theme")} description={t('settings.appearance.theme.description', "Choose your preferred color scheme")} locked={themeLocked}>
<RadioGroup <RadioGroup
value={theme} value={theme}
onChange={(v) => setTheme(v as Theme)} onChange={(v) => setTheme(v as Theme)}
@@ -0,0 +1,19 @@
import { describe, expect, it } from 'vitest';
import fs from 'node:fs';
import path from 'node:path';
// Where the organisation policy reaches the settings pages. No React Native
// renderer in the test env, so this checks the wiring (as
// src/components/__tests__/org-policy-wiring.test.ts does); what the policy
// does to the settings is tested in org-policy.test.ts and policy-store.test.ts.
const read = (rel: string) => fs.readFileSync(path.resolve(__dirname, '..', '..', '..', '..', rel), 'utf8');
const settings = (name: string) => read(`src/components/settings/${name}.tsx`);
describe('organisation policy on the settings pages', () => {
it('shows the colour mode as set by the organisation when its theme policy locks it', () => {
const page = settings('AppearanceSettings');
expect(page).toContain("const themeLocked = useSettingLocked('theme');");
expect(page).toMatch(/label=\{t\('settings\.appearance\.theme\.label', "Theme"\)\}[^>]*locked=\{themeLocked\}>/);
});
});