Skip to content

Commit 2e54223

Browse files
committed
Merge remote-tracking branch 'upstream/r/18.x' into metadata-rework-reduce-rerenders
2 parents 2ed720a + e2dc2d6 commit 2e54223

File tree

9 files changed

+49
-10
lines changed

9 files changed

+49
-10
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
@@ -306,7 +306,8 @@
306306
"addSegmentBelow": "Add segment below",
307307
"jumpToSegmentAbove": "Jump to segment above",
308308
"jumpToSegmentBelow": "Jump to segment below",
309-
"deleteSegment": "Delete segment"
309+
"deleteSegment": "Delete segment",
310+
"addCue": "Add segment at current time"
310311
},
311312

312313
"subtitleVideoArea": {

src/main/Cutting.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { useTheme } from "../themes";
2626
import { setError } from "../redux/errorSlice";
2727
import { selectTitleFromEpisodeDc } from "../redux/metadataSlice";
2828
import { titleStyle, titleStyleBold, videosStyle } from "../cssStyles";
29-
import { LuMoveHorizontal } from "react-icons/lu";
29+
import { LuHourglass } from "react-icons/lu";
3030
import { css } from "@emotion/react";
3131
import VideoPlayers from "./VideoPlayers";
3232
import VideoControls from "./VideoControls";
@@ -58,7 +58,7 @@ const Cutting: React.FC = () => {
5858
error: true,
5959
errorTitle: t("error.workflowActive-errorTitle"),
6060
errorMessage: t("error.workflowActive-errorMessage"),
61-
errorIcon: LuMoveHorizontal,
61+
errorIcon: LuHourglass,
6262
}));
6363
} else {
6464
dispatch(setError({

src/main/Save.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,11 @@ const Save: React.FC = () => {
111111
export const SaveButton: React.FC<{
112112
text?: string
113113
isTransitionToEnd?: boolean
114+
startWorkflow?: boolean
114115
}> = ({
115116
text,
116117
isTransitionToEnd = false,
118+
startWorkflow = false,
117119
}) => {
118120
const { t } = useTranslation();
119121

@@ -164,7 +166,7 @@ export const SaveButton: React.FC<{
164166
tracks: tracks,
165167
customizedTrackSelection,
166168
subtitles: prepareSubtitles(),
167-
workflow: selectedWorkflowId ? [{ id: selectedWorkflowId }] : undefined,
169+
workflow: startWorkflow && selectedWorkflowId ? [{ id: selectedWorkflowId }] : undefined,
168170
}));
169171
};
170172

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/main/Thumbnail.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ const ThumbnailTableRow: React.FC<{
253253
// The "+40" comes from padding that is not included in the "getWidth" function
254254
generateRef.getWidth() + 40 :
255255
// Random default
256-
440;
256+
740;
257257

258258
const renderPriority = (thumbnailPriority: number) => {
259259
if (isNaN(thumbnailPriority)) {
@@ -300,15 +300,17 @@ const ThumbnailDisplayer: React.FC<{ track: Track; }> = ({ track }) => {
300300

301301
const generalStyle = css({
302302
width: "100%",
303-
maxWidth: "457px",
303+
maxWidth: "740px",
304304
aspectRatio: "16/9",
305305
});
306306

307307
const imageStyle = css({
308+
maxWidth: "457px",
308309
});
309310

310311
const placeholderStyle = css({
311312
width: "100vw", // TODO: This is necessary to make the placeholder large enough, but prevents it from shrinking
313+
maxWidth: "457px",
312314
backgroundColor: "grey",
313315
display: "flex",
314316
justifyContent: "center",

src/main/WorkflowSelection.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ const WorkflowSelection: React.FC = () => {
137137
<SaveButton
138138
isTransitionToEnd={true}
139139
text={t("workflowSelection.startProcessing-button")}
140+
startWorkflow={true}
140141
/>,
141142
saveStatus,
142143
saveError,
@@ -153,6 +154,7 @@ const WorkflowSelection: React.FC = () => {
153154
<SaveButton
154155
isTransitionToEnd={true}
155156
text={t("workflowSelection.startProcessing-button")}
157+
startWorkflow={true}
156158
/>,
157159
saveStatus,
158160
saveError,

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
}

src/util/utilityFunctions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { nanoid } from "@reduxjs/toolkit";
22
import { WebVTTParser, WebVTTSerializer } from "webvtt-parser";
33
import { ExtendedSubtitleCue, SubtitleCue } from "../types";
44
import { useEffect, useState, useRef } from "react";
5+
import i18next from "i18next";
56

67
export const roundToDecimalPlace = (num: number, decimalPlace: number) => {
78
const decimalFactor = Math.pow(10, decimalPlace);
@@ -131,16 +132,16 @@ export function parseSubtitle(subtitle: string): SubtitleCue[] {
131132

132133
/**
133134
* Parse language code to language name
134-
* Returns language name in the language set in the browser
135+
* Returns language name in the language set by the user
135136
* Returns undefined if the input was undefined or the language code could not
136137
* be parsed
137138
*/
138139
export function languageCodeToName(lang: string | undefined): string | undefined {
139140
if (!lang) {
140141
return undefined;
141142
}
142-
const browserLang = window.navigator.language;
143-
const languageNames = new Intl.DisplayNames(browserLang, { type: "language" });
143+
const currentLang = i18next.resolvedLanguage;
144+
const languageNames = new Intl.DisplayNames(currentLang, { type: "language" });
144145
try {
145146
return languageNames.of(lang.trim());
146147
// eslint-disable-next-line @typescript-eslint/no-unused-vars

0 commit comments

Comments
 (0)