diff --git a/client/src/components/Plugins/PluginFrame.test.tsx b/client/src/components/Plugins/PluginFrame.test.tsx index 545ec0243..fadb9efcc 100644 --- a/client/src/components/Plugins/PluginFrame.test.tsx +++ b/client/src/components/Plugins/PluginFrame.test.tsx @@ -12,7 +12,7 @@ vi.mock('react-router-dom', () => ({ useNavigate: () => navigate })); vi.mock('../shared/Toast', () => ({ useToast: () => toast })); vi.mock('../../i18n', () => ({ useTranslation: () => ({ locale: 'en', t: (k: string) => k }) })); vi.mock('../../store/authStore', () => ({ useAuthStore: (sel: (s: unknown) => unknown) => sel({ user: { id: 7, username: 'ada', avatar_url: null, role: 'admin' } }) })); -vi.mock('../../store/settingsStore', () => ({ useSettingsStore: (sel: (s: unknown) => unknown) => sel({ settings: { default_currency: 'EUR', time_format: '24h', distance_unit: 'metric', temperature_unit: 'celsius' } }) })); +vi.mock('../../store/settingsStore', () => ({ useSettingsStore: (sel: (s: unknown) => unknown) => sel({ settings: { default_currency: 'EUR', time_format: '24h', distance_unit: 'metric', temperature_unit: 'celsius', blur_booking_codes: true } }) })); vi.mock('../../api/client', () => ({ pluginsApi: { invoke: (id: string, sub: string, init?: unknown) => invoke(id, sub, init) } })); vi.mock('../../api/websocket', () => ({ addListener: (fn: (ev: Record) => void) => wsListeners.add(fn), @@ -84,7 +84,13 @@ describe('PluginFrame', () => { const ctx = posted.find((m) => m.type === 'trek:context') as Record | undefined; expect(ctx).toBeTruthy(); expect(ctx!.tokens).toBeTruthy(); // resolved design tokens (empty {} in jsdom, but present) - expect(ctx!.formats).toMatchObject({ currency: 'EUR', timeFormat: '24h', distanceUnit: 'metric' }); + expect(ctx!.formats).toMatchObject({ + currency: 'EUR', + timeFormat: '24h', + distanceUnit: 'metric', + temperatureUnit: 'celsius', + blurBookingCodes: true, + }); // Display identity is present but carries NO secret (no email, role only as a boolean). expect(ctx!.user).toMatchObject({ name: 'ada', isAdmin: true }); expect(JSON.stringify(ctx)).not.toContain('@'); // no email leaked diff --git a/client/src/components/Plugins/PluginFrame.tsx b/client/src/components/Plugins/PluginFrame.tsx index 442b6207a..4c38dd7b7 100644 --- a/client/src/components/Plugins/PluginFrame.tsx +++ b/client/src/components/Plugins/PluginFrame.tsx @@ -218,6 +218,7 @@ export default function PluginFrame({ pluginId, tripId = null, placeId = null, d distanceUnit: settings.distance_unit, temperatureUnit: settings.temperature_unit, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + blurBookingCodes: Boolean(settings.blur_booking_codes), }, tokens: readThemeTokens(), }), [tripId, placeId, dayId, reservationId, userId, locale, userName, userAvatar, isAdmin, settings]) diff --git a/plugin-sdk/src/cli/dev.ts b/plugin-sdk/src/cli/dev.ts index 60953f73a..2215869e8 100644 --- a/plugin-sdk/src/cli/dev.ts +++ b/plugin-sdk/src/cli/dev.ts @@ -658,7 +658,7 @@ function ctx(){ tripId: val("trip").checked?${tripId}:null, userId:"1", user:{name:"Dev User",avatar:null,isAdmin:true}, appearance:{scheme:accent,density:"comfortable",reducedMotion:val("rm").checked,noTransparency:val("nt").checked}, - formats:{locale:"en",currency:"EUR",timeFormat:"24h",distanceUnit:"metric",temperatureUnit:"celsius",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone}, + formats:{locale:"en",currency:"EUR",timeFormat:"24h",distanceUnit:"metric",temperatureUnit:"celsius",timezone:Intl.DateTimeFormat().resolvedOptions().timeZone,blurBookingCodes:false}, tokens:tokens}; } function postCtx(){ if(f.contentWindow) f.contentWindow.postMessage(ctx(),"*"); } diff --git a/wiki/Plugin-Development.md b/wiki/Plugin-Development.md index 402cf06be..be0e9224d 100644 --- a/wiki/Plugin-Development.md +++ b/wiki/Plugin-Development.md @@ -533,7 +533,7 @@ declared), no popups. | `locale` | e.g. `'en'` | | `hostOrigin` | the app origin | | `user` | `{ name, avatar, isAdmin } \| null` — **never** an email; role only as a boolean | -| `formats` | `{ locale, currency, timeFormat, distanceUnit, temperatureUnit, timezone }` | +| `formats` | `{ locale, currency, timeFormat, distanceUnit, temperatureUnit, timezone, blurBookingCodes }` | | `tokens` | TREK's resolved CSS design tokens for the current theme (see below) | | `appearance` | `{ scheme, density: 'comfortable'\|'compact', reducedMotion, noTransparency }` |