diff --git a/lib/rclone/common.ts b/lib/rclone/common.ts index bac0a52..fd33384 100644 --- a/lib/rclone/common.ts +++ b/lib/rclone/common.ts @@ -151,18 +151,5 @@ export async function isInternalRcloneInstalled() { export function parseRcloneOptions(options: Record) { console.log('[parseRcloneOptions]', options) - const parsedOptions: Record = {} - for (const [key, value] of Object.entries(options)) { - if (value === 'true') { - parsedOptions[key] = true - } else if (value === 'false') { - parsedOptions[key] = false - } else { - parsedOptions[key] = value - } - } - - console.log('[parseRcloneOptions] parsedOptions', parsedOptions) - - return parsedOptions + return options } diff --git a/lib/rclone/constants.ts b/lib/rclone/constants.ts index f56a60c..15bf8bf 100644 --- a/lib/rclone/constants.ts +++ b/lib/rclone/constants.ts @@ -1,15 +1,15 @@ export const RCLONE_CONFIG_DEFAULTS = { 'MultiThreadCutoff': '64M', - 'MultiThreadStreams': '8M', + 'MultiThreadStreams': 8, 'MultiThreadChunkSize': '8M', - 'UseListR': 'true', - 'UseServerModTime': 'true', + 'UseListR': true, + 'UseServerModTime': true, 'BufferSize': '32M', - 'Transfers': '8', - 'Checkers': '16', + 'Transfers': 8, + 'Checkers': 16, } export const RCLONE_VFS_DEFAULTS = { 'ChunkSize': '4M', - 'ChunkStreams': '16', + 'ChunkStreams': 16, } diff --git a/src/components/OptionsSection.tsx b/src/components/OptionsSection.tsx index 3d29064..2a43aa8 100644 --- a/src/components/OptionsSection.tsx +++ b/src/components/OptionsSection.tsx @@ -25,12 +25,9 @@ export default function OptionsSection({ const [options, setOptions] = useState({}) const [isJsonValid, setIsJsonValid] = useState(true) - console.log('[OptionsSection] globalOptions', globalOptions) - useEffect(() => { getAvailableOptions() .then((flags) => { - console.log(JSON.stringify(flags, null, 2)) return flags }) .then((flags) => setAvailableOptions(flags)) @@ -149,25 +146,48 @@ export default function OptionsSection({ const newOptions = { ...options, } - delete newOptions[option.FieldName] + // delete newOptions[option.FieldName] + newOptions[option.FieldName] = undefined setOptionsJson(JSON.stringify(newOptions, null, 2)) return } + let value: string | number | boolean = '' + const defaultGlobalValue = globalOptions[ option.FieldName as keyof typeof globalOptions ] - const defaultValue = + if ( + defaultGlobalValue !== null && + defaultGlobalValue !== undefined + ) { + value = defaultGlobalValue + } else { + value = availableOptions.find( + (o) => o.FieldName === option.FieldName + )?.DefaultStr + } + + const valueType = availableOptions.find( (o) => o.FieldName === option.FieldName - )?.DefaultStr || '' + )?.Type || 'string' + + if (valueType === 'bool') { + value = Boolean(value || false) + } else if ( + valueType.includes('int') || + valueType.includes('float') + ) { + value = Number(value || 0) + } const newOptions = { ...options, - [option.FieldName]: defaultGlobalValue || defaultValue, + [option.FieldName]: value, } setOptionsJson(JSON.stringify(newOptions, null, 2)) diff --git a/src/pages/Copy.tsx b/src/pages/Copy.tsx index 39807ab..185a6db 100644 --- a/src/pages/Copy.tsx +++ b/src/pages/Copy.tsx @@ -89,9 +89,9 @@ export default function Copy() { // Helper function to merge defaults from a remote const mergeRemoteDefaults = (remote: string | null) => { - if (!remote || !(remote in storeData.remoteConfigList)) return + if (!remote) return - const remoteConfig = storeData.remoteConfigList[remote] + const remoteConfig = storeData.remoteConfigList?.[remote] || {} if (remoteConfig.copyDefaults) { mergedCopyDefaults = { @@ -155,6 +155,23 @@ export default function Copy() { } }, [copyOptionsJson, filterOptionsJson, configOptionsJson]) + const buttonText = useMemo(() => { + if (isLoading) return 'STARTING...' + if (!sources || sources.length === 0) return 'Please select a source path' + if (!dest) return 'Please select a destination path' + if (sources[0] === dest) return 'Source and destination cannot be the same' + if (jsonError) return 'Invalid JSON for ' + jsonError.toUpperCase() + ' options' + return 'START COPY' + }, [isLoading, jsonError, sources, dest]) + + const buttonIcon = useMemo(() => { + if (isLoading) return + if (!sources || sources.length === 0 || !dest || sources[0] === dest) + return + if (jsonError) return + return + }, [isLoading, jsonError, sources, dest]) + const handleStartCopy = useCallback(async () => { setIsLoading(true) @@ -346,23 +363,6 @@ export default function Copy() { setIsLoading(false) }, [sources, dest, copyOptions, filterOptions, cronExpression, configOptions]) - const buttonText = useMemo(() => { - if (isLoading) return 'STARTING...' - if (!sources || sources.length === 0) return 'Please select a source path' - if (!dest) return 'Please select a destination path' - if (sources[0] === dest) return 'Source and destination cannot be the same' - if (jsonError) return 'Invalid JSON for ' + jsonError.toUpperCase() + ' options' - return 'START COPY' - }, [isLoading, jsonError, sources, dest]) - - const buttonIcon = useMemo(() => { - if (isLoading) return - if (!sources || sources.length === 0 || !dest || sources[0] === dest) - return - if (jsonError) return - return - }, [isLoading, jsonError, sources, dest]) - return (
{/* Main Content */} diff --git a/src/pages/Delete.tsx b/src/pages/Delete.tsx index d096718..ce580f6 100644 --- a/src/pages/Delete.tsx +++ b/src/pages/Delete.tsx @@ -60,9 +60,9 @@ export default function Delete() { // Helper function to merge defaults from a remote const mergeRemoteDefaults = (remote: string | null) => { - if (!remote || !(remote in storeData.remoteConfigList)) return + if (!remote) return - const remoteConfig = storeData.remoteConfigList[remote] + const remoteConfig = storeData.remoteConfigList?.[remote] || {} if (remoteConfig.filterDefaults) { mergedFilterDefaults = { diff --git a/src/pages/Mount.tsx b/src/pages/Mount.tsx index 395df02..bffa8d4 100644 --- a/src/pages/Mount.tsx +++ b/src/pages/Mount.tsx @@ -1,5 +1,4 @@ import { Accordion, AccordionItem, Avatar, Button } from '@heroui/react' -import { sep } from '@tauri-apps/api/path' import { getCurrentWindow } from '@tauri-apps/api/window' import { message } from '@tauri-apps/plugin-dialog' import { exists, mkdir, remove } from '@tauri-apps/plugin-fs' @@ -29,6 +28,7 @@ import { RCLONE_CONFIG_DEFAULTS, RCLONE_VFS_DEFAULTS } from '../../lib/rclone/co import { dialogGetMountPlugin } from '../../lib/rclone/mount' import { needsMountPlugin } from '../../lib/rclone/mount' import { usePersistedStore } from '../../lib/store' +import { triggerTrayRebuild } from '../../lib/tray' import OptionsSection from '../components/OptionsSection' import { PathFinder } from '../components/PathFinder' @@ -70,11 +70,9 @@ export default function Mount() { if (!remote) return - if (!(remote in storeData.remoteConfigList)) return - if ( - storeData.remoteConfigList[remote].mountDefaults && - Object.keys(storeData.remoteConfigList[remote].mountDefaults).length > 0 && + storeData.remoteConfigList?.[remote]?.mountDefaults && + Object.keys(storeData.remoteConfigList?.[remote]?.mountDefaults).length > 0 && !mountOptionsLocked ) { setMountOptionsJson( @@ -84,8 +82,8 @@ export default function Mount() { if (!vfsOptionsLocked) { if ( - storeData.remoteConfigList[remote].vfsDefaults && - Object.keys(storeData.remoteConfigList[remote].vfsDefaults).length > 0 + storeData.remoteConfigList?.[remote]?.vfsDefaults && + Object.keys(storeData.remoteConfigList?.[remote]?.vfsDefaults).length > 0 ) { setVfsOptionsJson( JSON.stringify(storeData.remoteConfigList[remote].vfsDefaults, null, 2) @@ -96,8 +94,8 @@ export default function Mount() { } if ( - storeData.remoteConfigList[remote].filterDefaults && - Object.keys(storeData.remoteConfigList[remote].filterDefaults).length > 0 && + storeData.remoteConfigList?.[remote]?.filterDefaults && + Object.keys(storeData.remoteConfigList?.[remote]?.filterDefaults).length > 0 && !filterOptionsLocked ) { setFilterOptionsJson( @@ -107,8 +105,8 @@ export default function Mount() { if (!configOptionsLocked) { if ( - storeData.remoteConfigList[remote].configDefaults && - Object.keys(storeData.remoteConfigList[remote].configDefaults).length > 0 + storeData.remoteConfigList?.[remote]?.configDefaults && + Object.keys(storeData.remoteConfigList?.[remote]?.configDefaults).length > 0 ) { setConfigOptionsJson( JSON.stringify(storeData.remoteConfigList[remote].configDefaults, null, 2) @@ -164,7 +162,14 @@ export default function Mount() { (!('VolumeName' in _mountOptions) || !_mountOptions.VolumeName) && ['windows', 'macos'].includes(platform()) ) { - _mountOptions.VolumeName = `${source.split(sep()).pop()}-${Math.random().toString(36).substring(2, 3).toUpperCase()}` + const segments = source.split('/').filter(Boolean) + console.log('[Mount] segments', segments) + + const sourcePath = + segments.length === 1 ? segments[0].replace(/:/g, '') : segments.pop() + console.log('[Mount] sourcePath', sourcePath) + + _mountOptions.VolumeName = `${sourcePath}-${Math.random().toString(36).substring(2, 3).toUpperCase()}` } let directoryExists: boolean | undefined diff --git a/src/pages/Move.tsx b/src/pages/Move.tsx index 0b28fc2..258ccf1 100644 --- a/src/pages/Move.tsx +++ b/src/pages/Move.tsx @@ -77,9 +77,9 @@ export default function Move() { // Helper function to merge defaults from a remote const mergeRemoteDefaults = (remote: string | null) => { - if (!remote || !(remote in storeData.remoteConfigList)) return + if (!remote) return - const remoteConfig = storeData.remoteConfigList[remote] + const remoteConfig = storeData.remoteConfigList?.[remote] || {} if (remoteConfig.moveDefaults) { mergedMoveDefaults = { diff --git a/src/pages/Sync.tsx b/src/pages/Sync.tsx index 8fe32e0..56700ac 100644 --- a/src/pages/Sync.tsx +++ b/src/pages/Sync.tsx @@ -82,9 +82,9 @@ export default function Sync() { // Helper function to merge defaults from a remote const mergeRemoteDefaults = (remote: string | null) => { - if (!remote || !(remote in storeData.remoteConfigList)) return + if (!remote) return - const remoteConfig = storeData.remoteConfigList[remote] + const remoteConfig = storeData.remoteConfigList?.[remote] || {} if (remoteConfig.syncDefaults) { mergedSyncDefaults = {