Skip to content

feat(settings): add CDP settings UI and DevTools toggle#1374

Merged
IceyLiu merged 3 commits intomainfrom
feat/cdp-settings-ui
Mar 17, 2026
Merged

feat(settings): add CDP settings UI and DevTools toggle#1374
IceyLiu merged 3 commits intomainfrom
feat/cdp-settings-ui

Conversation

@kaizhou-lab
Copy link
Copy Markdown
Collaborator

@kaizhou-lab kaizhou-lab commented Mar 17, 2026

Summary

Restore the CDP Settings UI that was accidentally removed in #1095, and add a DevTools toggle button.

  • Restore CDP settings panel in System Settings (enable/disable, port display, URL copy, MCP config copy, restart alert) — dev mode only
  • Add DevTools open/close toggle button in System Settings
  • Pin chrome-devtools-mcp to @0.16.0 in docs and log output to avoid breakage from upstream changes (keep @latest in getDefaultMcpServers for end-user WebUI)
  • Add 13 unit tests covering CdpSettings and DevTools toggle

Closes #1375

Test plan

  • 13 unit tests pass (bun run test -- tests/unit/SystemModalContent.dom.test.tsx)
  • Verify CDP settings panel renders in dev mode and is hidden in production
  • Verify enable/disable switch saves config and shows restart alert
  • Verify DevTools toggle button opens/closes DevTools
  • Verify MCP config copy contains correct port

zk added 3 commits March 17, 2026 19:47
- Add CDP (Chrome DevTools Protocol) configuration panel in system
  settings with enable/disable switch, port display, and MCP config
  copy functionality (only visible in dev mode)
- Add DevTools open/close toggle button in system settings
- Pin chrome-devtools-mcp version from @latest to @0.16.0
The default MCP server config is for end users (WebUI), so it should
use @latest to always get the newest version.
Cover CdpSettings component (render in dev mode, toggle enable,
error handling, restart alert, disabled hint, MCP config display,
open URL) and DevTools toggle button (render, click, event listener).
@IceyLiu IceyLiu merged commit 75834d7 into main Mar 17, 2026
36 of 42 checks passed
@piorpua piorpua deleted the feat/cdp-settings-ui branch March 17, 2026 12:01
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores the developer-facing CDP settings panel in System Settings and adds a DevTools open/close toggle, plus pins the documented/logged chrome-devtools-mcp version to avoid upstream breakage.

Changes:

  • Add CDP settings UI (dev-mode only) with enable/disable, port display, URL open/copy, MCP config copy, and restart-required alert.
  • Add DevTools open/close toggle button in System Settings and subscribe to main-process state updates.
  • Pin chrome-devtools-mcp to @0.16.0 in docs and CDP log output; add unit tests for the new UI.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
tests/unit/SystemModalContent.dom.test.tsx Adds DOM tests for DevTools toggle + CDP settings UI behavior.
src/renderer/components/SettingsModal/contents/SystemModalContent.tsx Implements CDP settings panel and DevTools toggle UI in System Settings.
src/index.ts Pins CDP log output MCP command to [email protected].
docs/cdp.md Pins documented MCP config to [email protected].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const result = await ipcBridge.application.updateCdpConfig.invoke({ enabled: checked });
if (result.success) {
Message.success(t('settings.cdp.configSaved'));
await mutate('cdp.status');
Comment on lines +163 to +165
void navigator.clipboard.writeText(config).then(() => {
Message.success(t('common.copySuccess'));
});
Comment on lines +109 to +152
let swrCache: Record<string, any> = {};
let swrMutateCallback: ((key: string) => void) | null = null;

vi.mock('swr', () => {
const useSWR = (key: string, fetcher: () => Promise<any>) => {
const [data, setData] = React.useState<any>(undefined);
const [isLoading, setIsLoading] = React.useState(true);

React.useEffect(() => {
if (swrCache[key] !== undefined) {
setData(swrCache[key]);
setIsLoading(false);
return;
}
fetcher().then((result) => {
swrCache[key] = result;
setData(result);
setIsLoading(false);
});
}, [key]);

// Register mutate listener
React.useEffect(() => {
swrMutateCallback = (mutateKey: string) => {
if (mutateKey === key) {
fetcher().then((result) => {
swrCache[key] = result;
setData(result);
});
}
};
}, [key]);

return { data, isLoading, error: undefined };
};

const mutate = (key: string) => {
if (swrMutateCallback) swrMutateCallback(key);
return Promise.resolve();
};

useSWR.default = useSWR;
return { default: useSWR, mutate };
});
Comment on lines +100 to +176
const { data: cdpStatus, isLoading } = useSWR('cdp.status', () => ipcBridge.application.getCdpStatus.invoke());
const [switchLoading, setSwitchLoading] = useState(false);

const status = cdpStatus?.data;

// Track the pending state (config saved but not yet applied)
const hasPendingChange = status?.startupEnabled !== status?.enabled;

const handleToggle = async (checked: boolean) => {
setSwitchLoading(true);
try {
const result = await ipcBridge.application.updateCdpConfig.invoke({ enabled: checked });
if (result.success) {
Message.success(t('settings.cdp.configSaved'));
await mutate('cdp.status');
} else {
Message.error(result.msg || t('settings.cdp.configFailed'));
}
} catch {
Message.error(t('settings.cdp.configFailed'));
} finally {
setSwitchLoading(false);
}
};

const handleRestart = async () => {
try {
await ipcBridge.application.restart.invoke();
} catch {
Message.error(t('common.error'));
}
};

const openCdpUrl = () => {
if (status?.port) {
const url = `http://127.0.0.1:${status.port}/json`;
ipcBridge.shell.openExternal.invoke(url).catch(console.error);
}
};

const copyCdpUrl = () => {
if (status?.port) {
const url = `http://127.0.0.1:${status.port}`;
void navigator.clipboard.writeText(url).then(() => {
Message.success(t('common.copySuccess'));
});
}
};

const copyMcpConfig = () => {
if (status?.port) {
const config = `{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"-y",
"[email protected]",
"--browser-url=http://127.0.0.1:${status.port}"
]
}
}
}`;
void navigator.clipboard.writeText(config).then(() => {
Message.success(t('common.copySuccess'));
});
}
};

// Only show CDP settings in development mode
if (!isLoading && status?.isDevMode === false) {
return null;
}

if (isLoading) {
return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(settings): restore CDP settings UI and pin chrome-devtools-mcp version

3 participants