Skip to content

Commit aa56d11

Browse files
committed
Move timeline when scrubber goes out of frame
When the timeline is zoomed in and video playback is active, the scrubber will eventually move outside of the visible part of the timeline. This fixes that by scrolling the timeline as soon as that happens.
1 parent d9938eb commit aa56d11

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

src/main/Timeline.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import { ThemedTooltip } from "./Tooltip";
3636
import ScrollContainer from "react-indiana-drag-scroll";
3737
import CuttingActionsContextMenu from "./CuttingActionsContextMenu";
3838
import { useHotkeys } from "react-hotkeys-hook";
39-
import { Spinner } from "@opencast/appkit";
39+
import { ProtoButton, Spinner } from "@opencast/appkit";
4040
import {
4141
selectSelectedSubtitleByIdForTimeline as chapterSelectSegments,
4242
selectActiveSegmentIndex as chapterSelectActiveSegmentIndex,
@@ -135,6 +135,15 @@ const Timeline: React.FC<{
135135
dispatch(setCurrentlyAt((offsetX / width) * (duration)));
136136
};
137137

138+
// Scroll the scroll container by its width one time
139+
// To be used when the scrubber moves out of sight while playing the video.
140+
const scrollByOwnWidth = () => {
141+
if (scrollContainerRef.current) {
142+
scrollContainerRef.current.scrollLeft = scrollContainerRef.current?.scrollLeft + scrollContainerWidth;
143+
updateScroll();
144+
}
145+
};
146+
138147
return (
139148
<ScrollContainer
140149
innerRef={scrollContainerRef}
@@ -152,6 +161,9 @@ const Timeline: React.FC<{
152161
ref={scrubberRef}
153162
timelineWidth={width}
154163
timelineHeight={timelineHeight}
164+
scrollContainerWidth={scrollContainerWidth}
165+
scrollLeft={scrollContainerRef.current?.scrollLeft ?? 0}
166+
scrollTheContainerbyOwnWidth={scrollByOwnWidth}
155167
selectCurrentlyAt={selectCurrentlyAt}
156168
selectIsPlaying={selectIsPlaying}
157169
setCurrentlyAt={setCurrentlyAt}
@@ -192,6 +204,9 @@ const Timeline: React.FC<{
192204
type ScrubberProps = {
193205
timelineWidth: number,
194206
timelineHeight: number,
207+
scrollContainerWidth: number,
208+
scrollLeft: number,
209+
scrollTheContainerbyOwnWidth: () => void,
195210
selectCurrentlyAt: (state: RootState) => number,
196211
selectIsPlaying: (state: RootState) => boolean,
197212
setCurrentlyAt: ActionCreatorWithPayload<number, string>,
@@ -203,7 +218,8 @@ type ScrubberProps = {
203218
* @param param0
204219
*/
205220
export const Scrubber = React.forwardRef<HTMLDivElement, ScrubberProps>((props, nodeRef) => {
206-
const { timelineWidth, timelineHeight, selectCurrentlyAt, selectIsPlaying, setCurrentlyAt, setIsPlaying } = props;
221+
const {timelineWidth, timelineHeight, scrollContainerWidth, scrollLeft, scrollTheContainerbyOwnWidth,
222+
selectCurrentlyAt, selectIsPlaying, setCurrentlyAt, setIsPlaying } = props;
207223

208224
const { t } = useTranslation();
209225

@@ -240,6 +256,14 @@ export const Scrubber = React.forwardRef<HTMLDivElement, ScrubberProps>((props,
240256
// eslint-disable-next-line react-hooks/exhaustive-deps
241257
}, [timelineWidth]);
242258

259+
// Check when the scrubber moves out of sight (can happen when playing the video while zoomed in)
260+
// and then scroll the container
261+
useEffect(() => {
262+
if (controlledPosition.x > (scrollLeft + scrollContainerWidth)) {
263+
scrollTheContainerbyOwnWidth();
264+
}
265+
}, [controlledPosition.x, scrollContainerWidth, scrollLeft, scrollTheContainerbyOwnWidth]);
266+
243267
// Callback for when the scrubber gets dragged by the user
244268
const onControlledDrag: DraggableEventHandler = debounce((_e, position: { x: number, y : number }) => {
245269
// Update position

0 commit comments

Comments
 (0)