change segments to export into select segments

allows more flexibility
pull/901/head
Mikael Finstad 4 years ago
parent 6d8981798d
commit c48f2dd2f3
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26

@ -132,7 +132,7 @@ const App = memo(() => {
const [thumbnails, setThumbnails] = useState([]);
const [shortestFlag, setShortestFlag] = useState(false);
const [zoomWindowStartTime, setZoomWindowStartTime] = useState(0);
const [disabledSegmentIds, setDisabledSegmentIds] = useState({});
const [deselectedSegmentIds, setDeselectedSegmentIds] = useState({});
const [subtitlesByStreamId, setSubtitlesByStreamId] = useState({});
const [activeSubtitleStreamIndex, setActiveSubtitleStreamIndex] = useState();
const [hideCanvasPreview, setHideCanvasPreview] = useState(false);
@ -929,7 +929,7 @@ const App = memo(() => {
setThumbnails([]);
setShortestFlag(false);
setZoomWindowStartTime(0);
setDisabledSegmentIds({});
setDeselectedSegmentIds({});
setSubtitlesByStreamId({});
setActiveSubtitleStreamIndex();
setHideCanvasPreview(false);
@ -1127,31 +1127,31 @@ const App = memo(() => {
invertCutSegments ? inverseCutSegments : apparentCutSegments
), [invertCutSegments, inverseCutSegments, apparentCutSegments]);
const enabledSegmentsRaw = useMemo(() => {
const selectedSegmentsRaw = useMemo(() => {
// For invertCutSegments we do not support filtering
if (invertCutSegments) return inverseCutSegments;
return apparentCutSegments.filter((s) => !disabledSegmentIds[s.segId]);
}, [invertCutSegments, inverseCutSegments, apparentCutSegments, disabledSegmentIds]);
return apparentCutSegments.filter((s) => !deselectedSegmentIds[s.segId]);
}, [invertCutSegments, inverseCutSegments, apparentCutSegments, deselectedSegmentIds]);
// If user has selected none to export, it makes no sense, so export all instead
const enabledSegments = enabledSegmentsRaw.length > 0 ? enabledSegmentsRaw : inverseOrNormalSegments;
const selectedSegments = selectedSegmentsRaw.length > 0 ? selectedSegmentsRaw : inverseOrNormalSegments;
const enableOnlySegment = useCallback((seg) => setDisabledSegmentIds(Object.fromEntries(cutSegments.filter((s) => s.segId !== seg.segId).map((s) => [s.segId, true]))), [cutSegments]);
const toggleSegmentEnabled = useCallback((seg) => setDisabledSegmentIds((existing) => ({ ...existing, [seg.segId]: !existing[seg.segId] })), []);
const disableAllSegments = useCallback(() => setDisabledSegmentIds(Object.fromEntries(cutSegments.map((s) => [s.segId, true]))), [cutSegments]);
const enableAllSegments = useCallback(() => setDisabledSegmentIds({}), []);
const selectOnlySegment = useCallback((seg) => setDeselectedSegmentIds(Object.fromEntries(cutSegments.filter((s) => s.segId !== seg.segId).map((s) => [s.segId, true]))), [cutSegments]);
const toggleSegmentSelected = useCallback((seg) => setDeselectedSegmentIds((existing) => ({ ...existing, [seg.segId]: !existing[seg.segId] })), []);
const deselectAllSegments = useCallback(() => setDeselectedSegmentIds(Object.fromEntries(cutSegments.map((s) => [s.segId, true]))), [cutSegments]);
const selectAllSegments = useCallback(() => setDeselectedSegmentIds({}), []);
const enableOnlyCurrentSegment = useCallback(() => enableOnlySegment(currentCutSeg), [currentCutSeg, enableOnlySegment]);
const toggleCurrentSegmentEnabled = useCallback(() => toggleSegmentEnabled(currentCutSeg), [currentCutSeg, toggleSegmentEnabled]);
const selectOnlyCurrentSegment = useCallback(() => selectOnlySegment(currentCutSeg), [currentCutSeg, selectOnlySegment]);
const toggleCurrentSegmentSelected = useCallback(() => toggleSegmentSelected(currentCutSeg), [currentCutSeg, toggleSegmentSelected]);
const filenamifyOrNot = useCallback((name) => (safeOutputFileName ? filenamify(name) : name).substr(0, maxLabelLength), [safeOutputFileName, maxLabelLength]);
const segmentsToExport = useMemo(() => {
if (!segmentsToChaptersOnly) return enabledSegments;
if (!segmentsToChaptersOnly) return selectedSegments;
// segmentsToChaptersOnly is a special mode where all segments will be simply written out as chapters to one file: https://github.com/mifi/lossless-cut/issues/993#issuecomment-1037927595
// Chapters export mode: Emulate a single segment with no cuts (full timeline)
return [{ start: 0, end: getSegApparentEnd({}) }];
}, [enabledSegments, getSegApparentEnd, segmentsToChaptersOnly]);
}, [selectedSegments, getSegApparentEnd, segmentsToChaptersOnly]);
const areWeCutting = useMemo(() => segmentsToExport.some(({ start, end }) => isCuttingStart(start) || isCuttingEnd(end, duration)), [duration, segmentsToExport]);
@ -1223,7 +1223,7 @@ const App = memo(() => {
// Special segments-to-chapters mode:
let chaptersToAdd;
if (segmentsToChaptersOnly) {
const sortedSegments = sortSegments(enabledSegments);
const sortedSegments = sortSegments(selectedSegments);
if (hasAnySegmentOverlap(sortedSegments)) {
errorToast(i18n.t('Make sure you have no overlapping segments.'));
return;
@ -1322,7 +1322,7 @@ const App = memo(() => {
setWorking();
setCutProgress();
}
}, [numStreamsToCopy, setWorking, segmentsToChaptersOnly, enabledSegments, outSegTemplateOrDefault, generateOutSegFileNames, segmentsToExport, getOutSegError, cutMultiple, outputDir, customOutDir, fileFormat, duration, isRotationSet, effectiveRotation, copyFileStreams, allFilesMeta, keyframeCut, shortestFlag, ffmpegExperimental, preserveMovData, preserveMetadataOnMerge, movFastStart, avoidNegativeTs, customTagsByFile, customTagsByStreamId, dispositionByStreamId, detectedFps, enableSmartCut, willMerge, mainFileFormatData, mainStreams, exportExtraStreams, hideAllNotifications, segmentsToChapters, invertCutSegments, autoConcatCutSegments, isCustomFormatSelected, autoDeleteMergedSegments, filePath, nonCopiedExtraStreams, handleCutFailed]);
}, [numStreamsToCopy, setWorking, segmentsToChaptersOnly, selectedSegments, outSegTemplateOrDefault, generateOutSegFileNames, segmentsToExport, getOutSegError, cutMultiple, outputDir, customOutDir, fileFormat, duration, isRotationSet, effectiveRotation, copyFileStreams, allFilesMeta, keyframeCut, shortestFlag, ffmpegExperimental, preserveMovData, preserveMetadataOnMerge, movFastStart, avoidNegativeTs, customTagsByFile, customTagsByStreamId, dispositionByStreamId, detectedFps, enableSmartCut, willMerge, mainFileFormatData, mainStreams, exportExtraStreams, hideAllNotifications, segmentsToChapters, invertCutSegments, autoConcatCutSegments, isCustomFormatSelected, autoDeleteMergedSegments, filePath, nonCopiedExtraStreams, handleCutFailed]);
const onExportPress = useCallback(async () => {
if (!filePath || workingRef.current) return;
@ -1836,10 +1836,10 @@ const App = memo(() => {
toggleCaptureFormat,
toggleStripAudio,
setStartTimeOffset: askSetStartTimeOffset,
disableAllSegments,
enableAllSegments,
enableOnlyCurrentSegment,
toggleCurrentSegmentEnabled,
disableAllSegments: deselectAllSegments,
enableAllSegments: selectAllSegments,
enableOnlyCurrentSegment: selectOnlyCurrentSegment,
toggleCurrentSegmentEnabled: toggleCurrentSegmentSelected,
fixInvalidDuration: tryFixInvalidDuration,
increaseVolume: () => setPlaybackVolume((val) => Math.min(1, val + 0.07)),
decreaseVolume: () => setPlaybackVolume((val) => Math.max(0, val - 0.07)),
@ -1884,7 +1884,7 @@ const App = memo(() => {
if (match) return bubble;
return true; // bubble the event
}, [addCutSegment, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, disableAllSegments, enableAllSegments, enableOnlyCurrentSegment, exportConfirmVisible, extractAllStreams, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, pause, play, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, setCutEnd, setCutStart, setPlaybackVolume, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentEnabled, toggleHelp, toggleKeyboardShortcuts, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]);
}, [addCutSegment, askSetStartTimeOffset, batchFileJump, batchOpenSelectedFile, captureSnapshot, changePlaybackRate, cleanupFilesDialog, clearSegments, closeBatch, closeExportConfirm, concatCurrentBatch, concatDialogVisible, convertFormatBatch, createFixedDurationSegments, createNumSegments, currentSegIndexSafe, cutSegmentsHistory, deselectAllSegments, exportConfirmVisible, extractAllStreams, goToTimecode, increaseRotation, invertAllCutSegments, jumpCutEnd, jumpCutStart, jumpSeg, jumpTimelineEnd, jumpTimelineStart, keyboardNormalSeekSpeed, keyboardSeekAccFactor, keyboardShortcutsVisible, onExportConfirm, onExportPress, onLabelSegmentPress, pause, play, removeCutSegment, reorderSegsByStartTime, seekClosestKeyframe, seekRel, seekRelPercent, selectAllSegments, selectOnlyCurrentSegment, setCutEnd, setCutStart, setPlaybackVolume, shortStep, shuffleSegments, splitCurrentSegment, timelineToggleComfortZoom, toggleCaptureFormat, toggleCurrentSegmentSelected, toggleHelp, toggleKeyboardShortcuts, toggleKeyframeCut, togglePlay, toggleSegmentsList, toggleStreamsSelector, toggleStripAudio, tryFixInvalidDuration, userHtml5ifyCurrentFile, zoomRel]);
useKeyboard({ keyBindings, onKeyPress });
@ -2209,7 +2209,7 @@ const App = memo(() => {
numStreamsToCopy={numStreamsToCopy}
numStreamsTotal={numStreamsTotal}
setStreamsSelectorShown={setStreamsSelectorShown}
enabledSegments={enabledSegments}
selectedSegments={selectedSegments}
/>
<div style={{ flexGrow: 1, display: 'flex', overflowY: 'hidden' }}>
@ -2305,12 +2305,12 @@ const App = memo(() => {
removeCutSegment={removeCutSegment}
toggleSegmentsList={toggleSegmentsList}
splitCurrentSegment={splitCurrentSegment}
enabledSegmentsRaw={enabledSegmentsRaw}
enabledSegments={enabledSegments}
onExportSingleSegmentClick={enableOnlySegment}
onExportSegmentEnabledToggle={toggleSegmentEnabled}
onExportSegmentDisableAll={disableAllSegments}
onExportSegmentEnableAll={enableAllSegments}
selectedSegmentsRaw={selectedSegmentsRaw}
selectedSegments={selectedSegments}
onSelectSingleSegment={selectOnlySegment}
onToggleSegmentSelected={toggleSegmentSelected}
onDeselectAllSegments={deselectAllSegments}
onSelectAllSegments={selectAllSegments}
jumpSegStart={jumpSegStart}
jumpSegEnd={jumpSegEnd}
onViewSegmentTagsPress={onViewSegmentTagsPress}
@ -2360,7 +2360,7 @@ const App = memo(() => {
cleanupFilesDialog={cleanupFilesDialog}
captureSnapshot={captureSnapshot}
onExportPress={onExportPress}
enabledSegments={enabledSegments}
selectedSegments={selectedSegments}
seekAbs={seekAbs}
currentSegIndexSafe={currentSegIndexSafe}
cutSegments={cutSegments}
@ -2426,7 +2426,7 @@ const App = memo(() => {
/>
</SideSheet>
<ExportConfirm filePath={filePath} areWeCutting={areWeCutting} enabledSegments={enabledSegments} willMerge={willMerge} visible={exportConfirmVisible} onClosePress={closeExportConfirm} onExportConfirm={onExportConfirm} renderOutFmt={renderOutFmt} outputDir={outputDir} numStreamsTotal={numStreamsTotal} numStreamsToCopy={numStreamsToCopy} setStreamsSelectorShown={setStreamsSelectorShown} outFormat={fileFormat} setOutSegTemplate={setOutSegTemplate} outSegTemplate={outSegTemplateOrDefault} generateOutSegFileNames={generateOutSegFileNames} currentSegIndexSafe={currentSegIndexSafe} getOutSegError={getOutSegError} />
<ExportConfirm filePath={filePath} areWeCutting={areWeCutting} selectedSegments={selectedSegments} willMerge={willMerge} visible={exportConfirmVisible} onClosePress={closeExportConfirm} onExportConfirm={onExportConfirm} renderOutFmt={renderOutFmt} outputDir={outputDir} numStreamsTotal={numStreamsTotal} numStreamsToCopy={numStreamsToCopy} setStreamsSelectorShown={setStreamsSelectorShown} outFormat={fileFormat} setOutSegTemplate={setOutSegTemplate} outSegTemplate={outSegTemplateOrDefault} generateOutSegFileNames={generateOutSegFileNames} currentSegIndexSafe={currentSegIndexSafe} getOutSegError={getOutSegError} />
<HelpSheet
visible={helpVisible}

@ -31,7 +31,7 @@ const leftRightWidth = 100;
const BottomBar = memo(({
zoom, setZoom, timelineToggleComfortZoom,
isRotationSet, rotation, areWeCutting, increaseRotation, cleanupFilesDialog,
captureSnapshot, onExportPress, enabledSegments, hasVideo,
captureSnapshot, onExportPress, selectedSegments, hasVideo,
seekAbs, currentSegIndexSafe, cutSegments, currentCutSeg, setCutStart, setCutEnd,
setCurrentSegIndex, cutStartTimeManual, setCutStartTimeManual, cutEndTimeManual, setCutEndTimeManual,
jumpTimelineStart, jumpTimelineEnd, jumpCutEnd, jumpCutStart, startTimeOffset, setCutTime, currentApparentCutSeg,
@ -359,7 +359,7 @@ const BottomBar = memo(({
{!simpleMode && <ToggleExportConfirm style={{ marginRight: 5 }} />}
<ExportButton size={1.3} enabledSegments={enabledSegments} areWeCutting={areWeCutting} onClick={onExportPress} />
<ExportButton size={1.3} selectedSegments={selectedSegments} areWeCutting={areWeCutting} onClick={onExportPress} />
</div>
</>
);

@ -40,7 +40,7 @@ const warningStyle = { color: '#faa', fontSize: '80%' };
const HelpIcon = ({ onClick }) => <IoIosHelpCircle size={20} role="button" onClick={withBlur(onClick)} style={{ cursor: 'pointer', verticalAlign: 'middle', marginLeft: 5 }} />;
const ExportConfirm = memo(({
areWeCutting, enabledSegments, willMerge, visible, onClosePress, onExportConfirm,
areWeCutting, selectedSegments, willMerge, visible, onClosePress, onExportConfirm,
renderOutFmt,
outputDir, numStreamsTotal, numStreamsToCopy, setStreamsSelectorShown,
outFormat,
@ -123,7 +123,7 @@ const ExportConfirm = memo(({
<h2 style={{ marginTop: 0 }}>{t('Export options')}</h2>
<ul>
{enabledSegments.length >= 2 && <li>{t('Merge {{segments}} cut segments to one file?', { segments: enabledSegments.length })} <MergeExportButton enabledSegments={enabledSegments} /></li>}
{selectedSegments.length >= 2 && <li>{t('Merge {{segments}} cut segments to one file?', { segments: selectedSegments.length })} <MergeExportButton selectedSegments={selectedSegments} /></li>}
<li>
{t('Output container format:')} {renderOutFmt({ height: 20, maxWidth: 150 })}
<HelpIcon onClick={onOutFmtHelpPress} />
@ -224,7 +224,7 @@ const ExportConfirm = memo(({
exit={{ scale: 0.7, opacity: 0 }}
transition={{ duration: 0.4, easings: ['easeOut'] }}
>
<ExportButton enabledSegments={enabledSegments} areWeCutting={areWeCutting} onClick={() => onExportConfirm()} size={1.7} />
<ExportButton selectedSegments={selectedSegments} areWeCutting={areWeCutting} onClick={() => onExportConfirm()} size={1.7} />
</motion.div>
</div>
</>

@ -1,5 +1,5 @@
import React, { memo, useMemo, useRef, useCallback } from 'react';
import { FaSave, FaPlus, FaMinus, FaTag, FaSortNumericDown, FaAngleRight, FaCheck, FaTimes } from 'react-icons/fa';
import { FaSave, FaPlus, FaMinus, FaTag, FaSortNumericDown, FaAngleRight, FaRegCheckCircle, FaRegCircle } from 'react-icons/fa';
import { AiOutlineSplitCells } from 'react-icons/ai';
import { motion } from 'framer-motion';
import Swal from 'sweetalert2';
@ -21,7 +21,7 @@ const buttonBaseStyle = {
const neutralButtonColor = 'rgba(255, 255, 255, 0.2)';
const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCount, updateOrder, invertCutSegments, onClick, onRemovePress, onReorderPress, onLabelPress, enabled, onExportSingleSegmentClick, onExportSegmentEnabledToggle, onExportSegmentDisableAll, onExportSegmentEnableAll, jumpSegStart, jumpSegEnd, addCutSegment, onViewSegmentTagsPress }) => {
const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCount, updateOrder, invertCutSegments, onClick, onRemovePress, onReorderPress, onLabelPress, enabled, onSelectSingleSegment, onToggleSegmentSelected, onDeselectAllSegments, onSelectAllSegments, jumpSegStart, jumpSegEnd, addCutSegment, onViewSegmentTagsPress }) => {
const { t } = useTranslation();
const ref = useRef();
@ -46,16 +46,15 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
{ type: 'separator' },
{ label: t('Include ONLY this segment in export'), click: () => onExportSingleSegmentClick(seg) },
{ label: enabled ? t('Exclude this segment from export') : t('Include this segment in export'), click: () => onExportSegmentEnabledToggle(seg) },
{ label: t('Include all segments in export'), click: () => onExportSegmentEnableAll(seg) },
{ label: t('Exclude all segments from export'), click: () => onExportSegmentDisableAll(seg) },
{ label: t('Select ONLY current segment'), click: () => onSelectSingleSegment(seg) },
{ label: t('Select all segments'), click: () => onSelectAllSegments() },
{ label: t('Deselect all segments'), click: () => onDeselectAllSegments() },
{ type: 'separator' },
{ label: t('Segment tags'), click: () => onViewSegmentTagsPress(index) },
];
}, [addCutSegment, enabled, index, invertCutSegments, jumpSegEnd, jumpSegStart, onExportSegmentDisableAll, onExportSegmentEnableAll, onExportSegmentEnabledToggle, onExportSingleSegmentClick, onLabelPress, onRemovePress, onReorderPress, onViewSegmentTagsPress, seg, t, updateOrder]);
}, [addCutSegment, index, invertCutSegments, jumpSegEnd, jumpSegStart, onDeselectAllSegments, onSelectAllSegments, onSelectSingleSegment, onLabelPress, onRemovePress, onReorderPress, onViewSegmentTagsPress, seg, t, updateOrder]);
useContextMenu(ref, contextMenuTemplate);
@ -81,7 +80,7 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
function onDoubleClick() {
if (invertCutSegments) return;
if (!enabled) {
onExportSegmentEnabledToggle(seg);
onToggleSegmentSelected(seg);
return;
}
jumpSegStart();
@ -90,6 +89,10 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
const durationMsFormatted = Math.floor(durationMs);
const frameCount = getFrameCount(duration);
const CheckIcon = enabled ? FaRegCheckCircle : FaRegCircle;
const onToggleSegmentSelectedClick = useCallback(() => onToggleSegmentSelected(seg), [onToggleSegmentSelected, seg]);
return (
<motion.div
ref={ref}
@ -101,6 +104,7 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
initial={{ scaleY: 0 }}
animate={{ scaleY: 1 }}
exit={{ scaleY: 0 }}
className="segment-list-entry"
>
<div style={{ color: 'white', marginBottom: 3, display: 'flex', alignItems: 'center', height: 16 }}>
{renderNumber()}
@ -114,9 +118,9 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou
<Trans>{{ durationMsFormatted }} ms, {{ frameCount }} frames</Trans>
</div>
{!enabled && !invertCutSegments && (
<div style={{ position: 'absolute', pointerEvents: 'none', top: 0, right: 0, bottom: 0, left: 0, overflow: 'hidden', display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
<FaTimes style={{ fontSize: 100, color: 'rgba(255,0,0,0.8)' }} />
{!invertCutSegments && (
<div style={{ position: 'absolute', right: 3, bottom: 3 }}>
<CheckIcon className="enabled" size={20} onClick={onToggleSegmentSelectedClick} />
</div>
)}
</motion.div>
@ -128,7 +132,7 @@ const SegmentList = memo(({
currentSegIndex,
updateSegOrder, updateSegOrders, addCutSegment, removeCutSegment,
onLabelSegmentPress, currentCutSeg, segmentAtCursor, toggleSegmentsList, splitCurrentSegment,
enabledSegments, enabledSegmentsRaw, onExportSingleSegmentClick, onExportSegmentEnabledToggle, onExportSegmentDisableAll, onExportSegmentEnableAll,
selectedSegments, selectedSegmentsRaw, onSelectSingleSegment, onToggleSegmentSelected, onDeselectAllSegments, onSelectAllSegments,
jumpSegStart, jumpSegEnd, onViewSegmentTagsPress,
}) => {
const { t } = useTranslation();
@ -174,14 +178,7 @@ const SegmentList = memo(({
const currentSegColor = getSegColor(currentCutSeg).alpha(0.5).string();
const segAtCursorColor = getSegColor(segmentAtCursor).alpha(0.5).string();
function renderExportEnabledCheckBox() {
const segmentExportEnabled = currentCutSeg && enabledSegmentsRaw.some((s) => s.segId === currentCutSeg.segId);
const Icon = segmentExportEnabled ? FaCheck : FaTimes;
return <Icon size={24} title={segmentExportEnabled ? t('Include this segment in export') : t('Exclude this segment from export')} style={{ ...buttonBaseStyle, backgroundColor: currentSegColor }} role="button" onClick={() => onExportSegmentEnabledToggle(currentCutSeg)} />;
}
const segmentsTotal = enabledSegments.reduce((acc, { start, end }) => (end - start) + acc, 0);
const segmentsTotal = selectedSegments.reduce((acc, { start, end }) => (end - start) + acc, 0);
return (
<>
@ -219,8 +216,6 @@ const SegmentList = memo(({
style={{ ...buttonBaseStyle, padding: 4, background: currentSegColor }}
onClick={() => onLabelSegmentPress(currentSegIndex)}
/>
{renderExportEnabledCheckBox()}
</>
)}
@ -264,7 +259,7 @@ const SegmentList = memo(({
<ReactSortable list={sortableList} setList={setSortableList} sort={!invertCutSegments}>
{sortableList.map(({ id, seg }, index) => {
const enabled = !invertCutSegments && enabledSegmentsRaw.includes(seg);
const enabled = !invertCutSegments && selectedSegmentsRaw.includes(seg);
return (
<Segment
key={id}
@ -283,10 +278,10 @@ const SegmentList = memo(({
formatTimecode={formatTimecode}
currentSegIndex={currentSegIndex}
invertCutSegments={invertCutSegments}
onExportSingleSegmentClick={onExportSingleSegmentClick}
onExportSegmentEnabledToggle={onExportSegmentEnabledToggle}
onExportSegmentDisableAll={onExportSegmentDisableAll}
onExportSegmentEnableAll={onExportSegmentEnableAll}
onSelectSingleSegment={onSelectSingleSegment}
onToggleSegmentSelected={onToggleSegmentSelected}
onDeselectAllSegments={onDeselectAllSegments}
onSelectAllSegments={onSelectAllSegments}
onViewSegmentTagsPress={onViewSegmentTagsPress}
/>
);

@ -14,7 +14,7 @@ import useUserSettings from './hooks/useUserSettings';
const TopMenu = memo(({
filePath, fileFormat, copyAnyAudioTrack, toggleStripAudio,
renderOutFmt, toggleHelp, numStreamsToCopy, numStreamsTotal, setStreamsSelectorShown, toggleSettings,
enabledSegments, isCustomFormatSelected, clearOutDir,
selectedSegments, isCustomFormatSelected, clearOutDir,
}) => {
const { t } = useTranslation();
const { customOutDir, changeOutDir, simpleMode, outFormatLocked, setOutFormatLocked } = useUserSettings();
@ -78,7 +78,7 @@ const TopMenu = memo(({
{!simpleMode && (isCustomFormatSelected || outFormatLocked) && renderFormatLock()}
<MergeExportButton enabledSegments={enabledSegments} />
<MergeExportButton selectedSegments={selectedSegments} />
</>
)}

@ -7,7 +7,7 @@ import { primaryColor } from '../colors';
import useUserSettings from '../hooks/useUserSettings';
const ExportButton = memo(({ enabledSegments, areWeCutting, onClick, size = 1 }) => {
const ExportButton = memo(({ selectedSegments, areWeCutting, onClick, size = 1 }) => {
const CutIcon = areWeCutting ? FiScissors : FaFileExport;
const { t } = useTranslation();
@ -15,13 +15,13 @@ const ExportButton = memo(({ enabledSegments, areWeCutting, onClick, size = 1 })
const { autoMerge } = useUserSettings();
let exportButtonTitle = t('Export');
if (enabledSegments.length === 1) {
if (selectedSegments.length === 1) {
exportButtonTitle = t('Export selection');
} else if (enabledSegments.length > 1) {
exportButtonTitle = t('Export {{ num }} segments', { num: enabledSegments.length });
} else if (selectedSegments.length > 1) {
exportButtonTitle = t('Export {{ num }} segments', { num: selectedSegments.length });
}
const exportButtonText = autoMerge && enabledSegments && enabledSegments.length > 1 ? t('Export+merge') : t('Export');
const exportButtonText = autoMerge && selectedSegments && selectedSegments.length > 1 ? t('Export+merge') : t('Export');
return (
<div

@ -309,19 +309,19 @@ const KeyboardShortcuts = memo(({
category: segmentsAndCutpointsCategory,
},
enableOnlyCurrentSegment: {
name: t('Include ONLY this segment in export'),
name: t('Select ONLY current segment'),
category: segmentsAndCutpointsCategory,
},
disableAllSegments: {
name: t('Exclude all segments from export'),
name: t('Deselect all segments'),
category: segmentsAndCutpointsCategory,
},
enableAllSegments: {
name: t('Include all segments in export'),
name: t('Select all segments'),
category: segmentsAndCutpointsCategory,
},
toggleCurrentSegmentEnabled: {
name: t('Toggle inclusion of this segment in export'),
name: t('Toggle current segment selected'),
category: segmentsAndCutpointsCategory,
},

@ -7,7 +7,7 @@ import { withBlur } from '../util';
import useUserSettings from '../hooks/useUserSettings';
const MergeExportButton = memo(({ enabledSegments }) => {
const MergeExportButton = memo(({ selectedSegments }) => {
const { t } = useTranslation();
const { autoMerge, setAutoMerge, autoDeleteMergedSegments, setAutoDeleteMergedSegments, segmentsToChaptersOnly, setSegmentsToChaptersOnly } = useUserSettings();
@ -66,7 +66,7 @@ const MergeExportButton = memo(({ enabledSegments }) => {
return (
<Button
height={20}
style={{ minWidth: 120, textAlign: 'center', opacity: enabledSegments && enabledSegments.length < 2 ? 0.4 : undefined }}
style={{ minWidth: 120, textAlign: 'center', opacity: selectedSegments && selectedSegments.length < 2 ? 0.4 : undefined }}
title={description}
onClick={withBlur(onClick)}
iconBefore={AutoMergeIcon && <AutoMergeIcon />}

@ -57,3 +57,11 @@ kbd {
align-items: flex-start !important;
text-align: left;
}
.segment-list-entry .enabled {
display: none;
}
.segment-list-entry:hover .enabled {
display: inherit;
}

Loading…
Cancel
Save