fix(ui): compact embedded chat URLs (#2431)
* fix(ui): keep embedded session chat URLs compact * test(ui): guard embedded session chat URL length * fix(ui): sync embedded custom themes Bootstrap custom themes from parent window so iframe URLs stay compact. Refs #2423 * docs(ui): clarify theme sync precedence
This commit is contained in:
@@ -2457,6 +2457,10 @@ export const ContextPanel: React.FC = () => {
|
||||
}
|
||||
|
||||
const data = event.data as { type?: unknown };
|
||||
if (data?.type === 'openchamber:theme-sync-request') {
|
||||
postThemeSyncToEmbeddedChat();
|
||||
return;
|
||||
}
|
||||
if (data?.type === 'openchamber:chat-settings-request') {
|
||||
postChatSettingsSyncToEmbeddedChat();
|
||||
return;
|
||||
@@ -2473,7 +2477,7 @@ export const ContextPanel: React.FC = () => {
|
||||
|
||||
window.addEventListener('message', handleMessage);
|
||||
return () => window.removeEventListener('message', handleMessage);
|
||||
}, [postChatSettingsSyncToEmbeddedChat, setThemeMode, themeMode]);
|
||||
}, [postChatSettingsSyncToEmbeddedChat, postThemeSyncToEmbeddedChat, setThemeMode, themeMode]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
const hasAnyChatTab = tabs.some((tab) => tab.mode === 'chat');
|
||||
|
||||
@@ -50,7 +50,7 @@ afterAll(() => {
|
||||
});
|
||||
|
||||
describe('embedded session chat URL', () => {
|
||||
test('includes parent effective system theme bootstrap data', () => {
|
||||
test('includes compact parent theme bootstrap data', () => {
|
||||
const currentTheme = makeTheme('custom-dark', 'dark');
|
||||
|
||||
const src = buildEmbeddedSessionChatURL('ses_1', '/repo', false, {
|
||||
@@ -67,7 +67,41 @@ describe('embedded session chat URL', () => {
|
||||
expect(url.searchParams.get('themeVariant')).toBe('dark');
|
||||
expect(url.searchParams.get('lightThemeId')).toBe('custom-light');
|
||||
expect(url.searchParams.get('darkThemeId')).toBe('custom-dark');
|
||||
expect(JSON.parse(url.searchParams.get('currentTheme') || '{}').metadata.id).toBe('custom-dark');
|
||||
expect(url.searchParams.get('currentTheme')).toBeNull();
|
||||
});
|
||||
|
||||
test('does not encode syntax tokens in the URL', () => {
|
||||
const currentTheme = makeTheme('token-rich-dark', 'dark');
|
||||
currentTheme.colors.syntax.tokens = Object.fromEntries(
|
||||
Array.from({ length: 500 }, (_, index) => [`token-${index}`, `#${index.toString(16).padStart(6, '0')}`]),
|
||||
);
|
||||
|
||||
const src = buildEmbeddedSessionChatURL(
|
||||
'ses_abcdefghijklmnopqrstuvwxyz0123456789',
|
||||
'/workspace/projects/openchamber',
|
||||
true,
|
||||
{
|
||||
mode: 'system',
|
||||
lightThemeId: 'token-rich-light',
|
||||
darkThemeId: 'token-rich-dark',
|
||||
currentTheme,
|
||||
},
|
||||
);
|
||||
|
||||
const srcWithoutTokens = buildEmbeddedSessionChatURL(
|
||||
'ses_abcdefghijklmnopqrstuvwxyz0123456789',
|
||||
'/workspace/projects/openchamber',
|
||||
true,
|
||||
{
|
||||
mode: 'system',
|
||||
lightThemeId: 'token-rich-light',
|
||||
darkThemeId: 'token-rich-dark',
|
||||
currentTheme: makeTheme('token-rich-dark', 'dark'),
|
||||
},
|
||||
);
|
||||
|
||||
expect(new URL(src).searchParams.get('currentTheme')).toBeNull();
|
||||
expect(src).toBe(srcWithoutTokens);
|
||||
});
|
||||
|
||||
test('freezes bootstrap src per tab so live theme changes do not reload iframe', () => {
|
||||
|
||||
@@ -46,7 +46,6 @@ export const buildEmbeddedSessionChatURL = (
|
||||
url.searchParams.set('lightThemeId', theme.lightThemeId);
|
||||
url.searchParams.set('darkThemeId', theme.darkThemeId);
|
||||
url.searchParams.set('themeVariant', theme.currentTheme.metadata.variant === 'dark' ? 'dark' : 'light');
|
||||
url.searchParams.set('currentTheme', JSON.stringify(theme.currentTheme));
|
||||
|
||||
url.hash = '';
|
||||
return url.toString();
|
||||
@@ -126,4 +125,4 @@ export const getEmbeddedSessionChatOriginSessionId = (): string | null => {
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user