Files
PrivyDrop/frontend/components/ClipboardApp/RetrieveTabPanel.tsx
T
2025-06-21 23:35:27 +08:00

177 lines
5.9 KiB
TypeScript

import React, { useCallback } from "react";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import RichTextEditor from "@/components/Editor/RichTextEditor";
import {
ReadClipboardButton,
WriteClipboardButton,
} from "@/components/common/clipboard_btn";
import FileListDisplay from "@/components/ClipboardApp/FileListDisplay";
import type { Messages } from "@/types/messages";
import type { FileMeta } from "@/types/webrtc";
import type { ProgressState } from "@/hooks/useWebRTCConnection"; // Assuming this type is exported
import type WebRTC_Recipient from "@/lib/webrtc_Recipient";
interface RetrieveTabPanelProps {
messages: Messages;
putMessageInMs: (
message: string,
isShareEnd?: boolean,
displayTimeMs?: number
) => void; // For onLocationPick
retrieveRoomStatusText: string;
retrieveRoomIdInput: string;
setRetrieveRoomIdInput: (value: string) => void;
joinRoom: (isSender: boolean, roomId: string) => void;
retrieveJoinRoomBtnRef: React.RefObject<HTMLButtonElement>;
receiver: WebRTC_Recipient | null;
retrievedContent: string;
// setRetrievedContent: (content: string) => void; // If editor becomes editable
richTextToPlainText: (html: string) => string;
retrievedFileMetas: FileMeta[];
receiveProgress: ProgressState;
handleDownloadFile: (meta: FileMeta) => void;
// Functions for WebRTC interaction, passed from parent via useWebRTCConnection
requestFile: (fileId: string, peerId?: string) => void;
requestFolder: (folderName: string, peerId?: string) => void;
setReceiverDirectoryHandle: (
directoryHandle: FileSystemDirectoryHandle
) => Promise<void>;
getReceiverSaveType: () => { [fileId: string]: boolean } | undefined;
retrieveMessage: string;
}
export function RetrieveTabPanel({
messages,
putMessageInMs,
retrieveRoomStatusText,
retrieveRoomIdInput,
setRetrieveRoomIdInput,
joinRoom,
retrieveJoinRoomBtnRef,
receiver,
retrievedContent,
richTextToPlainText,
retrievedFileMetas,
receiveProgress,
handleDownloadFile,
requestFile,
requestFolder,
setReceiverDirectoryHandle,
getReceiverSaveType,
retrieveMessage,
}: RetrieveTabPanelProps) {
const onLocationPick = useCallback(async (): Promise<boolean> => {
if (!messages) return false; // Should not happen if panel is rendered
if (!window.showDirectoryPicker) {
putMessageInMs(
// messages.text.ClipboardApp.pickSaveUnsupported ||
"Directory picker not supported.",
false
);
return false;
}
if (!window.confirm(messages.text.ClipboardApp.pickSaveMsg)) return false;
try {
const directoryHandle = await window.showDirectoryPicker();
await setReceiverDirectoryHandle(directoryHandle);
putMessageInMs(
// messages.text.ClipboardApp.pickSaveSuccess ||
"Save location set.",
false
);
return true;
} catch (err: any) {
if (err.name !== "AbortError") {
console.error("Failed to set up folder receive:", err);
putMessageInMs(
// messages.text.ClipboardApp.pickSaveError ||
"Could not set save location.",
false
);
}
return false;
}
}, [messages, putMessageInMs, setReceiverDirectoryHandle]);
const handleFileRequestFromPanel = useCallback(
(meta: FileMeta) => {
if (meta.folderName) {
requestFolder(meta.folderName);
} else if (meta.fileId) {
requestFile(meta.fileId);
} else {
console.warn("Cannot request file from panel: missing fileId", meta);
// Optionally use putMessageInMs to inform user
}
},
[requestFile, requestFolder]
);
return (
<div id="retrieve-panel" role="tabpanel" aria-labelledby="retrieve-tab">
<div className="mb-3 text-sm text-gray-600">
{retrieveRoomStatusText ||
(receiver && receiver.isInRoom
? messages.text.ClipboardApp.roomStatus.connected_dis
: messages.text.ClipboardApp.roomStatus.receiverEmptyMsg)}
</div>
<div className="flex flex-col sm:flex-row items-center gap-2 mb-3">
<ReadClipboardButton
title={messages.text.ClipboardApp.html.readClipboard_dis}
onRead={setRetrieveRoomIdInput}
/>
<Input
aria-label="Retrieve Room ID"
value={retrieveRoomIdInput}
onChange={(e) => setRetrieveRoomIdInput(e.target.value)}
placeholder={
messages.text.ClipboardApp.html.retrieveRoomId_placeholder
}
className="flex-grow min-w-0"
/>
</div>
<div className="mb-3">
<Button
className="w-full"
onClick={() => joinRoom(false, retrieveRoomIdInput)}
ref={retrieveJoinRoomBtnRef}
disabled={
!receiver || receiver.isInRoom || !retrieveRoomIdInput.trim()
}
>
{messages.text.ClipboardApp.html.joinRoom_dis}
</Button>
</div>
{retrievedContent && (
<div className="my-3 p-2 border rounded bg-gray-50">
<RichTextEditor
value={retrievedContent}
onChange={() => {
/* Read-only */
}}
/>
<div className="mt-2">
<WriteClipboardButton
title={messages.text.ClipboardApp.html.Copy_dis}
textToCopy={richTextToPlainText(retrievedContent)}
/>
</div>
</div>
)}
<FileListDisplay
mode="receiver"
files={retrievedFileMetas}
fileProgresses={receiveProgress}
onDownload={handleDownloadFile}
onRequest={handleFileRequestFromPanel} // Use the panel's own handler
onLocationPick={onLocationPick} // Use the panel's own handler
saveType={getReceiverSaveType()}
/>
{retrieveMessage && (
<p className="mt-3 text-sm text-blue-600">{retrieveMessage}</p>
)}
</div>
);
}