lossless-cut/src/hooks/useUserSettingsRoot.ts

274 wiersze
14 KiB
TypeScript
Czysty Zwykły widok Historia

import { useEffect, useState, useRef, useCallback } from 'react';
2021-01-23 18:35:34 +00:00
import i18n from 'i18next';
2024-03-15 13:45:33 +00:00
import { StoreGetConfig, StoreResetConfig, StoreSetConfig, Config } from '../../types';
2021-01-23 18:35:34 +00:00
2023-02-16 05:14:15 +00:00
import { errorToast } from '../swal';
2022-11-22 15:23:41 +00:00
import isDev from '../isDev';
2021-01-23 18:35:34 +00:00
2022-11-22 15:23:41 +00:00
const remote = window.require('@electron/remote');
2021-01-23 18:35:34 +00:00
2024-03-15 13:45:33 +00:00
const configStore: { get: StoreGetConfig, set: StoreSetConfig, reset: StoreResetConfig } = remote.require('./configStore');
2021-01-23 18:35:34 +00:00
export default () => {
const firstUpdateRef = useRef(true);
2024-03-15 13:45:33 +00:00
function safeSetConfig<T extends keyof Config>(keyValue: Record<T, Config[T]>) {
const entry = Object.entries(keyValue)[0]!;
const key = entry[0] as T;
const value = entry[1] as Config[T];
2023-01-06 14:53:19 +00:00
2021-01-23 18:35:34 +00:00
// Prevent flood-saving all config during mount
if (firstUpdateRef.current) return;
2021-04-07 16:34:20 +00:00
if (isDev) console.log('save', key, value);
2021-01-23 18:35:34 +00:00
try {
configStore.set(key, value);
} catch (err) {
console.error('Failed to set config', key, err);
errorToast(i18n.t('Unable to save your preferences. Try to disable any anti-virus'));
}
}
2024-03-15 13:45:33 +00:00
function safeGetConfig<T extends keyof Config>(key: T) {
2022-02-20 09:23:27 +00:00
const rawVal = configStore.get(key);
2024-03-15 13:45:33 +00:00
if (rawVal === undefined) return undefined as typeof rawVal;
2022-02-20 09:23:27 +00:00
// NOTE: Need to clone any non-primitive in renderer, or it will become very slow
// I think because Electron is proxying objects over the bridge
2024-03-15 13:45:33 +00:00
const cloned: typeof rawVal = JSON.parse(JSON.stringify(rawVal));
return cloned;
2022-02-20 09:23:27 +00:00
}
2022-07-20 14:40:44 +00:00
// From https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
// If the initial state is the result of an expensive computation, you may provide a function instead, which will be executed only on the initial render
// Without this there was a huge performance issue https://github.com/mifi/lossless-cut/issues/1097
2024-03-15 13:45:33 +00:00
const safeGetConfigInitial = <T extends keyof Config>(key: T) => () => safeGetConfig(key);
2022-07-20 14:40:44 +00:00
const [captureFormat, setCaptureFormat] = useState(safeGetConfigInitial('captureFormat'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ captureFormat }), [captureFormat]);
2022-07-20 14:40:44 +00:00
const [customOutDir, setCustomOutDir] = useState(safeGetConfigInitial('customOutDir'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ customOutDir }), [customOutDir]);
2022-07-20 14:40:44 +00:00
const [keyframeCut, setKeyframeCut] = useState(safeGetConfigInitial('keyframeCut'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ keyframeCut }), [keyframeCut]);
2022-07-20 14:40:44 +00:00
const [preserveMovData, setPreserveMovData] = useState(safeGetConfigInitial('preserveMovData'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ preserveMovData }), [preserveMovData]);
2022-07-20 14:40:44 +00:00
const [movFastStart, setMovFastStart] = useState(safeGetConfigInitial('movFastStart'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ movFastStart }), [movFastStart]);
2022-07-20 14:40:44 +00:00
const [avoidNegativeTs, setAvoidNegativeTs] = useState(safeGetConfigInitial('avoidNegativeTs'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ avoidNegativeTs }), [avoidNegativeTs]);
2022-07-20 14:40:44 +00:00
const [autoMerge, setAutoMerge] = useState(safeGetConfigInitial('autoMerge'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ autoMerge }), [autoMerge]);
2022-07-20 14:40:44 +00:00
const [timecodeFormat, setTimecodeFormat] = useState(safeGetConfigInitial('timecodeFormat'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ timecodeFormat }), [timecodeFormat]);
2022-07-20 14:40:44 +00:00
const [invertCutSegments, setInvertCutSegments] = useState(safeGetConfigInitial('invertCutSegments'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ invertCutSegments }), [invertCutSegments]);
2022-07-20 14:40:44 +00:00
const [autoExportExtraStreams, setAutoExportExtraStreams] = useState(safeGetConfigInitial('autoExportExtraStreams'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ autoExportExtraStreams }), [autoExportExtraStreams]);
2022-07-20 14:40:44 +00:00
const [askBeforeClose, setAskBeforeClose] = useState(safeGetConfigInitial('askBeforeClose'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ askBeforeClose }), [askBeforeClose]);
2022-07-20 14:40:44 +00:00
const [enableAskForImportChapters, setEnableAskForImportChapters] = useState(safeGetConfigInitial('enableAskForImportChapters'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ enableAskForImportChapters }), [enableAskForImportChapters]);
2022-07-20 14:40:44 +00:00
const [enableAskForFileOpenAction, setEnableAskForFileOpenAction] = useState(safeGetConfigInitial('enableAskForFileOpenAction'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ enableAskForFileOpenAction }), [enableAskForFileOpenAction]);
2022-07-20 14:40:44 +00:00
const [playbackVolume, setPlaybackVolume] = useState(safeGetConfigInitial('playbackVolume'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ playbackVolume }), [playbackVolume]);
2022-07-20 14:40:44 +00:00
const [autoSaveProjectFile, setAutoSaveProjectFile] = useState(safeGetConfigInitial('autoSaveProjectFile'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ autoSaveProjectFile }), [autoSaveProjectFile]);
2022-07-20 14:40:44 +00:00
const [wheelSensitivity, setWheelSensitivity] = useState(safeGetConfigInitial('wheelSensitivity'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ wheelSensitivity }), [wheelSensitivity]);
2022-07-20 14:40:44 +00:00
const [invertTimelineScroll, setInvertTimelineScroll] = useState(safeGetConfigInitial('invertTimelineScroll'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ invertTimelineScroll }), [invertTimelineScroll]);
2022-07-20 14:40:44 +00:00
const [language, setLanguage] = useState(safeGetConfigInitial('language'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ language }), [language]);
2022-07-20 14:40:44 +00:00
const [ffmpegExperimental, setFfmpegExperimental] = useState(safeGetConfigInitial('ffmpegExperimental'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ ffmpegExperimental }), [ffmpegExperimental]);
2022-07-20 14:40:44 +00:00
const [hideNotifications, setHideNotifications] = useState(safeGetConfigInitial('hideNotifications'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ hideNotifications }), [hideNotifications]);
2022-07-20 14:40:44 +00:00
const [autoLoadTimecode, setAutoLoadTimecode] = useState(safeGetConfigInitial('autoLoadTimecode'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ autoLoadTimecode }), [autoLoadTimecode]);
2022-07-20 14:40:44 +00:00
const [autoDeleteMergedSegments, setAutoDeleteMergedSegments] = useState(safeGetConfigInitial('autoDeleteMergedSegments'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ autoDeleteMergedSegments }), [autoDeleteMergedSegments]);
2022-07-20 14:40:44 +00:00
const [exportConfirmEnabled, setExportConfirmEnabled] = useState(safeGetConfigInitial('exportConfirmEnabled'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ exportConfirmEnabled }), [exportConfirmEnabled]);
2022-07-20 14:40:44 +00:00
const [segmentsToChapters, setSegmentsToChapters] = useState(safeGetConfigInitial('segmentsToChapters'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ segmentsToChapters }), [segmentsToChapters]);
2022-07-20 14:40:44 +00:00
const [preserveMetadataOnMerge, setPreserveMetadataOnMerge] = useState(safeGetConfigInitial('preserveMetadataOnMerge'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ preserveMetadataOnMerge }), [preserveMetadataOnMerge]);
2022-07-20 14:40:44 +00:00
const [simpleMode, setSimpleMode] = useState(safeGetConfigInitial('simpleMode'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ simpleMode }), [simpleMode]);
2022-07-20 14:40:44 +00:00
const [outSegTemplate, setOutSegTemplate] = useState(safeGetConfigInitial('outSegTemplate'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ outSegTemplate }), [outSegTemplate]);
2022-07-20 14:40:44 +00:00
const [keyboardSeekAccFactor, setKeyboardSeekAccFactor] = useState(safeGetConfigInitial('keyboardSeekAccFactor'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ keyboardSeekAccFactor }), [keyboardSeekAccFactor]);
2022-07-20 14:40:44 +00:00
const [keyboardNormalSeekSpeed, setKeyboardNormalSeekSpeed] = useState(safeGetConfigInitial('keyboardNormalSeekSpeed'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ keyboardNormalSeekSpeed }), [keyboardNormalSeekSpeed]);
const [treatInputFileModifiedTimeAsStart, setTreatInputFileModifiedTimeAsStart] = useState(safeGetConfigInitial('treatInputFileModifiedTimeAsStart'));
useEffect(() => safeSetConfig({ treatInputFileModifiedTimeAsStart }), [treatInputFileModifiedTimeAsStart]);
const [treatOutputFileModifiedTimeAsStart, setTreatOutputFileModifiedTimeAsStart] = useState(safeGetConfigInitial('treatOutputFileModifiedTimeAsStart'));
useEffect(() => safeSetConfig({ treatOutputFileModifiedTimeAsStart }), [treatOutputFileModifiedTimeAsStart]);
2022-07-20 14:40:44 +00:00
const [outFormatLocked, setOutFormatLocked] = useState(safeGetConfigInitial('outFormatLocked'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ outFormatLocked }), [outFormatLocked]);
2022-07-20 14:40:44 +00:00
const [safeOutputFileName, setSafeOutputFileName] = useState(safeGetConfigInitial('safeOutputFileName'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ safeOutputFileName }), [safeOutputFileName]);
2022-07-20 14:40:44 +00:00
const [enableAutoHtml5ify, setEnableAutoHtml5ify] = useState(safeGetConfigInitial('enableAutoHtml5ify'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ enableAutoHtml5ify }), [enableAutoHtml5ify]);
2022-07-20 14:40:44 +00:00
const [segmentsToChaptersOnly, setSegmentsToChaptersOnly] = useState(safeGetConfigInitial('segmentsToChaptersOnly'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ segmentsToChaptersOnly }), [segmentsToChaptersOnly]);
2022-07-20 14:40:44 +00:00
const [keyBindings, setKeyBindings] = useState(safeGetConfigInitial('keyBindings'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ keyBindings }), [keyBindings]);
2022-07-20 14:40:44 +00:00
const [enableSmartCut, setEnableSmartCut] = useState(safeGetConfigInitial('enableSmartCut'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ enableSmartCut }), [enableSmartCut]);
2022-07-20 14:40:44 +00:00
const [customFfPath, setCustomFfPath] = useState(safeGetConfigInitial('customFfPath'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ customFfPath }), [customFfPath]);
2022-07-20 14:40:44 +00:00
const [storeProjectInWorkingDir, setStoreProjectInWorkingDir] = useState(safeGetConfigInitial('storeProjectInWorkingDir'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ storeProjectInWorkingDir }), [storeProjectInWorkingDir]);
const [enableOverwriteOutput, setEnableOverwriteOutput] = useState(safeGetConfigInitial('enableOverwriteOutput'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ enableOverwriteOutput }), [enableOverwriteOutput]);
const [mouseWheelZoomModifierKey, setMouseWheelZoomModifierKey] = useState(safeGetConfigInitial('mouseWheelZoomModifierKey'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ mouseWheelZoomModifierKey }), [mouseWheelZoomModifierKey]);
const [captureFrameMethod, setCaptureFrameMethod] = useState(safeGetConfigInitial('captureFrameMethod'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ captureFrameMethod }), [captureFrameMethod]);
const [captureFrameQuality, setCaptureFrameQuality] = useState(safeGetConfigInitial('captureFrameQuality'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ captureFrameQuality }), [captureFrameQuality]);
const [captureFrameFileNameFormat, setCaptureFrameFileNameFormat] = useState(safeGetConfigInitial('captureFrameFileNameFormat'));
2023-01-06 14:53:19 +00:00
useEffect(() => safeSetConfig({ captureFrameFileNameFormat }), [captureFrameFileNameFormat]);
2023-01-15 09:27:45 +00:00
const [enableNativeHevc, setEnableNativeHevc] = useState(safeGetConfigInitial('enableNativeHevc'));
useEffect(() => safeSetConfig({ enableNativeHevc }), [enableNativeHevc]);
const [enableUpdateCheck, setEnableUpdateCheck] = useState(safeGetConfigInitial('enableUpdateCheck'));
useEffect(() => safeSetConfig({ enableUpdateCheck }), [enableUpdateCheck]);
2023-02-16 10:47:49 +00:00
const [cleanupChoices, setCleanupChoices] = useState(safeGetConfigInitial('cleanupChoices'));
useEffect(() => safeSetConfig({ cleanupChoices }), [cleanupChoices]);
const [allowMultipleInstances, setAllowMultipleInstances] = useState(safeGetConfigInitial('allowMultipleInstances'));
useEffect(() => safeSetConfig({ allowMultipleInstances }), [allowMultipleInstances]);
const [darkMode, setDarkMode] = useState(safeGetConfigInitial('darkMode'));
useEffect(() => safeSetConfig({ darkMode }), [darkMode]);
const [preferStrongColors, setPreferStrongColors] = useState(safeGetConfigInitial('preferStrongColors'));
useEffect(() => safeSetConfig({ preferStrongColors }), [preferStrongColors]);
2023-08-27 20:07:30 +00:00
const [outputFileNameMinZeroPadding, setOutputFileNameMinZeroPadding] = useState(safeGetConfigInitial('outputFileNameMinZeroPadding'));
useEffect(() => safeSetConfig({ outputFileNameMinZeroPadding }), [outputFileNameMinZeroPadding]);
const [cutFromAdjustmentFrames, setCutFromAdjustmentFrames] = useState(safeGetConfigInitial('cutFromAdjustmentFrames'));
useEffect(() => safeSetConfig({ cutFromAdjustmentFrames }), [cutFromAdjustmentFrames]);
const resetKeyBindings = useCallback(() => {
configStore.reset('keyBindings');
setKeyBindings(safeGetConfig('keyBindings'));
}, []);
2021-01-23 18:35:34 +00:00
// NOTE! This useEffect must be placed after all usages of firstUpdateRef.current (safeSetConfig)
useEffect(() => {
firstUpdateRef.current = false;
2021-04-07 16:33:54 +00:00
return () => {
firstUpdateRef.current = true;
};
2021-01-23 18:35:34 +00:00
}, []);
return {
captureFormat,
setCaptureFormat,
customOutDir,
setCustomOutDir,
keyframeCut,
setKeyframeCut,
preserveMovData,
setPreserveMovData,
movFastStart,
setMovFastStart,
avoidNegativeTs,
setAvoidNegativeTs,
autoMerge,
setAutoMerge,
timecodeFormat,
setTimecodeFormat,
2021-01-23 18:35:34 +00:00
invertCutSegments,
setInvertCutSegments,
autoExportExtraStreams,
setAutoExportExtraStreams,
askBeforeClose,
setAskBeforeClose,
enableAskForImportChapters,
setEnableAskForImportChapters,
enableAskForFileOpenAction,
setEnableAskForFileOpenAction,
playbackVolume,
setPlaybackVolume,
2021-01-23 18:35:34 +00:00
autoSaveProjectFile,
setAutoSaveProjectFile,
wheelSensitivity,
setWheelSensitivity,
invertTimelineScroll,
setInvertTimelineScroll,
language,
setLanguage,
ffmpegExperimental,
setFfmpegExperimental,
hideNotifications,
setHideNotifications,
autoLoadTimecode,
setAutoLoadTimecode,
autoDeleteMergedSegments,
setAutoDeleteMergedSegments,
exportConfirmEnabled,
setExportConfirmEnabled,
segmentsToChapters,
setSegmentsToChapters,
preserveMetadataOnMerge,
setPreserveMetadataOnMerge,
simpleMode,
setSimpleMode,
outSegTemplate,
setOutSegTemplate,
2021-01-23 20:58:04 +00:00
keyboardSeekAccFactor,
setKeyboardSeekAccFactor,
2021-01-23 21:45:59 +00:00
keyboardNormalSeekSpeed,
setKeyboardNormalSeekSpeed,
treatInputFileModifiedTimeAsStart,
setTreatInputFileModifiedTimeAsStart,
treatOutputFileModifiedTimeAsStart,
setTreatOutputFileModifiedTimeAsStart,
2021-04-07 16:33:54 +00:00
outFormatLocked,
setOutFormatLocked,
safeOutputFileName,
setSafeOutputFileName,
enableAutoHtml5ify,
setEnableAutoHtml5ify,
segmentsToChaptersOnly,
setSegmentsToChaptersOnly,
keyBindings,
setKeyBindings,
resetKeyBindings,
enableSmartCut,
setEnableSmartCut,
customFfPath,
setCustomFfPath,
storeProjectInWorkingDir,
setStoreProjectInWorkingDir,
enableOverwriteOutput,
setEnableOverwriteOutput,
mouseWheelZoomModifierKey,
setMouseWheelZoomModifierKey,
captureFrameMethod,
setCaptureFrameMethod,
captureFrameQuality,
setCaptureFrameQuality,
captureFrameFileNameFormat,
setCaptureFrameFileNameFormat,
2023-01-15 09:27:45 +00:00
enableNativeHevc,
setEnableNativeHevc,
enableUpdateCheck,
setEnableUpdateCheck,
2023-02-16 10:47:49 +00:00
cleanupChoices,
setCleanupChoices,
allowMultipleInstances,
setAllowMultipleInstances,
darkMode,
setDarkMode,
preferStrongColors,
setPreferStrongColors,
2023-08-27 20:07:30 +00:00
outputFileNameMinZeroPadding,
setOutputFileNameMinZeroPadding,
cutFromAdjustmentFrames,
setCutFromAdjustmentFrames,
2021-01-23 18:35:34 +00:00
};
};