+
{renderNumber()}
- {timeStr}
+ {timeStr}
{seg.name}
diff --git a/src/components/KeyboardShortcuts.jsx b/src/components/KeyboardShortcuts.jsx
index 804e485a..a563a106 100644
--- a/src/components/KeyboardShortcuts.jsx
+++ b/src/components/KeyboardShortcuts.jsx
@@ -113,6 +113,7 @@ const KeyboardShortcuts = memo(({
const { actionsMap, extraLinesPerCategory } = useMemo(() => {
const playbackCategory = t('Playback');
+ const selectivePlaybackCategory = t('Playback/preview segments only');
const seekingCategory = t('Seeking');
const segmentsAndCutpointsCategory = t('Segments and cut points');
const zoomOperationsCategory = t('Timeline/zoom operations');
@@ -156,18 +157,6 @@ const KeyboardShortcuts = memo(({
name: t('Play/pause (no reset speed)'),
category: playbackCategory,
},
- togglePlayOnlyCurrentSegment: {
- name: t('Play/pause (only current segment)'),
- category: playbackCategory,
- },
- toggleLoopOnlyCurrentSegment: {
- name: t('Loop/pause (only current segment)'),
- category: playbackCategory,
- },
- toggleLoopStartEndOnlyCurrentSegment: {
- name: t('Loop/pause (only beginning and end of current segment)'),
- category: playbackCategory,
- },
play: {
name: t('Play'),
category: playbackCategory,
@@ -201,6 +190,24 @@ const KeyboardShortcuts = memo(({
category: playbackCategory,
},
+ // selectivePlaybackCategory
+ togglePlayOnlyCurrentSegment: {
+ name: t('Play current segment once'),
+ category: selectivePlaybackCategory,
+ },
+ toggleLoopOnlyCurrentSegment: {
+ name: t('Loop current segment'),
+ category: selectivePlaybackCategory,
+ },
+ toggleLoopStartEndOnlyCurrentSegment: {
+ name: t('Loop beginning and end of current segment'),
+ category: selectivePlaybackCategory,
+ },
+ toggleLoopSelectedSegments: {
+ name: t('Play selected segments in order'),
+ category: selectivePlaybackCategory,
+ },
+
// seekingCategory
seekPreviousFrame: {
name: t('Step backward 1 frame'),
diff --git a/src/components/SegmentCutpointButton.jsx b/src/components/SegmentCutpointButton.jsx
index fb7d3d41..14cd4446 100644
--- a/src/components/SegmentCutpointButton.jsx
+++ b/src/components/SegmentCutpointButton.jsx
@@ -14,7 +14,7 @@ const SegmentCutpointButton = ({ currentCutSeg, side, Icon, onClick, title, styl
size={13}
title={title}
role="button"
- style={{ color: 'white', padding: start ? '4px 4px 4px 2px' : '4px 2px 4px 4px', borderLeft: start && border, borderRight: !start && border, background: backgroundColor, borderRadius: 6, ...style }}
+ style={{ flexShrink: 0, color: 'white', padding: start ? '4px 4px 4px 2px' : '4px 2px 4px 4px', borderLeft: start && border, borderRight: !start && border, background: backgroundColor, borderRadius: 6, ...style }}
onClick={onClick}
/>
);
diff --git a/src/hooks/useSegments.js b/src/hooks/useSegments.js
index d5b90294..0a2f97e9 100644
--- a/src/hooks/useSegments.js
+++ b/src/hooks/useSegments.js
@@ -18,7 +18,7 @@ import { maxSegmentsAllowed } from '../util/constants';
export default ({
filePath, workingRef, setWorking, setCutProgress, mainVideoStream,
- duration, getRelevantTime, maxLabelLength, checkFileOpened,
+ duration, getRelevantTime, maxLabelLength, checkFileOpened, invertCutSegments,
}) => {
// Segment related state
const segCounterRef = useRef(0);
@@ -430,6 +430,13 @@ export default ({
}));
}, [maxLabelLength, selectedSegmentsRaw, setCutSegments]);
+ // Guaranteed to have at least one segment (if user has selected none to export (selectedSegments empty), it makes no sense so select all instead.)
+ const selectedSegments = useMemo(() => (selectedSegmentsRaw.length > 0 ? selectedSegmentsRaw : apparentCutSegments), [apparentCutSegments, selectedSegmentsRaw]);
+
+ // For invertCutSegments we do not support filtering (selecting) segments
+ const selectedSegmentsOrInverse = useMemo(() => (invertCutSegments ? inverseCutSegments : selectedSegments), [inverseCutSegments, invertCutSegments, selectedSegments]);
+ const nonFilteredSegmentsOrInverse = useMemo(() => (invertCutSegments ? inverseCutSegments : apparentCutSegments), [invertCutSegments, inverseCutSegments, apparentCutSegments]);
+
const removeSelectedSegments = useCallback(() => removeSegments(selectedSegmentsRaw.map((seg) => seg.segId)), [removeSegments, selectedSegmentsRaw]);
const selectOnlySegment = useCallback((seg) => setDeselectedSegmentIds(Object.fromEntries(cutSegments.filter((s) => s.segId !== seg.segId).map((s) => [s.segId, true]))), [cutSegments]);
@@ -476,7 +483,9 @@ export default ({
clearSegments,
loadCutSegments,
selectedSegmentsRaw,
- setCutTime,
+ selectedSegments,
+ selectedSegmentsOrInverse,
+ nonFilteredSegmentsOrInverse,
getSegApparentEnd,
setCurrentSegIndex,
diff --git a/src/segments.js b/src/segments.js
index bc28a54f..2ec6e632 100644
--- a/src/segments.js
+++ b/src/segments.js
@@ -165,34 +165,49 @@ export function convertSegmentsToChapters(sortedSegments) {
return sortSegments([...sortedSegments, ...invertedSegments]);
}
-export function playOnlyCurrentSegment({ mode, currentTime, playingOnlySegment }) {
- if (mode === 'loop-start-end') {
- const maxSec = 3; // max time each side (start/end)
- const sec = Math.min(maxSec, (playingOnlySegment.end - playingOnlySegment.start) / 3) * 2;
-
- const startWindowEnd = playingOnlySegment.start + sec / 2;
- const endWindowStart = playingOnlySegment.end - sec / 2;
+export function playOnlyCurrentSegment({ playbackMode, currentTime, playingSegment }) {
+ switch (playbackMode) {
+ case 'loop-segment-start-end': {
+ const maxSec = 3; // max time each side (start/end)
+ const sec = Math.min(maxSec, (playingSegment.end - playingSegment.start) / 3) * 2;
+
+ const startWindowEnd = playingSegment.start + sec / 2;
+ const endWindowStart = playingSegment.end - sec / 2;
+
+ if (currentTime >= playingSegment.end) {
+ return { seek: playingSegment.start };
+ }
+ if (currentTime < endWindowStart && currentTime >= startWindowEnd) {
+ return { seek: endWindowStart };
+ }
+ break;
+ }
- if (currentTime >= playingOnlySegment.end) {
- return { seek: playingOnlySegment.start };
+ case 'loop-segment': {
+ if (currentTime >= playingSegment.end) {
+ return { seek: playingSegment.start };
+ }
+ break;
}
- if (currentTime < endWindowStart && currentTime >= startWindowEnd) {
- return { seek: endWindowStart };
+
+ case 'play-segment-once': {
+ if (currentTime >= playingSegment.end) {
+ return {
+ seek: playingSegment.end,
+ stop: true,
+ };
+ }
+ break;
}
- }
- if (mode === 'loop-full') {
- if (currentTime >= playingOnlySegment.end) {
- return { seek: playingOnlySegment.start };
+ case 'loop-selected-segments': {
+ if (currentTime >= playingSegment.end) {
+ return { nextSegment: true };
+ }
+ break;
}
- }
- // mode === 'play'
- if (currentTime >= playingOnlySegment.end) {
- return {
- seek: playingOnlySegment.end,
- stop: true,
- };
+ default:
}
return {};