1
0
mirror of https://github.com/mifi/lossless-cut.git synced 2024-11-25 03:33:14 +01:00

allow drag-drop working dir

closes #2147
This commit is contained in:
Mikael Finstad 2024-09-29 10:33:05 +02:00
parent b855e9e7d1
commit cc202b4845
No known key found for this signature in database
GPG Key ID: 25AB36E3E81CBC26
4 changed files with 46 additions and 13 deletions

View File

@ -2281,11 +2281,21 @@ function App() {
focusWindow(); focusWindow();
await userOpenFiles(filePaths); userOpenFiles(filePaths);
}
const element = videoContainerRef.current;
element?.addEventListener('drop', onDrop);
return () => element?.removeEventListener('drop', onDrop);
}, [userOpenFiles, videoContainerRef]);
useEffect(() => {
function onDrop(ev: DragEvent) {
// default drop handler to prevent new electron window from popping up https://github.com/electron/electron/issues/39839
ev.preventDefault();
} }
document.body.addEventListener('drop', onDrop); document.body.addEventListener('drop', onDrop);
return () => document.body.removeEventListener('drop', onDrop); return () => document.body.removeEventListener('drop', onDrop);
}, [userOpenFiles]); }, []);
const renderOutFmt = useCallback((style: CSSProperties) => ( const renderOutFmt = useCallback((style: CSSProperties) => (
<OutputFormatSelect style={style} detectedFileFormat={detectedFileFormat} fileFormat={fileFormat} onOutputFormatUserChange={onOutputFormatUserChange} /> <OutputFormatSelect style={style} detectedFileFormat={detectedFileFormat} fileFormat={fileFormat} onOutputFormatUserChange={onOutputFormatUserChange} />

View File

@ -5,11 +5,15 @@ import { useTranslation, Trans } from 'react-i18next';
import SetCutpointButton from './components/SetCutpointButton'; import SetCutpointButton from './components/SetCutpointButton';
import SimpleModeButton from './components/SimpleModeButton'; import SimpleModeButton from './components/SimpleModeButton';
import useUserSettings from './hooks/useUserSettings'; import useUserSettings from './hooks/useUserSettings';
import { StateSegment } from './types';
const electron = window.require('electron'); const electron = window.require('electron');
function NoFileLoaded({ mifiLink, currentCutSeg, onClick, darkMode }: { function NoFileLoaded({ mifiLink, currentCutSeg, onClick, darkMode }: {
mifiLink: unknown, currentCutSeg, onClick: () => void, darkMode?: boolean, mifiLink: unknown,
currentCutSeg: StateSegment,
onClick: () => void,
darkMode?: boolean,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { simpleMode } = useUserSettings(); const { simpleMode } = useUserSettings();

View File

@ -1,4 +1,4 @@
import { CSSProperties, ReactNode, memo, useCallback } from 'react'; import { CSSProperties, ReactNode, memo, useCallback, useEffect, useRef } from 'react';
import { IoIosSettings } from 'react-icons/io'; import { IoIosSettings } from 'react-icons/io';
import { FaLock, FaUnlock } from 'react-icons/fa'; import { FaLock, FaUnlock } from 'react-icons/fa';
import { CrossIcon, ListIcon, VolumeUpIcon, VolumeOffIcon } from 'evergreen-ui'; import { CrossIcon, ListIcon, VolumeUpIcon, VolumeOffIcon } from 'evergreen-ui';
@ -13,6 +13,8 @@ import useUserSettings from './hooks/useUserSettings';
import { InverseCutSegment } from './types'; import { InverseCutSegment } from './types';
const { stat } = window.require('fs/promises');
const outFmtStyle = { height: 20, maxWidth: 100 }; const outFmtStyle = { height: 20, maxWidth: 100 };
const exportModeStyle = { flexGrow: 0, flexBasis: 140 }; const exportModeStyle = { flexGrow: 0, flexBasis: 140 };
@ -44,7 +46,8 @@ function TopMenu({
clearOutDir: () => void, clearOutDir: () => void,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { customOutDir, changeOutDir, simpleMode, outFormatLocked, setOutFormatLocked } = useUserSettings(); const { customOutDir, changeOutDir, setCustomOutDir, simpleMode, outFormatLocked, setOutFormatLocked } = useUserSettings();
const workingDirButtonRef = useRef<HTMLButtonElement>(null);
const onOutFormatLockedClick = useCallback(() => setOutFormatLocked((v) => (v ? undefined : fileFormat)), [fileFormat, setOutFormatLocked]); const onOutFormatLockedClick = useCallback(() => setOutFormatLocked((v) => (v ? undefined : fileFormat)), [fileFormat, setOutFormatLocked]);
@ -55,6 +58,22 @@ function TopMenu({
return <Icon onClick={onOutFormatLockedClick} title={t('Lock/unlock output format')} size={14} style={{ marginRight: 7, marginLeft: 2, color: outFormatLocked ? primaryTextColor : undefined }} />; return <Icon onClick={onOutFormatLockedClick} title={t('Lock/unlock output format')} size={14} style={{ marginRight: 7, marginLeft: 2, color: outFormatLocked ? primaryTextColor : undefined }} />;
} }
// Convenience for drag and drop: https://github.com/mifi/lossless-cut/issues/2147
useEffect(() => {
async function onDrop(ev: DragEvent) {
ev.preventDefault();
if (!ev.dataTransfer) return;
const paths = [...ev.dataTransfer.files].map((f) => f.path);
const [firstPath] = paths;
if (paths.length === 1 && firstPath && (await stat(firstPath)).isDirectory()) {
setCustomOutDir(firstPath);
}
}
const element = workingDirButtonRef.current;
element?.addEventListener('drop', onDrop);
return () => element?.removeEventListener('drop', onDrop);
}, [setCustomOutDir]);
return ( return (
<div <div
className="no-user-select" className="no-user-select"
@ -93,6 +112,7 @@ function TopMenu({
)} )}
<Button <Button
ref={workingDirButtonRef}
onClick={withBlur(changeOutDir)} onClick={withBlur(changeOutDir)}
title={customOutDir} title={customOutDir}
style={{ paddingLeft: showClearWorkingDirButton ? 4 : undefined }} style={{ paddingLeft: showClearWorkingDirButton ? 4 : undefined }}

View File

@ -1,12 +1,11 @@
import { ButtonHTMLAttributes, memo } from 'react'; import { ButtonHTMLAttributes, DetailedHTMLProps, forwardRef } from 'react';
import styles from './Button.module.css'; import styles from './Button.module.css';
function Button({ type = 'button', ...props }: ButtonHTMLAttributes<HTMLButtonElement>) { // eslint-disable-next-line react/display-name
return ( const Button = forwardRef<HTMLButtonElement, DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>>(({ type = 'button', ...props }, ref) => (
// eslint-disable-next-line react/jsx-props-no-spreading, react/button-has-type // eslint-disable-next-line react/jsx-props-no-spreading, react/button-has-type
<button className={styles['button']} type={type} {...props} /> <button ref={ref} className={styles['button']} type={type} {...props} />
); ));
}
export default memo(Button); export default Button;