From 391cab538c85364ba0006f42ff4e95f00ae53301 Mon Sep 17 00:00:00 2001 From: Mikael Finstad Date: Fri, 10 Mar 2023 15:08:58 +0800 Subject: [PATCH] improve export confirm --- src/components/ExportConfirm.jsx | 272 ++++++++++++++++------- src/components/ExportConfirm.module.css | 11 + src/components/HighlightedText.jsx | 2 +- src/components/MovFastStartButton.jsx | 8 +- src/components/OutSegTemplateEditor.jsx | 16 +- src/components/PreserveMovDataButton.jsx | 8 +- 6 files changed, 210 insertions(+), 107 deletions(-) diff --git a/src/components/ExportConfirm.jsx b/src/components/ExportConfirm.jsx index 0b0a7e6c..ecd76fc9 100644 --- a/src/components/ExportConfirm.jsx +++ b/src/components/ExportConfirm.jsx @@ -1,6 +1,6 @@ import React, { memo, useCallback, useMemo } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; -import { WarningSignIcon, Button, CrossIcon } from 'evergreen-ui'; +import { WarningSignIcon, CrossIcon } from 'evergreen-ui'; import { FaRegCheckCircle } from 'react-icons/fa'; import i18n from 'i18next'; import { useTranslation, Trans } from 'react-i18next'; @@ -15,6 +15,7 @@ import ToggleExportConfirm from './ToggleExportConfirm'; import OutSegTemplateEditor from './OutSegTemplateEditor'; import HighlightedText, { highlightedTextStyle } from './HighlightedText'; import Select from './Select'; +import Switch from './Switch'; import { primaryTextColor } from '../colors'; import { withBlur } from '../util'; @@ -106,8 +107,6 @@ const ExportConfirm = memo(({ toast.fire({ icon: 'info', timer: 10000, text: `${avoidNegativeTs}: ${texts[avoidNegativeTs]}` }); }, [avoidNegativeTs]); - const outSegTemplateHelpIcon = ; - const canEditTemplate = !willMerge || !autoDeleteMergedSegments; // https://stackoverflow.com/questions/33454533/cant-scroll-to-top-of-flex-item-that-is-overflowing-container @@ -127,94 +126,199 @@ const ExportConfirm = memo(({

{t('Export options')}

-
    - {selectedSegments.length !== nonFilteredSegmentsOrInverse.length &&
  • {t('{{selectedSegments}} of {{nonFilteredSegments}} segments selected', { selectedSegments: selectedSegments.length, nonFilteredSegments: nonFilteredSegmentsOrInverse.length })}
  • } -
  • - {selectedSegments.length > 1 ? t('Export mode for {{segments}} segments', { segments: selectedSegments.length }) : t('Export mode')} - - {effectiveExportMode === 'sesgments_to_chapters' && } -
  • -
  • - {t('Output container format:')} {renderOutFmt({ height: 20, maxWidth: 150 })} - -
  • -
  • - Input has {{ numStreamsTotal }} tracks - setStreamsSelectorShown(true)}>Keeping {{ numStreamsToCopy }} tracks - - {areWeCuttingProblematicStreams && } - {areWeCuttingProblematicStreams &&
    Warning: Cutting thumbnail tracks is known to cause problems. Consider disabling track {{ trackNumber: mainCopiedThumbnailStreams[0].index + 1 }}.
    } -
  • -
  • - {t('Save output to path:')} {outputDir} -
  • - {canEditTemplate && ( -
  • - -
  • - )} -
+ + + {selectedSegments.length !== nonFilteredSegmentsOrInverse.length && ( + + + + )} + + + + + + + + + + + + + + + + + + + + + + {canEditTemplate && ( + + + + + )} + +
+ {t('{{selectedSegments}} of {{nonFilteredSegments}} segments selected', { selectedSegments: selectedSegments.length, nonFilteredSegments: nonFilteredSegmentsOrInverse.length })} + +
+ {selectedSegments.length > 1 ? t('Export mode for {{segments}} segments', { segments: selectedSegments.length }) : t('Export mode')} + + + + {effectiveExportMode === 'sesgments_to_chapters' && } + +
+ {t('Output container format:')} + + {renderOutFmt({ height: 20, maxWidth: 150 })} + + +
+ Input has {{ numStreamsTotal }} tracks + {areWeCuttingProblematicStreams && ( +
Warning: Cutting thumbnail tracks is known to cause problems. Consider disabling track {{ trackNumber: mainCopiedThumbnailStreams[0] ? mainCopiedThumbnailStreams[0].index + 1 : 0 }}.
+ )} +
+ setStreamsSelectorShown(true)}>Keeping {{ numStreamsToCopy }} tracks + + {areWeCuttingProblematicStreams && } + +
+ {t('Save output to path:')} + + {outputDir} + +
+ + + +

