Skip to content

Commit d659be5

Browse files
committed
Merge branch 'add-segment-at-current-time' of Arnei/opencast-editor into r/17.x
Pull request #1367 Resolves #1313 Add cue at current time for subtitles
2 parents 92ab423 + 88b40c3 commit d659be5

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

src/globalKeys.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,9 @@ export const KEYMAP: IKeyMap = {
136136
name: "subtitleList.deleteSegment",
137137
key: "Shift+Alt+d",
138138
},
139+
addCue: {
140+
name: "subtitleList.addCue",
141+
key: "Shift+Alt+e",
142+
},
139143
},
140144
};

src/i18n/locales/en-US.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@
289289
"addSegmentBelow": "Add segment below",
290290
"jumpToSegmentAbove": "Jump to segment above",
291291
"jumpToSegmentBelow": "Jump to segment below",
292-
"deleteSegment": "Delete segment"
292+
"deleteSegment": "Delete segment",
293+
"addCue": "Add segment at current time"
293294
},
294295

295296
"subtitleVideoArea": {

src/main/SubtitleTimeline.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { useEffect, useRef, useState } from "react";
22
import { css } from "@emotion/react";
33
import { SegmentsList as CuttingSegmentsList, Waveforms } from "./Timeline";
44
import {
5+
addCueAtIndex,
56
selectCurrentlyAt,
67
selectSelectedSubtitleById,
78
selectSelectedSubtitleId,
@@ -25,6 +26,7 @@ import { ThemedTooltip } from "./Tooltip";
2526
import { useTranslation } from "react-i18next";
2627
import { useHotkeys } from "react-hotkeys-hook";
2728
import { KEYMAP } from "../globalKeys";
29+
import { shallowEqual } from "react-redux";
2830

2931
/**
3032
* Copy-paste of the timeline in Video.tsx, so that we can make some small adjustments,
@@ -39,6 +41,7 @@ const SubtitleTimeline: React.FC = () => {
3941
const dispatch = useAppDispatch();
4042
const duration = useAppSelector(selectDuration);
4143
const currentlyAt = useAppSelector(selectCurrentlyAt);
44+
const subtitleId = useAppSelector(selectSelectedSubtitleId, shallowEqual);
4245

4346
const { ref, width = 1 } = useResizeObserver<HTMLDivElement>();
4447
const refTop = useRef<HTMLElement>(null);
@@ -71,6 +74,17 @@ const SubtitleTimeline: React.FC = () => {
7174

7275
const [keyboardJumpDelta, setKeyboardJumpDelta] = useState(1000); // In milliseconds. For keyboard navigation
7376

77+
// Callback for adding subtitle segment by hotkey
78+
const addCue = (time: number) => {
79+
dispatch(addCueAtIndex({
80+
identifier: subtitleId,
81+
cueIndex: -1,
82+
text: "",
83+
startTime: time,
84+
endTime: time + 5000,
85+
}));
86+
};
87+
7488
// Callbacks for keyboard controls
7589
// TODO: Better increases and decreases than ten intervals
7690
// TODO: Additional helpful controls (e.g. jump to start/end of segment/next segment)
@@ -94,6 +108,11 @@ const SubtitleTimeline: React.FC = () => {
94108
() => setKeyboardJumpDelta(keyboardJumpDelta => Math.max(keyboardJumpDelta / 10, 1)),
95109
{}, [keyboardJumpDelta],
96110
);
111+
useHotkeys(
112+
KEYMAP.subtitleList.addCue.key,
113+
() => addCue(currentlyAt),
114+
{}, [currentlyAt],
115+
);
97116

98117
// Callback for the scroll container
99118
const onEndScroll = (e: ScrollEvent) => {
@@ -102,6 +121,14 @@ const SubtitleTimeline: React.FC = () => {
102121
const offsetX = refTop.current.scrollLeft;
103122
const scrollLeftMax = (refTop.current.scrollWidth - refTop.current.clientWidth);
104123
dispatch(setCurrentlyAt((offsetX / scrollLeftMax) * (duration)));
124+
125+
// Blur active element after scrolling, to ensure hotkeys are working
126+
// This is a little hack to work around focus getting stuck in textarea elements from the subtitle list
127+
try {
128+
(document.activeElement as HTMLElement).blur();
129+
} catch (_e) {
130+
console.error("Tried to blur active element, but active element cannot be blurred.");
131+
}
105132
}
106133
};
107134

src/redux/subtitleSlice.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export const subtitleSlice = createSlice({
135135
state.subtitles[action.payload.identifier].cues.splice(0, 0, cue);
136136
}
137137

138-
if (action.payload.cueIndex >= 0 ||
138+
if (action.payload.cueIndex >= 0 &&
139139
action.payload.cueIndex < state.subtitles[action.payload.identifier].cues.length) {
140140
state.subtitles[action.payload.identifier].cues.splice(action.payload.cueIndex, 0, cue);
141141
}

0 commit comments

Comments
 (0)