menu icons
Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com>
@@ -1,6 +1,6 @@
|
||||
import * as Sentry from '@sentry/browser'
|
||||
import { Menu, MenuItem, PredefinedMenuItem, Submenu } from '@tauri-apps/api/menu'
|
||||
import { sep } from '@tauri-apps/api/path'
|
||||
import { resolveResource, sep } from '@tauri-apps/api/path'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { ask, message, open } from '@tauri-apps/plugin-dialog'
|
||||
import { exists, mkdir, remove } from '@tauri-apps/plugin-fs'
|
||||
@@ -11,12 +11,14 @@ import notify from './notify'
|
||||
import {
|
||||
cleanupRemote,
|
||||
deleteRemote,
|
||||
getRemote,
|
||||
listMounts,
|
||||
listServes,
|
||||
mountRemote,
|
||||
stopServe,
|
||||
unmountRemote,
|
||||
} from './rclone/api'
|
||||
import { compareVersions, getRcloneVersion } from './rclone/common'
|
||||
import { dialogGetMountPlugin, needsMountPlugin } from './rclone/mount'
|
||||
import { usePersistedStore, useStore } from './store'
|
||||
import { showDefaultTray, showLoadingTray } from './tray'
|
||||
@@ -33,15 +35,22 @@ async function parseRemotes(remotes: string[]) {
|
||||
const currentServes = await listServes()
|
||||
console.log('[parseRemotes] currentServes', currentServes)
|
||||
|
||||
const parsedRemotes: Record<string, (MenuItem | Submenu | PredefinedMenuItem)[]> = {}
|
||||
const parsedRemotes: Record<
|
||||
string,
|
||||
{ icon: string; items: (MenuItem | Submenu | PredefinedMenuItem)[] }
|
||||
> = {}
|
||||
|
||||
for (const remote of remotes) {
|
||||
console.log('[parseRemotes] remote', remote)
|
||||
|
||||
const remoteConfig = persistedStoreState.remoteConfigList?.[remote]
|
||||
if (remoteConfig?.disabledActions?.includes('tray')) {
|
||||
continue
|
||||
}
|
||||
|
||||
const remoteInfo = await getRemote(remote).catch(null)
|
||||
console.log('[parseRemotes] remoteInfo', remoteInfo)
|
||||
|
||||
const submenuItems: (MenuItem | Submenu | PredefinedMenuItem)[] = []
|
||||
|
||||
if (!remoteConfig?.disabledActions?.includes('tray-mount')) {
|
||||
@@ -206,37 +215,42 @@ async function parseRemotes(remotes: string[]) {
|
||||
}
|
||||
|
||||
if (!remoteConfig?.disabledActions?.includes('tray-cleanup')) {
|
||||
const cleanupMenuItem = await MenuItem.new({
|
||||
id: `cleanup-${remote}`,
|
||||
text: 'Cleanup',
|
||||
action: async () => {
|
||||
try {
|
||||
const confirmed = await ask(`Start cleanup on ${remote}?`, {
|
||||
title: `Cleaning up ${remote}`,
|
||||
kind: 'warning',
|
||||
okLabel: 'Start',
|
||||
cancelLabel: 'Cancel',
|
||||
})
|
||||
if (
|
||||
remoteInfo?.provider &&
|
||||
['s3', 'b2', 'box', 'drive', 'onedrive'].includes(remoteInfo.provider)
|
||||
) {
|
||||
const cleanupMenuItem = await MenuItem.new({
|
||||
id: `cleanup-${remote}`,
|
||||
text: 'Cleanup',
|
||||
action: async () => {
|
||||
try {
|
||||
const confirmed = await ask(`Start cleanup on ${remote}?`, {
|
||||
title: `Cleaning up ${remote}`,
|
||||
kind: 'warning',
|
||||
okLabel: 'Start',
|
||||
cancelLabel: 'Cancel',
|
||||
})
|
||||
|
||||
if (!confirmed) {
|
||||
return
|
||||
if (!confirmed) {
|
||||
return
|
||||
}
|
||||
|
||||
await cleanupRemote(remote)
|
||||
await message(`Cleanup started for ${remote}`, {
|
||||
title: 'Cleanup Started',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
} catch (error) {
|
||||
await message(`Failed to start cleanup job, ${error}`, {
|
||||
title: 'Cleanup Error',
|
||||
kind: 'error',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
}
|
||||
|
||||
await cleanupRemote(remote)
|
||||
await message(`Cleanup started for ${remote}`, {
|
||||
title: 'Cleanup Started',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
} catch (error) {
|
||||
await message(`Failed to start cleanup job, ${error}`, {
|
||||
title: 'Cleanup Error',
|
||||
kind: 'error',
|
||||
okLabel: 'OK',
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
submenuItems.push(cleanupMenuItem)
|
||||
},
|
||||
})
|
||||
submenuItems.push(cleanupMenuItem)
|
||||
}
|
||||
}
|
||||
|
||||
if (!remoteConfig?.disabledActions?.includes('tray-remove')) {
|
||||
@@ -358,7 +372,12 @@ async function parseRemotes(remotes: string[]) {
|
||||
submenuItems.push(stopServeMenuItem)
|
||||
}
|
||||
|
||||
parsedRemotes[remote] = submenuItems
|
||||
parsedRemotes[remote] = {
|
||||
icon: remoteInfo?.provider
|
||||
? await resolveResource(`icons/small/providers/${remoteInfo.provider}.png`)
|
||||
: await resolveResource(`icons/small/backends/${remoteInfo?.type}.png`),
|
||||
items: submenuItems,
|
||||
}
|
||||
}
|
||||
|
||||
return parsedRemotes
|
||||
@@ -383,13 +402,14 @@ export async function buildMenu() {
|
||||
})
|
||||
menuItems.push(noRemotesMenuItem)
|
||||
} else if (remotes.length > 5) {
|
||||
const items = await parseRemotes(remotes)
|
||||
const parsedRemotes = await parseRemotes(remotes)
|
||||
const submenuItems: (MenuItem | Submenu | PredefinedMenuItem)[] = []
|
||||
|
||||
for (const remote in items) {
|
||||
for (const r in parsedRemotes) {
|
||||
const sub = await Submenu.new({
|
||||
items: items[remote],
|
||||
text: remote,
|
||||
items: parsedRemotes[r].items,
|
||||
icon: parsedRemotes[r].icon,
|
||||
text: r,
|
||||
})
|
||||
submenuItems.push(sub)
|
||||
}
|
||||
@@ -401,12 +421,13 @@ export async function buildMenu() {
|
||||
|
||||
menuItems.push(sub)
|
||||
} else {
|
||||
const items = await parseRemotes(remotes)
|
||||
const parsedRemotes = await parseRemotes(remotes)
|
||||
|
||||
for (const remote in items) {
|
||||
for (const r in parsedRemotes) {
|
||||
const sub = await Submenu.new({
|
||||
items: items[remote],
|
||||
text: remote,
|
||||
items: parsedRemotes[r].items,
|
||||
icon: parsedRemotes[r].icon,
|
||||
text: r,
|
||||
})
|
||||
menuItems.push(sub)
|
||||
}
|
||||
@@ -446,20 +467,6 @@ export async function buildMenu() {
|
||||
menuItems.push(copyMenuItem)
|
||||
}
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-move')) {
|
||||
const moveMenuItem = await MenuItem.new({
|
||||
id: 'move',
|
||||
text: 'Move',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Move',
|
||||
url: '/move',
|
||||
})
|
||||
},
|
||||
})
|
||||
menuItems.push(moveMenuItem)
|
||||
}
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-sync')) {
|
||||
const syncMenuItem = await MenuItem.new({
|
||||
id: 'sync',
|
||||
@@ -474,46 +481,82 @@ export async function buildMenu() {
|
||||
menuItems.push(syncMenuItem)
|
||||
}
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-serve')) {
|
||||
const serveToMenuItem = await MenuItem.new({
|
||||
id: 'serve',
|
||||
text: 'Serve',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Serve',
|
||||
url: '/serve',
|
||||
})
|
||||
},
|
||||
})
|
||||
menuItems.push(serveToMenuItem)
|
||||
}
|
||||
const allowsAdditional =
|
||||
!persistedStoreState.disabledActions?.includes('tray-move') ||
|
||||
!persistedStoreState.disabledActions?.includes('tray-serve') ||
|
||||
!persistedStoreState.disabledActions?.includes('tray-purge') ||
|
||||
!persistedStoreState.disabledActions?.includes('tray-delete')
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-purge')) {
|
||||
const purgeMenuItem = await MenuItem.new({
|
||||
id: 'purge',
|
||||
text: 'Purge',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Purge',
|
||||
url: '/purge',
|
||||
})
|
||||
},
|
||||
})
|
||||
menuItems.push(purgeMenuItem)
|
||||
}
|
||||
if (allowsAdditional) {
|
||||
const commandsSubmenuItems: (MenuItem | Submenu | PredefinedMenuItem)[] = []
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-delete')) {
|
||||
const deleteMenuItem = await MenuItem.new({
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Delete',
|
||||
url: '/delete',
|
||||
})
|
||||
},
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-move')) {
|
||||
const moveMenuItem = await MenuItem.new({
|
||||
id: 'move',
|
||||
text: 'Move',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Move',
|
||||
url: '/move',
|
||||
})
|
||||
},
|
||||
})
|
||||
commandsSubmenuItems.push(moveMenuItem)
|
||||
}
|
||||
|
||||
const rcloneVersion = await getRcloneVersion()
|
||||
|
||||
if (
|
||||
rcloneVersion?.yours &&
|
||||
compareVersions(rcloneVersion.yours, '1.70.0') === 1 &&
|
||||
!persistedStoreState.disabledActions?.includes('tray-serve')
|
||||
) {
|
||||
const serveToMenuItem = await MenuItem.new({
|
||||
id: 'serve',
|
||||
text: 'Serve',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Serve',
|
||||
url: '/serve',
|
||||
})
|
||||
},
|
||||
})
|
||||
commandsSubmenuItems.push(serveToMenuItem)
|
||||
}
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-purge')) {
|
||||
const purgeMenuItem = await MenuItem.new({
|
||||
id: 'purge',
|
||||
text: 'Purge',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Purge',
|
||||
url: '/purge',
|
||||
})
|
||||
},
|
||||
})
|
||||
commandsSubmenuItems.push(purgeMenuItem)
|
||||
}
|
||||
|
||||
if (!persistedStoreState.disabledActions?.includes('tray-delete')) {
|
||||
const deleteMenuItem = await MenuItem.new({
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
action: async () => {
|
||||
await openWindow({
|
||||
name: 'Delete',
|
||||
url: '/delete',
|
||||
})
|
||||
},
|
||||
})
|
||||
commandsSubmenuItems.push(deleteMenuItem)
|
||||
}
|
||||
|
||||
const commandsSubmenu = await Submenu.new({
|
||||
items: commandsSubmenuItems,
|
||||
text: 'Commands',
|
||||
})
|
||||
menuItems.push(deleteMenuItem)
|
||||
menuItems.push(commandsSubmenu)
|
||||
}
|
||||
|
||||
await PredefinedMenuItem.new({
|
||||
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 774 B |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 734 B |
|
After Width: | Height: | Size: 698 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 787 B |
|
After Width: | Height: | Size: 777 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 635 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 784 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 764 B |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 997 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
@@ -44,27 +44,7 @@
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"resources": [
|
||||
"icons/favicon/icon.png",
|
||||
"icons/favicon/frame_00_delay-0.1s.png",
|
||||
"icons/favicon/frame_01_delay-0.1s.png",
|
||||
"icons/favicon/frame_02_delay-0.1s.png",
|
||||
"icons/favicon/frame_03_delay-0.1s.png",
|
||||
"icons/favicon/frame_04_delay-0.1s.png",
|
||||
"icons/favicon/frame_05_delay-0.1s.png",
|
||||
"icons/favicon/frame_06_delay-0.1s.png",
|
||||
"icons/favicon/frame_07_delay-0.1s.png",
|
||||
"icons/favicon/frame_08_delay-0.1s.png",
|
||||
"icons/favicon/frame_09_delay-0.1s.png",
|
||||
"icons/favicon/frame_10_delay-0.1s.png",
|
||||
"icons/favicon/frame_11_delay-0.1s.png",
|
||||
"icons/favicon/frame_12_delay-0.1s.png",
|
||||
"icons/favicon/frame_13_delay-0.1s.png",
|
||||
"icons/favicon/frame_14_delay-0.1s.png",
|
||||
"icons/favicon/frame_15_delay-0.1s.png",
|
||||
"icons/favicon/frame_16_delay-0.1s.png",
|
||||
"icons/favicon/frame_17_delay-0.1s.png"
|
||||
],
|
||||
"resources": ["icons/favicon/", "icons/small/"],
|
||||
"shortDescription": "Cross-platform GUI for rclone & S3",
|
||||
"longDescription": "Cross-platform GUI for rclone & S3",
|
||||
"license": "Apache-2.0",
|
||||
|
||||