mirror of
https://github.com/mifi/lossless-cut.git
synced 2024-11-22 18:32:34 +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);
|
console.log('outSegTemplateOrDefault', outSegTemplateOrDefault);
|
||||||
|
|
||||||
const { outSegFileNames, outSegError } = generateOutSegFileNames({ segments: segmentsToExport, template: outSegTemplateOrDefault });
|
const { outSegFileNames, outSegProblems } = generateOutSegFileNames({ segments: segmentsToExport, template: outSegTemplateOrDefault });
|
||||||
if (outSegError != null) {
|
if (outSegProblems.error != null) {
|
||||||
console.warn('Output segments file name invalid, using default instead', outSegFileNames);
|
console.warn('Output segments file name invalid, using default instead', outSegFileNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +23,13 @@ const formatVariable = (variable) => `\${${variable}}`;
|
|||||||
|
|
||||||
const extVar = formatVariable('EXT');
|
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 { safeOutputFileName, toggleSafeOutputFileName, outputFileNameMinZeroPadding, setOutputFileNameMinZeroPadding } = useUserSettings();
|
||||||
|
|
||||||
const [text, setText] = useState(outSegTemplate);
|
const [text, setText] = useState(outSegTemplate);
|
||||||
const [debouncedText] = useDebounce(text, 500);
|
const [debouncedText] = useDebounce(text, 500);
|
||||||
const [validText, setValidText] = useState();
|
const [validText, setValidText] = useState();
|
||||||
const [error, setError] = useState();
|
const [outSegProblems, setOutSegProblems] = useState({ error: undefined, sameAsInputFileNameWarning: false });
|
||||||
const [outSegFileNames, setOutSegFileNames] = useState();
|
const [outSegFileNames, setOutSegFileNames] = useState();
|
||||||
const [shown, setShown] = useState();
|
const [shown, setShown] = useState();
|
||||||
const inputRef = useRef();
|
const inputRef = useRef();
|
||||||
@ -42,22 +42,16 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
|||||||
if (debouncedText == null) return;
|
if (debouncedText == null) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { outSegFileNames: newOutSegFileNames, outSegError } = generateOutSegFileNames({ template: debouncedText });
|
const outSegs = generateOutSegFileNames({ template: debouncedText });
|
||||||
setOutSegFileNames(newOutSegFileNames);
|
setOutSegFileNames(outSegs.outSegFileNames);
|
||||||
if (outSegError) {
|
setOutSegProblems(outSegs.outSegProblems);
|
||||||
setError(outSegError);
|
setValidText(outSegs.outSegProblems.error == null ? debouncedText : undefined);
|
||||||
setValidText();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setValidText(debouncedText);
|
|
||||||
setError();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
setValidText();
|
setValidText();
|
||||||
setError(err.message);
|
setOutSegProblems({ error: err.message });
|
||||||
}
|
}
|
||||||
}, [debouncedText, generateOutSegFileNames, getOutSegError, t]);
|
}, [debouncedText, generateOutSegFileNames, t]);
|
||||||
|
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
const isMissingExtension = validText != null && !validText.endsWith(extVar);
|
const isMissingExtension = validText != null && !validText.endsWith(extVar);
|
||||||
@ -80,8 +74,8 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
|||||||
}, [setOutSegTemplate]);
|
}, [setOutSegTemplate]);
|
||||||
|
|
||||||
const onHideClick = useCallback(() => {
|
const onHideClick = useCallback(() => {
|
||||||
if (error == null) setShown(false);
|
if (outSegProblems.error == null) setShown(false);
|
||||||
}, [error]);
|
}, [outSegProblems.error]);
|
||||||
|
|
||||||
const onShowClick = useCallback(() => {
|
const onShowClick = useCallback(() => {
|
||||||
if (!shown) setShown(true);
|
if (!shown) setShown(true);
|
||||||
@ -89,7 +83,7 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
|||||||
|
|
||||||
const onTextChange = useCallback((e) => setText(e.target.value), []);
|
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 onVariableClick = useCallback((variable) => {
|
||||||
const input = inputRef.current;
|
const input = inputRef.current;
|
||||||
@ -132,7 +126,18 @@ const OutSegTemplateEditor = memo(({ outSegTemplate, setOutSegTemplate, generate
|
|||||||
))}
|
))}
|
||||||
</div>
|
</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 && (
|
{isMissingExtension && (
|
||||||
<div style={{ marginBottom: '1em' }}>
|
<div style={{ marginBottom: '1em' }}>
|
||||||
|
@ -9,10 +9,11 @@ import { getSegmentTags, formatSegNum } from '../segments';
|
|||||||
export const segNumVariable = 'SEG_NUM';
|
export const segNumVariable = 'SEG_NUM';
|
||||||
export const segSuffixVariable = 'SEG_SUFFIX';
|
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 error;
|
||||||
|
let sameAsInputFileNameWarning = false;
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
for (const fileName of fileNames) {
|
for (const fileName of fileNames) {
|
||||||
@ -49,6 +50,10 @@ function getOutSegError({ fileNames, filePath, outputDir, safeOutputFileName })
|
|||||||
const shouldCheckPathLength = isWindows || isDev;
|
const shouldCheckPathLength = isWindows || isDev;
|
||||||
const shouldCheckFileEnd = 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) {
|
if (fileName.length === 0) {
|
||||||
error = i18n.t('At least one resulting file name has no length');
|
error = i18n.t('At least one resulting file name has no length');
|
||||||
break;
|
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 {
|
||||||
|
error,
|
||||||
return undefined;
|
sameAsInputFileNameWarning,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used as a fallback and so it has to always generate unique file names
|
// 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 });
|
let outSegFileNames = generate({ template: desiredTemplate, forceSafeOutputFileName: false });
|
||||||
|
|
||||||
const outSegError = getOutSegError({ fileNames: outSegFileNames, filePath, outputDir, safeOutputFileName });
|
const outSegProblems = getOutSegProblems({ fileNames: outSegFileNames, filePath, outputDir, safeOutputFileName });
|
||||||
if (outSegError != null) {
|
if (outSegProblems.error != null) {
|
||||||
outSegFileNames = generate({ template: defaultOutSegTemplate, forceSafeOutputFileName: true });
|
outSegFileNames = generate({ template: defaultOutSegTemplate, forceSafeOutputFileName: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { outSegFileNames, outSegError };
|
return { outSegFileNames, outSegProblems };
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user