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>
  );
}