Spaces:
Running
on
A100
Running
on
A100
File size: 4,787 Bytes
ae238b3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
import React from "react";
import {useState, useRef, useCallback} from "react";
import {useTranscriptionStore} from "../stores/transcriptionStore";
import {
SUPPORTED_AUDIO_FORMATS,
SUPPORTED_VIDEO_FORMATS,
CODEC_INFO,
} from "../utils/mediaTypes";
import TranscriptionSideBar from "../components/TranscriptionSideBar";
import TranscriptionPlayer from "../components/TranscriptionPlayer";
import MediaRecorder from "../components/MediaRecorder";
import {useDragAndDrop} from "../hooks/useDragAndDrop";
import {CloudArrowUpIcon} from "@heroicons/react/24/outline";
import ErrorBoundary from "../components/ErrorBoundary";
export default function TranscriptionPage() {
const {isRecording, setFile, stopRecording} = useTranscriptionStore();
// Sidebar resizing state
const [sidebarWidth, setSidebarWidth] = useState(256); // Default 256px (w-64)
const [isResizing, setIsResizing] = useState(false);
const sidebarRef = useRef<HTMLDivElement>(null);
// Drag and drop functionality
const {isDragActive, dragProps} = useDragAndDrop({
onFileDropped: setFile,
acceptedTypes: ["audio/*"],
});
// Handle sidebar resizing
const handleMouseDown = useCallback((e: React.MouseEvent) => {
e.preventDefault();
setIsResizing(true);
}, []);
const handleMouseMove = useCallback(
(e: MouseEvent) => {
if (!isResizing) return;
const newWidth = Math.max(200, Math.min(600, e.clientX)); // Min 200px, max 600px
setSidebarWidth(newWidth);
},
[isResizing]
);
const handleMouseUp = useCallback(() => {
setIsResizing(false);
}, []);
// Add global mouse event listeners
React.useEffect(() => {
if (isResizing) {
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
document.body.style.userSelect = "none"; // Prevent text selection during drag
document.body.style.cursor = "ew-resize";
}
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
document.body.style.userSelect = "";
document.body.style.cursor = "";
};
}, [isResizing, handleMouseMove, handleMouseUp]);
return (
<ErrorBoundary componentName="TranscriptionPage">
<div className="flex h-screen bg-gray-900 relative" {...dragProps}>
{/* Drag Overlay */}
{isDragActive && (
<div className="absolute inset-0 bg-blue-900/80 border-4 border-dashed border-blue-400 z-50 flex items-center justify-center">
<div className="text-center text-white">
<CloudArrowUpIcon className="w-16 h-16 mx-auto mb-4 text-blue-300" />
<div className="text-2xl font-semibold mb-2">
Drop your audio file here
</div>
<div className="text-lg text-blue-200 mb-4">
Supports audio files only
</div>
{/* Audio formats section */}
<div className="text-center mb-3">
<div className="text-sm font-medium text-blue-300 mb-1">
Audio Formats
</div>
<div className="text-xs text-blue-100 opacity-90">
{SUPPORTED_AUDIO_FORMATS.join(" • ")}
</div>
</div>
{/* Codec info */}
<div className="text-center">
<div className="text-xs text-blue-200 opacity-75">
Best with standard codecs:{" "}
{CODEC_INFO.audio.common.slice(0, 2).join(", ")}
</div>
</div>
</div>
</div>
)}
{/* Sidebar with Resize Handle */}
<div className="relative flex">
<div
ref={sidebarRef}
className="flex-shrink-0 bg-gray-800 text-white overflow-y-auto"
style={{width: `${sidebarWidth}px`}}
>
<TranscriptionSideBar />
</div>
{/* Drag Handle */}
<div
className="w-1 bg-gray-600 hover:bg-gray-500 cursor-ew-resize flex-shrink-0 transition-colors duration-150"
onMouseDown={handleMouseDown}
title="Drag to resize sidebar"
/>
</div>
{/* Main Content */}
<ErrorBoundary componentName="TranscriptionPlayer">
{isRecording ? (
<div className="flex-1 flex items-center justify-center bg-gray-900">
<MediaRecorder
onComplete={() => stopRecording()}
onCancel={() => stopRecording()}
/>
</div>
) : (
<TranscriptionPlayer />
)}
</ErrorBoundary>
</div>
</ErrorBoundary>
);
}
|