{t('Advanced options')}

- {willMerge && ( -
    -
  • - {t('Create chapters from merged segments? (slow)')} - -
  • -
  • - {t('Preserve original metadata when merging? (slow)')} - -
  • -
- )} + + + {willMerge && ( + <> + + + + + + + + + + + + )} -

{t('Depending on your specific file/player, you may have to try different options for best results.')}

+ + + -
    - {areWeCutting && ( - <> -
  • - {t('Smart cut (experimental):')} - - {needSmartCut && } -
  • - {!needSmartCut && ( -
  • - {t('Cut mode:')} - {!keyframeCut && {t('Note: Keyframe cut is recommended for most common files')}} -
  • - )} - - )} + {areWeCutting && ( + <> +
+ + + + + {!needSmartCut && ( + + + + + + )} + + )} - {isMov && ( - <> -
  • - {t('Enable MOV Faststart?')} - {isIpod && !movFastStart && {t('For the ipod format, it is recommended to activate this option')}} -
  • -
  • - {t('Preserve all MP4/MOV metadata?')} - {isIpod && preserveMovData && {t('For the ipod format, it is recommended to deactivate this option')}} -
  • - - )} + {isMov && ( + <> + + + + + + + + + + + + )} - {!needSmartCut && ( -
  • - "avoid_negative_ts" - - - {!['make_zero', 'auto'].includes(avoidNegativeTs) &&
    {t('It\'s generally recommended to set this to one of: {{values}}', { values: '"auto", "make_zero"' })}
    } -
  • - )} - + {!needSmartCut && ( + + + + + + )} + +
    + {t('Create chapters from merged segments? (slow)')} + + + + +
    + {t('Preserve original metadata when merging? (slow)')} + + + + +
    + {t('Depending on your specific file/player, you may have to try different options for best results.')} + +
    + {t('Smart cut (experimental):')} + + setEnableSmartCut((v) => !v)} /> + + {needSmartCut && } + +
    + {t('Cut mode:')} + {!keyframeCut &&
    {t('Note: Keyframe cut is recommended for most common files')}
    } +
    + + + {!keyframeCut && } + +
    + {t('Enable MOV Faststart?')} + + + + {isIpod && !movFastStart && {t('For the ipod format, it is recommended to activate this option')}} +
    + {t('Preserve all MP4/MOV metadata?')} + {isIpod && preserveMovData &&
    {t('For the ipod format, it is recommended to deactivate this option')}
    } +
    + + + {isIpod && preserveMovData && } + +
    + "avoid_negative_ts" + {!['make_zero', 'auto'].includes(avoidNegativeTs) &&
    {t('It\'s generally recommended to set this to one of: {{values}}', { values: '"auto", "make_zero"' })}
    } +
    + + + {!['make_zero', 'auto'].includes(avoidNegativeTs) && } + +
    diff --git a/src/components/ExportConfirm.module.css b/src/components/ExportConfirm.module.css index 817c055a..3328d0db 100644 --- a/src/components/ExportConfirm.module.css +++ b/src/components/ExportConfirm.module.css @@ -24,3 +24,14 @@ background: var(--blackA8); } +table.options { + width: 100%; +} + +table.options td:last-child { + text-align: right; + width: 3em; +} +table.options td:nth-child(2) { + text-align: right; +} diff --git a/src/components/HighlightedText.jsx b/src/components/HighlightedText.jsx index 1ef6c551..c6b44b1a 100644 --- a/src/components/HighlightedText.jsx +++ b/src/components/HighlightedText.jsx @@ -2,7 +2,7 @@ import React, { memo } from 'react'; import { primaryTextColor } from '../colors'; -export const highlightedTextStyle = { textDecoration: 'underline', textUnderlineOffset: '.2em', textDecorationColor: primaryTextColor, color: 'var(--gray12)', borderRadius: '.4em', padding: '0 .3em' }; +export const highlightedTextStyle = { textDecoration: 'underline', textUnderlineOffset: '.2em', textDecorationColor: primaryTextColor, color: 'var(--gray12)', borderRadius: '.4em' }; // eslint-disable-next-line react/jsx-props-no-spreading const HighlightedText = memo(({ children, style, ...props }) => {children}); diff --git a/src/components/MovFastStartButton.jsx b/src/components/MovFastStartButton.jsx index 40699e90..29a71f79 100644 --- a/src/components/MovFastStartButton.jsx +++ b/src/components/MovFastStartButton.jsx @@ -1,19 +1,15 @@ import React, { memo } from 'react'; -import { Button } from 'evergreen-ui'; -import { useTranslation } from 'react-i18next'; import { withBlur } from '../util'; import useUserSettings from '../hooks/useUserSettings'; +import Switch from './Switch'; const MovFastStartButton = memo(() => { - const { t } = useTranslation(); const { movFastStart, toggleMovFastStart } = useUserSettings(); return ( - + ); }); diff --git a/src/components/OutSegTemplateEditor.jsx b/src/components/OutSegTemplateEditor.jsx index bfcee81d..1ef0615e 100644 --- a/src/components/OutSegTemplateEditor.jsx +++ b/src/components/OutSegTemplateEditor.jsx @@ -15,9 +15,9 @@ const ReactSwal = withReactContent(Swal); // eslint-disable-next-line no-template-curly-in-string const extVar = '${EXT}'; -const inputStyle = { flexGrow: 1, fontFamily: 'inherit', fontSize: '.8em', backgroundColor: 'var(--gray3)', color: 'var(--gray12)', appearance: 'none', border: 'none' }; +const inputStyle = { flexGrow: 1, fontFamily: 'inherit', fontSize: '.8em', backgroundColor: 'var(--gray3)', color: 'var(--gray12)', border: '1px solid var(--gray6)', appearance: 'none' }; -const OutSegTemplateEditor = memo(({ helpIcon, outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe, getOutSegError }) => { +const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe, getOutSegError }) => { const { safeOutputFileName, toggleSafeOutputFileName } = useUserSettings(); const [text, setText] = useState(outSegTemplate); @@ -86,12 +86,9 @@ const OutSegTemplateEditor = memo(({ helpIcon, outSegTemplate, setOutSegTemplate return ( <>
    - - {outSegFileNames != null && t('Output name(s):', { count: outSegFileNames.length })} - {' '} - {outSegFileNames != null && {outSegFileNames[currentSegIndexSafe] || outSegFileNames[0] || '-'}} - - {helpIcon} +
    {outSegFileNames != null && t('Output name(s):', { count: outSegFileNames.length })}
    + + {outSegFileNames != null && {outSegFileNames[currentSegIndexSafe] || outSegFileNames[0] || '-'}}
    {needToShow && ( @@ -107,8 +104,7 @@ const OutSegTemplateEditor = memo(({ helpIcon, outSegTemplate, setOutSegTemplate
    {error != null && {i18n.t('There is an error in the file name template:')}{error}} {isMissingExtension && {i18n.t('The file name template is missing {{ext}} and will result in a file without the suggested extension. This may result in an unplayable output file.', { ext: extVar })}} - {/* eslint-disable-next-line no-template-curly-in-string */} -
    +
    {`${i18n.t('Variables')}`}{': '} {['FILENAME', 'CUT_FROM', 'CUT_TO', 'SEG_NUM', 'SEG_LABEL', 'SEG_SUFFIX', 'EXT', 'SEG_TAGS.XX'].map((variable) => setText((oldText) => `${oldText}\${${variable}}`)}>{variable})}
    diff --git a/src/components/PreserveMovDataButton.jsx b/src/components/PreserveMovDataButton.jsx index 74ee1157..04a1153b 100644 --- a/src/components/PreserveMovDataButton.jsx +++ b/src/components/PreserveMovDataButton.jsx @@ -1,19 +1,15 @@ import React, { memo } from 'react'; -import { Button } from 'evergreen-ui'; -import { useTranslation } from 'react-i18next'; import { withBlur } from '../util'; import useUserSettings from '../hooks/useUserSettings'; +import Switch from './Switch'; const PreserveMovDataButton = memo(() => { - const { t } = useTranslation(); const { preserveMovData, togglePreserveMovData } = useUserSettings(); return ( - + ); });