mirror of
https://github.com/mifi/lossless-cut.git
synced 2024-11-22 10:22:31 +01:00
reduce the risk of overwriting source files
This commit is contained in:
parent
bc04a4f2a4
commit
35e12d3a3d
@ -1176,8 +1176,8 @@ function App() {
|
||||
|
||||
console.log('outSegTemplateOrDefault', outSegTemplateOrDefault);
|
||||
|
||||
const { outSegFileNames, outSegError } = generateOutSegFileNames({ segments: segmentsToExport, template: outSegTemplateOrDefault });
|
||||
if (outSegError != null) {
|
||||
const { outSegFileNames, outSegProblems } = generateOutSegFileNames({ segments: segmentsToExport, template: outSegTemplateOrDefault });
|
||||
if (outSegProblems.error != null) {
|
||||
console.warn('Output segments file name invalid, using default instead', outSegFileNames);
|
||||
}
|
||||
|
||||
|
@ -23,13 +23,13 @@ const formatVariable = (variable) => `\${${variable}}`;
|
||||
|
||||
const extVar = formatVariable('EXT');
|
||||
|
||||
const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe, getOutSegError }) => {
|
||||
const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generateOutSegFileNames, currentSegIndexSafe }) => {
|
||||
const { safeOutputFileName, toggleSafeOutputFileName, outputFileNameMinZeroPadding, setOutputFileNameMinZeroPadding } = useUserSettings();
|
||||
|
||||
const [text, setText] = useState(outSegTemplate);
|
||||
const [debouncedText] = useDebounce(text, 500);
|
||||
const [validText, setValidText] = useState();
|
||||
const [error, setError] = useState();
|
||||
const [outSegProblems, setOutSegProblems] = useState({ error: undefined, sameAsInputFileNameWarning: false });
|
||||
const [outSegFileNames, setOutSegFileNames] = useState();
|
||||
const [shown, setShown] = useState();
|
||||
const inputRef = useRef();
|
||||
@ -42,22 +42,16 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
||||
if (debouncedText == null) return;
|
||||
|
||||
try {
|
||||
const { outSegFileNames: newOutSegFileNames, outSegError } = generateOutSegFileNames({ template: debouncedText });
|
||||
setOutSegFileNames(newOutSegFileNames);
|
||||
if (outSegError) {
|
||||
setError(outSegError);
|
||||
setValidText();
|
||||
return;
|
||||
}
|
||||
|
||||
setValidText(debouncedText);
|
||||
setError();
|
||||
const outSegs = generateOutSegFileNames({ template: debouncedText });
|
||||
setOutSegFileNames(outSegs.outSegFileNames);
|
||||
setOutSegProblems(outSegs.outSegProblems);
|
||||
setValidText(outSegs.outSegProblems.error == null ? debouncedText : undefined);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setValidText();
|
||||
setError(err.message);
|
||||
setOutSegProblems({ error: err.message });
|
||||
}
|
||||
}, [debouncedText, generateOutSegFileNames, getOutSegError, t]);
|
||||
}, [debouncedText, generateOutSegFileNames, t]);
|
||||
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
const isMissingExtension = validText != null && !validText.endsWith(extVar);
|
||||
@ -80,8 +74,8 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
||||
}, [setOutSegTemplate]);
|
||||
|
||||
const onHideClick = useCallback(() => {
|
||||
if (error == null) setShown(false);
|
||||
}, [error]);
|
||||
if (outSegProblems.error == null) setShown(false);
|
||||
}, [outSegProblems.error]);
|
||||
|
||||
const onShowClick = useCallback(() => {
|
||||
if (!shown) setShown(true);
|
||||
@ -89,7 +83,7 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
||||
|
||||
const onTextChange = useCallback((e) => setText(e.target.value), []);
|
||||
|
||||
const needToShow = shown || error != null;
|
||||
const needToShow = shown || outSegProblems.error != null || outSegProblems.sameAsInputFileNameWarning;
|
||||
|
||||
const onVariableClick = useCallback((variable) => {
|
||||
const input = inputRef.current;
|
||||
@ -132,7 +126,18 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
||||
))}
|
||||
</div>
|
||||
|
||||
{error != null && <div style={{ marginBottom: '1em' }}><ErrorIcon color="var(--red9)" size={14} verticalAlign="baseline" /> {error}</div>}
|
||||
{outSegProblems.error != null && (
|
||||
<div style={{ marginBottom: '1em' }}>
|
||||
<ErrorIcon color="var(--red9)" size={14} verticalAlign="baseline" /> {outSegProblems.error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{outSegProblems.error == null && outSegProblems.sameAsInputFileNameWarning && (
|
||||
<div style={{ marginBottom: '1em' }}>
|
||||
<WarningSignIcon verticalAlign="middle" color="var(--amber9)" />{' '}
|
||||
{i18n.t('Output file name is the same as the source file name. This increases the risk of accidentally overwriting or deleting source files!')}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isMissingExtension && (
|
||||
<div style={{ marginBottom: '1em' }}>
|
||||
|
@ -9,10 +9,11 @@ import { getSegmentTags, formatSegNum } from '../segments';
|
||||
export const segNumVariable = 'SEG_NUM';
|
||||
export const segSuffixVariable = 'SEG_SUFFIX';
|
||||
|
||||
const { parse: parsePath, sep: pathSep, join: pathJoin, normalize: pathNormalize } = window.require('path');
|
||||
const { parse: parsePath, sep: pathSep, join: pathJoin, normalize: pathNormalize, basename } = window.require('path');
|
||||
|
||||
function getOutSegError({ fileNames, filePath, outputDir, safeOutputFileName }) {
|
||||
function getOutSegProblems({ fileNames, filePath, outputDir, safeOutputFileName }) {
|
||||
let error;
|
||||
let sameAsInputFileNameWarning = false;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const fileName of fileNames) {
|
||||
@ -49,6 +50,10 @@ function getOutSegError({ fileNames, filePath, outputDir, safeOutputFileName })
|
||||
const shouldCheckPathLength = isWindows || isDev;
|
||||
const shouldCheckFileEnd = isWindows || isDev;
|
||||
|
||||
if (basename(filePath) === fileName) {
|
||||
sameAsInputFileNameWarning = true; // just an extra warning in case sameAsInputPath doesn't work
|
||||
}
|
||||
|
||||
if (fileName.length === 0) {
|
||||
error = i18n.t('At least one resulting file name has no length');
|
||||
break;
|
||||
@ -73,11 +78,14 @@ function getOutSegError({ fileNames, filePath, outputDir, safeOutputFileName })
|
||||
}
|
||||
}
|
||||
|
||||
if (error != null) return error;
|
||||
if (error == null && hasDuplicates(fileNames)) {
|
||||
error = i18n.t('Output file name template results in duplicate file names (you are trying to export multiple files with the same name). You can fix this for example by adding the "{{segNumVariable}}" variable.', { segNumVariable });
|
||||
}
|
||||
|
||||
if (hasDuplicates(fileNames)) return i18n.t('Output file name template results in duplicate file names (you are trying to export multiple files with the same name). You can fix this for example by adding the "{{segNumVariable}}" variable.', { segNumVariable });
|
||||
|
||||
return undefined;
|
||||
return {
|
||||
error,
|
||||
sameAsInputFileNameWarning,
|
||||
};
|
||||
}
|
||||
|
||||
// This is used as a fallback and so it has to always generate unique file names
|
||||
@ -155,10 +163,10 @@ export function generateOutSegFileNames({ segments, template: desiredTemplate, f
|
||||
|
||||
let outSegFileNames = generate({ template: desiredTemplate, forceSafeOutputFileName: false });
|
||||
|
||||
const outSegError = getOutSegError({ fileNames: outSegFileNames, filePath, outputDir, safeOutputFileName });
|
||||
if (outSegError != null) {
|
||||
const outSegProblems = getOutSegProblems({ fileNames: outSegFileNames, filePath, outputDir, safeOutputFileName });
|
||||
if (outSegProblems.error != null) {
|
||||
outSegFileNames = generate({ template: defaultOutSegTemplate, forceSafeOutputFileName: true });
|
||||
}
|
||||
|
||||
return { outSegFileNames, outSegError };
|
||||
return { outSegFileNames, outSegProblems };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user