diff --git a/src/App.jsx b/src/App.jsx index b95b2368..6fbc1e9e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,6 @@ import React, { memo, useEffect, useState, useCallback, useRef, useMemo } from 'react'; import { unstable_batchedUpdates as batchedUpdates } from 'react-dom'; -import { FaAngleLeft, FaWindowClose, FaTimes, FaAngleRight, FaFile } from 'react-icons/fa'; +import { FaAngleLeft, FaWindowClose, FaTimes } from 'react-icons/fa'; import { AnimatePresence, motion } from 'framer-motion'; import Lottie from 'react-lottie-player'; import { SideSheet, Button, Position, ForkIcon, DisableIcon, Select, ThemeProvider } from 'evergreen-ui'; @@ -39,6 +39,8 @@ import ExportConfirm from './ExportConfirm'; import ValueTuner from './components/ValueTuner'; import VolumeControl from './components/VolumeControl'; import SubtitleControl from './components/SubtitleControl'; +import BatchFile from './components/BatchFile'; + import { loadMifiLink } from './mifi'; import { primaryColor, controlsBackground, timelineBackground } from './colors'; import allOutFormats from './outFormats'; @@ -2331,17 +2333,9 @@ const App = memo(() => {
- {batchFiles.map(({ path, name }) => { - const isCurrent = path === filePath; - return ( -
batchOpenSingleFile(path)}> - -
{name}
-
- {isCurrent && } -
- ); - })} + {batchFiles.map(({ path, name }) => ( + + ))}
)} diff --git a/src/SegmentList.jsx b/src/SegmentList.jsx index 6400ea18..f13b843a 100644 --- a/src/SegmentList.jsx +++ b/src/SegmentList.jsx @@ -25,33 +25,38 @@ const Segment = memo(({ seg, index, currentSegIndex, formatTimecode, getFrameCou const ref = useRef(); - useContextMenu(ref, invertCutSegments ? [] : [ - { label: t('Jump to cut start'), click: jumpSegStart }, - { label: t('Jump to cut end'), click: jumpSegEnd }, + const contextMenuTemplate = useMemo(() => { + if (invertCutSegments) return []; + return [ + { label: t('Jump to cut start'), click: jumpSegStart }, + { label: t('Jump to cut end'), click: jumpSegEnd }, - { type: 'separator' }, + { type: 'separator' }, - { label: t('Add segment'), click: addCutSegment }, - { label: t('Label segment'), click: onLabelPress }, - { label: t('Remove segment'), click: onRemovePress }, + { label: t('Add segment'), click: addCutSegment }, + { label: t('Label segment'), click: onLabelPress }, + { label: t('Remove segment'), click: onRemovePress }, - { type: 'separator' }, + { type: 'separator' }, - { label: t('Change segment order'), click: onReorderPress }, - { label: t('Increase segment order'), click: () => updateOrder(1) }, - { label: t('Decrease segment order'), click: () => updateOrder(-1) }, + { label: t('Change segment order'), click: onReorderPress }, + { label: t('Increase segment order'), click: () => updateOrder(1) }, + { label: t('Decrease segment order'), click: () => updateOrder(-1) }, - { type: 'separator' }, + { 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('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) }, - { type: 'separator' }, + { type: 'separator' }, - { label: t('Segment tags'), click: () => onViewSegmentTagsPress(index) }, - ]); + { label: t('Segment tags'), click: () => onViewSegmentTagsPress(index) }, + ]; + }, [addCutSegment, enabled, index, invertCutSegments, jumpSegEnd, jumpSegStart, onExportSegmentDisableAll, onExportSegmentEnableAll, onExportSegmentEnabledToggle, onExportSingleSegmentClick, onLabelPress, onRemovePress, onReorderPress, onViewSegmentTagsPress, seg, t, updateOrder]); + + useContextMenu(ref, contextMenuTemplate); const duration = seg.end - seg.start; const durationMs = duration * 1000; diff --git a/src/Timeline.jsx b/src/Timeline.jsx index e984fd0f..39e8c564 100644 --- a/src/Timeline.jsx +++ b/src/Timeline.jsx @@ -192,9 +192,11 @@ const Timeline = memo(({ const onMouseMove = useCallback((e) => setHoveringTime(getMouseTimelinePos(e.nativeEvent)), [getMouseTimelinePos]); const onMouseOut = useCallback(() => setHoveringTime(), []); - useContextMenu(timelineScrollerRef, [ + const contextMenuTemplate = useMemo(() => [ { label: t('Seek to timecode'), click: goToTimecode }, - ]); + ], [goToTimecode, t]); + + useContextMenu(timelineScrollerRef, contextMenuTemplate); return ( // eslint-disable-next-line jsx-a11y/mouse-events-have-key-events diff --git a/src/components/BatchFile.jsx b/src/components/BatchFile.jsx new file mode 100644 index 00000000..3c8b5e13 --- /dev/null +++ b/src/components/BatchFile.jsx @@ -0,0 +1,29 @@ +import React, { memo, useRef, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FaAngleRight, FaFile } from 'react-icons/fa'; + +import useContextMenu from '../hooks/useContextMenu'; +import { primaryColor } from '../colors'; + +const BatchFile = memo(({ path, filePath, name, onOpen, onDelete }) => { + const ref = useRef(); + + const { t } = useTranslation(); + const contextMenuTemplate = useMemo(() => [ + { label: t('Remove'), click: () => onDelete(path) }, + ], [t, onDelete, path]); + + useContextMenu(ref, contextMenuTemplate); + const isCurrent = path === filePath; + + return ( +
onOpen(path)}> + +
{name}
+
+ {isCurrent && } +
+ ); +}); + +export default BatchFile;