import { useCallback, useEffect, useRef, useState } from "react"; import { LuCornerDownLeft } from "react-icons/lu"; import { ExclamationCircleIcon } from "@heroicons/react/16/solid"; import { useClose } from "@headlessui/react"; import { Button } from "@components/Button"; import { GridCard } from "@components/Card"; import { TextAreaWithLabel } from "@components/TextArea"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; import { useHidStore, useRTCStore, useUiStore, useSettingsStore } from "@/hooks/stores"; import { keys } from "@/keyboardMappings"; import useKeyboardLayout from "@/hooks/useKeyboardLayout"; import useKeyboard from "../../hooks/useKeyboard"; export default function PasteModal() { const TextAreaRef = useRef(null); const { setPasteModeEnabled } = useHidStore(); const { setDisableVideoFocusTrap } = useUiStore(); const { send } = useJsonRpc(); const { rpcDataChannel } = useRTCStore(); const [invalidChars, setInvalidChars] = useState([]); const close = useClose(); const { handleKeyPress } = useKeyboard(); const { setKeyboardLayout } = useSettingsStore(); const { selectedKeyboard } = useKeyboardLayout(); useEffect(() => { send("getKeyboardLayout", {}, (resp: JsonRpcResponse) => { if ("error" in resp) return; setKeyboardLayout(resp.result as string); }); }, [send, setKeyboardLayout]); const onCancelPasteMode = useCallback(() => { setPasteModeEnabled(false); setDisableVideoFocusTrap(false); setInvalidChars([]); }, [setDisableVideoFocusTrap, setPasteModeEnabled]); const onConfirmPaste = useCallback(async () => { setPasteModeEnabled(false); setDisableVideoFocusTrap(false); if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return; if (!selectedKeyboard) return; for (let i = 0; i < 5; i++) { for (let i = 0; i < 26; i++) { handleKeyPress(keys[`Key${String.fromCharCode(65 + i)}`], true); await new Promise(resolve => setTimeout(resolve, 50)); handleKeyPress(keys[`Key${String.fromCharCode(65 + i)}`], false); await new Promise(resolve => setTimeout(resolve, 50)); } await new Promise(resolve => setTimeout(resolve, 50)); handleKeyPress(keys.Enter, true); await new Promise(resolve => setTimeout(resolve, 50)); handleKeyPress(keys.Enter, false); await new Promise(resolve => setTimeout(resolve, 50)); } // for (let index = 0; index < 2; index++) { // handleKeyPress(keys.KeyA, true); // await new Promise(resolve => setTimeout(resolve, 3000)); // handleKeyPress(keys.KeyA, false); // } }, [setPasteModeEnabled, setDisableVideoFocusTrap, rpcDataChannel?.readyState, selectedKeyboard, handleKeyPress]); useEffect(() => { if (TextAreaRef.current) { TextAreaRef.current.focus(); } }, []); return (
e.stopPropagation()} onKeyDown={e => e.stopPropagation()}> e.stopPropagation()} onKeyDown={e => { e.stopPropagation(); if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); onConfirmPaste(); } else if (e.key === "Escape") { e.preventDefault(); onCancelPasteMode(); } }} onChange={e => { const value = e.target.value; const invalidChars = [ ...new Set( // @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments [...new Intl.Segmenter().segment(value)] .map(x => x.segment) .filter(char => !selectedKeyboard.chars[char]), ), ]; setInvalidChars(invalidChars); }} /> {invalidChars.length > 0 && (
The following characters won't be pasted:{" "} {invalidChars.join(", ")}
)}

Sending text using keyboard layout: {selectedKeyboard.isoCode}-{selectedKeyboard.name}

); }