[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
This commit is contained in:
111
components/terminal/hooks/useTerminalFilePaste.ts
Normal file
111
components/terminal/hooks/useTerminalFilePaste.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import type { Terminal as XTerm } from "@xterm/xterm";
|
||||
import type React from "react";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { netcattyBridge } from "../../../infrastructure/services/netcattyBridge";
|
||||
import { logger } from "../../../lib/logger";
|
||||
import type { TerminalSession } from "../../../types";
|
||||
import type { RemoteClipboardImageUploadResult } from "../clipboardImagePaste";
|
||||
import { handleTerminalClipboardPaste } from "../terminalClipboardPaste";
|
||||
|
||||
interface UseTerminalFilePasteOptions {
|
||||
isLocalConnection: boolean;
|
||||
status: TerminalSession["status"];
|
||||
termRef: React.MutableRefObject<XTerm | null>;
|
||||
sessionRef: React.MutableRefObject<string | null>;
|
||||
terminalBackend: {
|
||||
writeToSession: (sessionId: string, data: string, options?: { automated?: boolean; sensitive?: boolean }) => void;
|
||||
};
|
||||
isSensitiveInput?: () => boolean;
|
||||
scrollOnPasteRef?: React.RefObject<boolean>;
|
||||
onPasteData?: (data: string) => boolean | void;
|
||||
scrollToBottomAfterProgrammaticInput: (data: string) => void;
|
||||
containerRef: React.RefObject<HTMLDivElement | null>;
|
||||
/** Remote sessions only: auto-upload a clipboard image on paste. */
|
||||
autoUploadClipboardImage?: boolean;
|
||||
getRemoteCwd?: () => Promise<string | null | undefined>;
|
||||
onClipboardImageUploadResult?: (result: RemoteClipboardImageUploadResult) => void;
|
||||
}
|
||||
|
||||
export function useTerminalFilePaste({
|
||||
isLocalConnection,
|
||||
status,
|
||||
termRef,
|
||||
sessionRef,
|
||||
terminalBackend,
|
||||
isSensitiveInput,
|
||||
scrollOnPasteRef,
|
||||
onPasteData,
|
||||
scrollToBottomAfterProgrammaticInput,
|
||||
containerRef,
|
||||
autoUploadClipboardImage = false,
|
||||
getRemoteCwd,
|
||||
onClipboardImageUploadResult,
|
||||
}: UseTerminalFilePasteOptions) {
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
if (!container) return;
|
||||
|
||||
const handlePaste = (event: ClipboardEvent) => {
|
||||
if (status !== "connected") return;
|
||||
|
||||
const bridge = netcattyBridge.get();
|
||||
|
||||
const wantsImageUpload =
|
||||
autoUploadClipboardImage && !isLocalConnection && !!bridge?.readClipboardImage;
|
||||
const canHandleLocalPaste =
|
||||
isLocalConnection && !!(bridge?.readClipboardFiles || bridge?.hasClipboardImage);
|
||||
if (!wantsImageUpload && !canHandleLocalPaste) return;
|
||||
|
||||
// ⚡ Must call preventDefault SYNCHRONOUSLY — the event lifecycle
|
||||
// is synchronous; calling it after an await is too late and the
|
||||
// browser will have already performed the default paste action.
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
const term = termRef.current;
|
||||
if (!term) return;
|
||||
await handleTerminalClipboardPaste({
|
||||
bridge,
|
||||
autoUploadClipboardImage: wantsImageUpload,
|
||||
clipboardImageBridge: bridge ?? undefined,
|
||||
getRemoteCwd,
|
||||
isLocalConnection,
|
||||
isSensitiveInput,
|
||||
onClipboardImageUploadResult,
|
||||
readClipboardText: () => navigator.clipboard.readText(),
|
||||
scrollOnPaste: scrollOnPasteRef?.current ?? false,
|
||||
onPasteData,
|
||||
sessionId: sessionRef.current,
|
||||
terminalBackend,
|
||||
term,
|
||||
scrollToBottomAfterProgrammaticInput,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("Failed to handle file paste", error);
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
container.addEventListener("paste", handlePaste, true);
|
||||
return () => {
|
||||
container.removeEventListener("paste", handlePaste, true);
|
||||
};
|
||||
}, [
|
||||
autoUploadClipboardImage,
|
||||
containerRef,
|
||||
getRemoteCwd,
|
||||
isLocalConnection,
|
||||
isSensitiveInput,
|
||||
onClipboardImageUploadResult,
|
||||
onPasteData,
|
||||
scrollOnPasteRef,
|
||||
scrollToBottomAfterProgrammaticInput,
|
||||
sessionRef,
|
||||
status,
|
||||
terminalBackend,
|
||||
termRef,
|
||||
]);
|
||||
}
|
||||
Reference in New Issue
Block a user