Mount (on startup & fixes)
Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
This commit is contained in:
+75
-62
@@ -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
@@ -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
|
||||
}[]
|
||||
}>
|
||||
)
|
||||
|
||||
|
||||
@@ -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] })),
|
||||
|
||||
@@ -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
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user