06e5114174
* feat: add clickable terminal links with configurable open behavior Add @xterm/addon-web-links to both passthrough and shell terminals, enabling Cmd+Click on URLs. Users can configure whether links open in a new browser tab (default) or the built-in browser panel via a new setting in the Settings page. * style: fix prettier formatting * fix: address CodeRabbit review comments - Extract applyTerminalLinkBehavior helper to reduce complexity - Set default terminalLinkBehavior for first-time users in empty settings path - Use storeApi.getState() for optimistic rollback to avoid stale closures - Add beforeEach settings reset in E2E tests - Use 4xx range assertion instead of hardcoded 500 * fix: return 400 for user settings validation errors Add ErrValidation sentinel to user service and wrap validation errors from apply* functions. Handler now returns 400 Bad Request instead of 500 Internal Server Error for invalid input. Update E2E test assertion to enforce client error status (< 500). * fix: remove cmd+click mention from terminal links description * fix: mirror validation error handling in WS update path * style: fix prettier formatting
35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
import { useCallback, useEffect, useRef } from "react";
|
|
import { useAppStore } from "@/components/state-provider";
|
|
import { useDockviewStore } from "@/lib/state/dockview-store";
|
|
|
|
/**
|
|
* Returns a stable callback for handling terminal link clicks.
|
|
* Reads the user's `terminalLinkBehavior` setting to decide whether
|
|
* to open URLs in a new browser tab or the built-in browser panel.
|
|
*/
|
|
export function useTerminalLinkHandler(): (event: MouseEvent, uri: string) => void {
|
|
const behaviorRef = useRef<"new_tab" | "browser_panel">("new_tab");
|
|
const behavior = useAppStore((s) => s.userSettings.terminalLinkBehavior);
|
|
|
|
useEffect(() => {
|
|
behaviorRef.current = behavior;
|
|
}, [behavior]);
|
|
|
|
return useCallback((_event: MouseEvent, uri: string) => {
|
|
if (behaviorRef.current === "browser_panel") {
|
|
const api = useDockviewStore.getState().api;
|
|
if (api) {
|
|
const browserId = `browser:${Date.now()}`;
|
|
api.addPanel({
|
|
id: browserId,
|
|
component: "browser",
|
|
title: "Browser",
|
|
params: { url: uri },
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
window.open(uri, "_blank", "noopener,noreferrer");
|
|
}, []);
|
|
}
|