import Input from "@tensamin/markdown/input"; import { Card, CardHeader, Popover, PopoverContent, PopoverTrigger, } from "@tensamin/ui"; import { useStorage } from "@tensamin/storage/context"; import * as React from "react"; import { Button } from "@tensamin/ui"; import { Plus, Laugh, FileVideo } from "lucide-react"; import { useChat } from "../context"; import { useMTP } from "@tensamin/mtp"; import { log, toast } from "@tensamin/shared/log"; import { cn, useIsMobile } from "@tensamin/ui"; import { useSession } from "@tensamin/storage/session"; import GifPicker from "./gifPicker"; export default function InputComponent({ value, setValue, }: { value: string; setValue: (value: string) => void; }) { const [invertEnterBehavior, setInvertEnterBehavior] = React.useState(false); const { sendEncrypted } = useMTP(); const { addLiveMessage, userId, inputBoxRef } = useChat(); const { load, save } = useStorage(); const { moveUserIdToTop } = useSession(); const gifPopoverRef = React.useRef(null); const [gifPopoverOpen, setGifPopoverOpen] = React.useState(false); const [gifPopoverSize, setGifPopoverSize] = React.useState<{ width: number; height: number; }>(); React.useEffect(() => { void load("settings.reverse_enter_behavior").then((shouldInvert) => { setInvertEnterBehavior(shouldInvert); }); }, [load]); React.useEffect(() => { void load("chat_picker_size").then((size) => { if (size) { setGifPopoverSize(size); } }); }, [load]); async function handleSubmit(content = value, preserveContent = false) { if (content.trim() === "") return; const time = Date.now(); const currentValue = content; if (!Number.isSafeInteger(userId) || userId <= 0) { toast("error", "No conversation selected"); return; } log(3, "chat", "purple", "Message send init, adding live message ..."); const reference = addLiveMessage({ NotEncrypted: true, SendTime: time, Content: currentValue, SentBySelf: true, MessageState: "awaiting", }); log(3, "chat", "purple", "Live message added, sending encrypted frame..."); void load("user_id") .then((ownUserId) => sendEncrypted( "MessageSend", { Content: currentValue, ReceiverId: userId, SendTime: time, }, { senderUserId: String(ownUserId), recipientUserId: String(userId), }, ), ) .catch((e) => { log(0, "Chat", "red", "Failed to send encrypted message", e, { ReceiverId: userId, SendTime: time, }); reference.setFailed(true); toast( "error", e instanceof Error && e.message.includes("public key") ? "Recipient has no encryption public key available" : "Failed to send encrypted message", ); }); log(3, "chat", "purple", "Encrypted message send queued"); moveUserIdToTop(userId); if (!preserveContent) { setValue(""); } } const isMobile = useIsMobile(); function handleGifPopoverResizeStart( event: React.PointerEvent, ) { const popover = gifPopoverRef.current; if (!popover) return; event.preventDefault(); event.stopPropagation(); const rect = popover.getBoundingClientRect(); const startX = event.clientX; const startY = event.clientY; const startWidth = rect.width; const startHeight = rect.height; const minSize = 40; const maxSize = 720; function clampSize(size: number) { return Math.min(Math.max(size, minSize), maxSize); } function handlePointerMove(moveEvent: PointerEvent) { const nextSize = { width: clampSize(startWidth + startX - moveEvent.clientX), height: clampSize(startHeight + startY - moveEvent.clientY), }; setGifPopoverSize(nextSize); } function handlePointerUp() { const popover = gifPopoverRef.current; if (popover) { const rect = popover.getBoundingClientRect(); void save("chat_picker_size", { width: clampSize(rect.width), height: clampSize(rect.height), }); } window.removeEventListener("pointermove", handlePointerMove); window.removeEventListener("pointerup", handlePointerUp); } window.addEventListener("pointermove", handlePointerMove); window.addEventListener("pointerup", handlePointerUp); } return (

Files list

} /> event.stopPropagation()} onWheelCapture={(event) => event.stopPropagation()} style={{ ...gifPopoverSize, maxHeight: gifPopoverSize?.height, }} >
{ void handleSubmit(url, true); setGifPopoverOpen(false); }} />
); }