Mount (on startup & fixes)

Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
This commit is contained in:
FTCHD
2025-09-12 18:55:16 +02:00
parent 122527ae8a
commit 67be5965c4
5 changed files with 94 additions and 75 deletions
+75 -62
View File
@@ -8,21 +8,25 @@ import { platform } from '@tauri-apps/plugin-os'
import { exit } from '@tauri-apps/plugin-process'
import { isDirectoryEmpty } from './fs'
import notify from './notify'
import { cleanupRemote, deleteRemote, mountRemote, unmountRemote } from './rclone/api'
import { cleanupRemote, deleteRemote, listMounts, mountRemote, unmountRemote } from './rclone/api'
import { dialogGetMountPlugin, needsMountPlugin } from './rclone/mount'
import { usePersistedStore, useStore } from './store'
import { getLoadingTray, getMainTray, rebuildTrayMenu } from './tray'
import { lockWindows, openFullWindow, openWindow, unlockWindows } from './window'
async function parseRemotes(remotes: string[]) {
console.log('[parseRemotes]')
console.log('[parseRemotes] remotes', remotes)
const storeState = useStore.getState()
const persistedStoreState = usePersistedStore.getState()
console.log('[parseRemotes] listing mounts')
const currentMounts = await listMounts()
console.log('[parseRemotes] currentMounts', currentMounts)
const parsedRemotes: Record<string, (MenuItem | Submenu | PredefinedMenuItem)[]> = {}
for (const remote of remotes) {
console.log('[parseRemotes] remote', remote)
const remoteConfig = persistedStoreState.remoteConfigList?.[remote]
if (remoteConfig?.disabledActions?.includes('tray')) {
continue
@@ -30,64 +34,7 @@ async function parseRemotes(remotes: string[]) {
const submenuItems: (MenuItem | Submenu | PredefinedMenuItem)[] = []
const alreadyMounted = storeState.mountedRemotes[remote]
if (alreadyMounted) {
const unmountMenuItem = await MenuItem.new({
id: `unmount-${remote}`,
text: 'Unmount',
action: async () => {
try {
const mountPoint = storeState.mountedRemotes[remote]
if (!mountPoint) {
console.error(`No mount point found for remote ${remote}`)
return
}
await unmountRemote({ mountPoint })
delete storeState.mountedRemotes[remote]
await rebuildTrayMenu()
await message(`Successfully unmounted ${remote} from ${mountPoint}`, {
title: 'Success',
})
} catch (error) {
Sentry.captureException(error)
console.error('Unmount operation failed:', error)
await message(`Failed to unmount ${remote}: ${error}`, {
kind: 'error',
title: 'Unmount Error',
})
}
},
})
submenuItems.push(unmountMenuItem)
// Add "Show Location" option for mounted remotes
const mountPoint = storeState.mountedRemotes[remote]
console.log('Adding Show Location', mountPoint)
const showLocationItem = await MenuItem.new({
id: `open-${remote}`,
text: 'Show Location',
action: async () => {
console.log('Show Location', mountPoint)
if (mountPoint) {
try {
await openPath(mountPoint)
} catch (error) {
Sentry.captureException(error)
console.error('Error opening path:', error)
await message(`Failed to open ${mountPoint} (${error})`, {
title: 'Open Error',
kind: 'error',
})
}
}
},
})
submenuItems.push(showLocationItem)
}
if (!alreadyMounted && !remoteConfig?.disabledActions?.includes('tray-mount')) {
if (!remoteConfig?.disabledActions?.includes('tray-mount')) {
const mountMenuItem = await MenuItem.new({
id: `mount-${remote}`,
text: 'Quick Mount',
@@ -180,7 +127,6 @@ async function parseRemotes(remotes: string[]) {
mountOptions: remoteConfig?.mountDefaults,
vfsOptions: remoteConfig?.vfsDefaults,
})
storeState.mountedRemotes[remote] = selectedPath
await notify({
title: 'Mounted',
@@ -299,6 +245,73 @@ async function parseRemotes(remotes: string[]) {
submenuItems.push(removeMenuItem)
}
const currentRemoteMounts = currentMounts.filter(
(mount) => mount.Fs.split(':')[0] === remote
)
console.log('[parseRemotes] currentRemoteMounts', currentRemoteMounts)
for (const currentMount of currentRemoteMounts) {
console.log(
'[parseRemotes] Adding Unmount (' +
currentMount.MountPoint.split('/').pop() +
') for ',
remote
)
const unmountMenuItem = await MenuItem.new({
id: `unmount-${remote}-${currentMount.MountPoint}`,
text: 'Unmount (' + currentMount.MountPoint.split('/').pop() + ')',
action: async () => {
try {
await unmountRemote({ mountPoint: currentMount.MountPoint })
await rebuildTrayMenu()
await message(
`Successfully unmounted ${remote} from ${currentMount.MountPoint.split('/').pop()}`,
{
title: 'Success',
}
)
} catch (error) {
Sentry.captureException(error)
console.error('Unmount operation failed:', error)
await message(`Failed to unmount ${remote}: ${error}`, {
kind: 'error',
title: 'Unmount Error',
})
}
},
})
submenuItems.push(unmountMenuItem)
console.log(
'[parseRemotes] Adding Open (' +
currentMount.MountPoint.split('/').pop() +
') for ',
remote
)
const showLocationItem = await MenuItem.new({
id: `open-${remote}-${currentMount.MountPoint}`,
text: 'Open (' + currentMount.MountPoint.split('/').pop() + ')',
action: async () => {
console.log(
'[parseRemotes] Opening (' + currentMount.MountPoint.split('/').pop() + ')'
)
try {
await openPath(currentMount.MountPoint)
} catch (error) {
Sentry.captureException(error)
console.error('Error opening path:', error)
await message(`Failed to open ${currentMount.MountPoint} (${error})`, {
title: 'Open Error',
kind: 'error',
})
}
},
})
submenuItems.push(showLocationItem)
}
parsedRemotes[remote] = submenuItems
}
+7 -3
View File
@@ -170,8 +170,8 @@ export async function cleanupRemote(remote: string) {
// console.log(JSON.stringify(r, null, 2))
}
export async function getMountPoints() {
console.log('[getMountPoints]')
export async function listMounts() {
console.log('[listMounts]')
const r = await fetch('http://localhost:5572/mount/listmounts', {
method: 'POST',
@@ -179,7 +179,11 @@ export async function getMountPoints() {
}).then(
(res) =>
res.json() as Promise<{
mountPoints: string[]
mountPoints: {
Fs: string
MountPoint: string
MountedOn: string
}[]
}>
)
-4
View File
@@ -32,8 +32,6 @@ interface State {
rcloneAuth: string
rcloneAuthHeader: string
mountedRemotes: Record<string, string>
serveList: { pid: number; protocol: string; remote: string }[]
setServeList: (serve: { pid: number; protocol: string; remote: string }) => void
removeServeList: (pid: number) => void
@@ -126,8 +124,6 @@ export const useStore = create<State>()(
rcloneAuth: '',
rcloneAuthHeader: '',
mountedRemotes: {},
serveList: [],
setServeList: (serve: { pid: number; protocol: string; remote: string }) =>
set((state) => ({ serveList: [...state.serveList, serve] })),
+9 -5
View File
@@ -8,6 +8,7 @@ import { exit, relaunch } from '@tauri-apps/plugin-process'
import { check } from '@tauri-apps/plugin-updater'
import { CronExpressionParser } from 'cron-parser'
import { defaultOptions } from 'tauri-plugin-sentry-api'
import { isDirectoryEmpty } from './lib/fs'
import { validateLicense } from './lib/license'
import notify from './lib/notify'
import {
@@ -221,15 +222,18 @@ async function startRclone() {
async function startupMounts() {
const remoteConfigList = usePersistedStore.getState().remoteConfigList
const remotes = useStore.getState().remotes
if (!remoteConfigList) {
return
}
for (const remote in remoteConfigList) {
for (const remote in remotes) {
const remoteConfig = remoteConfigList[remote]
if (!remoteConfig) continue
if (remoteConfig.mountOnStart && remoteConfig.defaultMountPoint) {
try {
const isEmpty = await isDirectoryEmpty(remoteConfig.defaultMountPoint)
if (!isEmpty) {
continue
}
await mountRemote({
remotePath: `${remote}:${remoteConfig?.defaultRemotePath || ''}`,
mountPoint: remoteConfig.defaultMountPoint,
+3 -1
View File
@@ -164,7 +164,7 @@ 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()}`
_mountOptions.VolumeName = `${source.split(sep()).pop()}-${Math.random().toString(36).substring(2, 3).toUpperCase()}`
}
let directoryExists: boolean | undefined
@@ -220,6 +220,8 @@ export default function Mount() {
})
setIsMounted(true)
await triggerTrayRebuild()
} catch (err) {
console.error('[Mount] Failed to start mount:', err)
const errorMessage =