Просмотр исходного кода

fix(app): terminal hyperlink clicks

Adam 2 недель назад
Родитель
Сommit
57b8c62909
1 измененных файлов с 21 добавлено и 0 удалено
  1. 21 0
      packages/app/src/components/terminal.tsx

+ 21 - 0
packages/app/src/components/terminal.tsx

@@ -1,5 +1,6 @@
 import type { Ghostty, Terminal as Term, FitAddon } from "ghostty-web"
 import { ComponentProps, createEffect, createSignal, onCleanup, onMount, splitProps } from "solid-js"
+import { usePlatform } from "@/context/platform"
 import { useSDK } from "@/context/sdk"
 import { monoFontFamily, useSettings } from "@/context/settings"
 import { SerializeAddon } from "@/addons/serialize"
@@ -52,6 +53,7 @@ const DEFAULT_TERMINAL_COLORS: Record<"light" | "dark", TerminalColors> = {
 }
 
 export const Terminal = (props: TerminalProps) => {
+  const platform = usePlatform()
   const sdk = useSDK()
   const settings = useSettings()
   const theme = useTheme()
@@ -135,6 +137,22 @@ export const Terminal = (props: TerminalProps) => {
     focusTerminal()
   }
 
+  const handleLinkClick = (event: MouseEvent) => {
+    if (!event.shiftKey && !event.ctrlKey && !event.metaKey) return
+    if (event.altKey) return
+    if (event.button !== 0) return
+
+    const t = term
+    if (!t) return
+
+    const link = (t as unknown as { currentHoveredLink?: { text: string } }).currentHoveredLink
+    if (!link?.text) return
+
+    event.preventDefault()
+    event.stopImmediatePropagation()
+    platform.openLink(link.text)
+  }
+
   onMount(() => {
     const run = async () => {
       const loaded = await loadGhostty()
@@ -240,6 +258,9 @@ export const Terminal = (props: TerminalProps) => {
       container.addEventListener("pointerdown", handlePointerDown)
       cleanups.push(() => container.removeEventListener("pointerdown", handlePointerDown))
 
+      container.addEventListener("click", handleLinkClick, { capture: true })
+      cleanups.push(() => container.removeEventListener("click", handleLinkClick, { capture: true }))
+
       handleTextareaFocus = () => {
         t.options.cursorBlink = true
       }