From 100011750ce0ba885d4e924c954e1bed76de167f Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Thu, 20 Feb 2020 22:01:03 +0800 Subject: [PATCH] allow labeling segments #199 also fix color bug --- src/TimelineSeg.jsx | 11 +++++- src/renderer.jsx | 95 +++++++++++++++++++++++++++++++++------------ 2 files changed, 79 insertions(+), 27 deletions(-) diff --git a/src/TimelineSeg.jsx b/src/TimelineSeg.jsx index 47a257f9..d3cf8599 100644 --- a/src/TimelineSeg.jsx +++ b/src/TimelineSeg.jsx @@ -8,7 +8,7 @@ const { formatDuration } = require('./util'); const TimelineSeg = ({ - duration, cutStart, cutEnd, isActive, segNum, + duration, cutStart, cutEnd, isActive, segNum, name, onSegClick, invertCutSegments, segBgColor, segActiveBgColor, segBorderColor, }) => { const cutSectionWidth = `${((cutEnd - cutStart) / duration) * 100}%`; @@ -42,6 +42,9 @@ const TimelineSeg = ({ const onThisSegClick = () => onSegClick(segNum); + const durationStr = cutEnd > cutStart ? `${formatDuration({ seconds: cutEnd - cutStart })} ` : ''; + const title = `${durationStr}${name}`; + return ( cutStart ? formatDuration({ seconds: cutEnd - cutStart }) : undefined} + title={title} >
{segNum + 1}
@@ -71,6 +74,10 @@ const TimelineSeg = ({ )} + {name &&
} + + {name &&
{name}
} +
); diff --git a/src/renderer.jsx b/src/renderer.jsx index e95f500d..bbf24a32 100644 --- a/src/renderer.jsx +++ b/src/renderer.jsx @@ -1,6 +1,6 @@ import React, { memo, useEffect, useState, useCallback, useRef, Fragment } from 'react'; import { IoIosHelpCircle, IoIosCamera } from 'react-icons/io'; -import { FaPlus, FaMinus, FaHandPointRight, FaHandPointLeft, FaTrashAlt, FaVolumeMute, FaVolumeUp, FaYinYang, FaFileExport } from 'react-icons/fa'; +import { FaPlus, FaMinus, FaHandPointRight, FaHandPointLeft, FaTrashAlt, FaVolumeMute, FaVolumeUp, FaYinYang, FaFileExport, FaTag } from 'react-icons/fa'; import { MdRotate90DegreesCcw, MdCallSplit, MdCallMerge } from 'react-icons/md'; import { FiScissors } from 'react-icons/fi'; import { AnimatePresence, motion } from 'framer-motion'; @@ -64,6 +64,7 @@ function createSegment({ start, end } = {}) { return { start, end, + name: '', color: generateColor(), uuid: uuid.v4(), }; @@ -302,7 +303,6 @@ const App = memo(() => { })(); const setCutTime = useCallback((type, time) => { - const cloned = cloneDeep(cutSegments); const currentSeg = currentCutSeg; if (type === 'start' && time >= getSegApparentEnd(currentSeg)) { throw new Error('Start time must precede end time'); @@ -310,12 +310,19 @@ const App = memo(() => { if (type === 'end' && time <= getSegApparentStart(currentSeg)) { throw new Error('Start time must precede end time'); } + const cloned = cloneDeep(cutSegments); cloned[currentSegIndexSafe][type] = Math.min(Math.max(time, 0), duration); setCutSegments(cloned); }, [ currentSegIndexSafe, getSegApparentEnd, cutSegments, currentCutSeg, setCutSegments, duration, ]); + const setCurrentSegmentName = (name) => { + const cloned = cloneDeep(cutSegments); + cloned[currentSegIndexSafe].name = name; + setCutSegments(cloned); + }; + function formatTimecode(sec) { return formatDuration({ seconds: sec, fps: timecodeShowFrames ? detectedFps : undefined }); } @@ -1063,10 +1070,21 @@ const App = memo(() => { const otherFormatsMap = fromPairs(Object.entries(allOutFormats) .filter(([f]) => ![...commonFormats, detectedFileFormat].includes(f))); - const segColor = (currentCutSeg || {}).color; - const segBgColor = segColor.alpha(0.5).string(); - const segActiveBgColor = segColor.lighten(0.5).alpha(0.5).string(); - const segBorderColor = segColor.lighten(0.5).string(); + function getSegColors(seg) { + if (!seg) return {}; + const { color } = seg; + return { + segBgColor: color.alpha(0.5).string(), + segActiveBgColor: color.lighten(0.5).alpha(0.5).string(), + segBorderColor: color.lighten(0.5).string(), + }; + } + + const { + segBgColor: currentSegBgColor, + segActiveBgColor: currentSegActiveBgColor, + segBorderColor: currentSegBorderColor, + } = getSegColors(currentCutSeg); const jumpCutButtonStyle = { position: 'absolute', color: 'black', bottom: 0, top: 0, padding: '2px 8px', @@ -1277,16 +1295,27 @@ const App = memo(() => { return () => window.removeEventListener('keydown', keyScrollPreventer); }, []); + async function onLabelSegmentPress() { + const { value } = await Swal.fire({ + showCancelButton: true, + title: 'Label current segment', + inputValue: currentCutSeg.name, + input: 'text', + }); + + if (value != null) setCurrentSegmentName(value); + } + function renderSetCutpointButton(side) { const start = side === 'start'; const Icon = start ? FaHandPointLeft : FaHandPointRight; - const border = `4px solid ${segBorderColor}`; + const border = `4px solid ${currentSegBorderColor}`; return ( ); @@ -1485,22 +1514,29 @@ const App = memo(() => { {currentTimePos !== undefined && } {commandedTimePos !== undefined &&
} - {apparentCutSegments.map((seg, i) => ( - setCurrentSegIndex(currentSegIndexNew)} - isActive={i === currentSegIndexSafe} - duration={durationSafe} - cutStart={seg.start} - cutEnd={seg.end} - invertCutSegments={invertCutSegments} - zoomed={zoomed} - /> - ))} + {apparentCutSegments.map((seg, i) => { + const { + segBgColor, segActiveBgColor, segBorderColor, + } = getSegColors(seg); + + return ( + setCurrentSegIndex(currentSegIndexNew)} + isActive={i === currentSegIndexSafe} + duration={durationSafe} + name={seg.name} + cutStart={seg.start} + cutEnd={seg.end} + invertCutSegments={invertCutSegments} + zoomed={zoomed} + /> + ); + })} {inverseCutSegments && inverseCutSegments.map((seg, i) => ( { { ); })} + + +