feat(app): 활성 창 캡쳐·캡쳐 목적지 선택·단축키 Ctrl+Alt 재배치 + UX 손질
- Ctrl+Alt+A/Z 맨 앞 창 통째 캡쳐(DWM 확장 프레임 경계), S/X 드래그 캡쳐. A/S 새 대화, Z/X 마지막 대화 - 캡쳐 후 창을 확실히 앞으로(AttachThreadInput), capture.image 에 목적지 path 실어 그 Composer 만 소비 - 드래그 선택영역 원본 밝기·더블버퍼(번쩍임) — code-assistant-v2 복사본에서 이식 - 단축키 Ctrl+Alt+Q/W: Eclipse·ADT·SAP GUI 바인딩 목록 대조해 비어 있는 조합으로 - 버튼 cursor:pointer(Tailwind v4), 가운데 스피너, 스니펫→챗 버튼, 스니펫 검색창 높이 84→88 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
2869985139
commit
47d31dbe06
@@ -29,15 +29,20 @@ describe("bridgeNavigate", () => {
|
||||
|
||||
await emit("bridge", { type: "navigate", path: "/snippet" })
|
||||
await emit("bridge", { type: "paste.target", name: "메모장", app: "notepad" })
|
||||
await emit("bridge", { type: "capture.image", dataUrl: "data:image/png;base64,abc" })
|
||||
await emit("bridge", {
|
||||
type: "capture.image",
|
||||
path: "/snap/new",
|
||||
dataUrl: "data:image/png;base64,abc",
|
||||
})
|
||||
|
||||
expect(navigate).toHaveBeenCalledWith("/snippet")
|
||||
expect(onNavigate).toHaveBeenCalledTimes(1)
|
||||
expect(getLastPasteTarget()).toEqual({ name: "메모장", app: "notepad" })
|
||||
expect(onPasteTarget).toHaveBeenCalledTimes(1)
|
||||
expect(onCapture).toHaveBeenCalledTimes(1)
|
||||
expect(consumePendingCaptureImage()).toBe("data:image/png;base64,abc")
|
||||
expect(consumePendingCaptureImage()).toBe("")
|
||||
expect(consumePendingCaptureImage("/snap/s/old")).toBe("")
|
||||
expect(consumePendingCaptureImage("/snap/new")).toBe("data:image/png;base64,abc")
|
||||
expect(consumePendingCaptureImage("/snap/new")).toBe("")
|
||||
|
||||
window.removeEventListener("bridge:navigate", onNavigate)
|
||||
window.removeEventListener("bridge:pasteTarget", onPasteTarget)
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface PasteTarget {
|
||||
|
||||
let navigateFn: NavigateFn | null = null
|
||||
let lastPasteTarget: PasteTarget = { name: "", app: "" }
|
||||
let pendingCaptureImage = ""
|
||||
let pendingCaptureImage: { path: string; dataUrl: string } | null = null
|
||||
|
||||
/** 앱 루트에서 useNavigate() 감싼 콜백을 등록함. */
|
||||
export function setBridgeNavigate(fn: NavigateFn | null) {
|
||||
@@ -21,10 +21,11 @@ export function getLastPasteTarget(): PasteTarget {
|
||||
return lastPasteTarget
|
||||
}
|
||||
|
||||
/** 마지막 캡처 이미지를 한 번만 소비함. */
|
||||
export function consumePendingCaptureImage(): string {
|
||||
const dataUrl = pendingCaptureImage
|
||||
pendingCaptureImage = ""
|
||||
/** 지정한 대화에 도착한 마지막 캡처 이미지를 한 번만 소비함. */
|
||||
export function consumePendingCaptureImage(path: string): string {
|
||||
if (pendingCaptureImage?.path !== path) return ""
|
||||
const { dataUrl } = pendingCaptureImage
|
||||
pendingCaptureImage = null
|
||||
return dataUrl
|
||||
}
|
||||
|
||||
@@ -41,11 +42,9 @@ function handleBridgeMessage(data: {
|
||||
return
|
||||
}
|
||||
|
||||
if (data.type === "capture.image") {
|
||||
pendingCaptureImage = data.dataUrl ?? ""
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("bridge:captureImage", { detail: { dataUrl: pendingCaptureImage } })
|
||||
)
|
||||
if (data.type === "capture.image" && data.path) {
|
||||
pendingCaptureImage = { path: data.path, dataUrl: data.dataUrl ?? "" }
|
||||
window.dispatchEvent(new CustomEvent("bridge:captureImage", { detail: pendingCaptureImage }))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user