File size: 3,992 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
import React, { useState, useEffect } from 'react';
import { InformationCircleIcon } from '@heroicons/react/24/outline';
import { useTranscriptionStore } from '../stores/transcriptionStore';
import { formatTime } from '../utils/subtitleUtils';

const DEFAULT_MERGE_THRESHOLD = 2;

const MediaEditControls: React.FC = () => {
  const [mergeThreshold, setMergeThreshold] = useState(DEFAULT_MERGE_THRESHOLD);

  const {
    transcription,
    currentTime,
    activeSegmentIndex,
    currentSegments,
    undo,
    redo,
    canUndo,
    canRedo,
    mergeSegmentsByProximity,
  } = useTranscriptionStore();

  const MAX_MERGE_INTERVAL_SECONDS = 30;

  if (!transcription) {
    return null;
  }

  const displaySegments = currentSegments || transcription.aligned_segments;

  // Handle merge threshold changes
  useEffect(() => {
    mergeSegmentsByProximity(mergeThreshold);
  }, [mergeThreshold, mergeSegmentsByProximity]);

  // Keyboard shortcuts for undo/redo
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
        e.preventDefault();
        undo();
      } else if ((e.ctrlKey || e.metaKey) && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {
        e.preventDefault();
        redo();
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => document.removeEventListener('keydown', handleKeyDown);
  }, [undo, redo]);

  return (
    <div className="flex items-center justify-center">
      <div className="flex items-center space-x-4">
        {/* Current Status Info */}
        <div className="flex items-center space-x-4 text-xs text-gray-400">
          <span className="text-green-400">
            {formatTime(currentTime)} / {formatTime(transcription.total_duration)}
          </span>
          <span className="text-blue-400">
            {activeSegmentIndex !== null
              ? `Segment ${activeSegmentIndex + 1}/${displaySegments.length}`
              : "No active segment"}
          </span>
        </div>

        {/* Combine Segments Slider */}
        <div className="flex items-center space-x-2">
          <label className="text-xs text-gray-300 whitespace-nowrap flex items-center space-x-1">
            <span>Combine Words:</span>
            <div className="tooltip" data-tip="This slider merges nearby words. The higher the more words are combined">
              <InformationCircleIcon className="w-4 h-4 text-gray-100 hover:text-gray-300 cursor-help inline ml-1" />
            </div>
          </label>
          <input
            type="range"
            min="0"
            max={MAX_MERGE_INTERVAL_SECONDS}
            step="0.5"
            value={mergeThreshold}
            onChange={(e) => setMergeThreshold(Number(e.target.value))}
            className="w-20 h-1 bg-gray-600 rounded-lg appearance-none cursor-pointer slider"
            style={{
              background: `linear-gradient(to right, #3B82F6 0%, #3B82F6 ${(mergeThreshold / MAX_MERGE_INTERVAL_SECONDS) * 100}%, #4B5563 ${(mergeThreshold / MAX_MERGE_INTERVAL_SECONDS) * 100}%, #4B5563 100%)`
            }}
          />
        </div>

        {/* Undo/Redo Buttons */}
        <div className="flex items-center space-x-2">
          <button
            onClick={undo}
            disabled={!canUndo}
            className="px-3 py-1 text-xs bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white rounded transition-colors"
            title="Undo (Ctrl+Z)"
          >
            ↶ Undo
          </button>
          <button
            onClick={redo}
            disabled={!canRedo}
            className="px-3 py-1 text-xs bg-blue-600 hover:bg-blue-700 disabled:bg-gray-600 disabled:cursor-not-allowed text-white rounded transition-colors"
            title="Redo (Ctrl+Y)"
          >
            ↷ Redo
          </button>
        </div>
      </div>
    </div>
  );
};

export default MediaEditControls;