From b4d55188a3b03c1f79843d821eb6936f3fffb62f Mon Sep 17 00:00:00 2001 From: FTCHD <144691102+FTCHD@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:13:02 +0200 Subject: [PATCH] fix Tray shifting in tab bars (#35) Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com> --- lib/menu.ts | 18 ++++--- lib/tray.ts | 127 +++++++++++++++++++++++++------------------------- lib/window.ts | 9 ++-- main.ts | 17 ++----- 4 files changed, 80 insertions(+), 91 deletions(-) diff --git a/lib/menu.ts b/lib/menu.ts index 4764cab..414dea3 100644 --- a/lib/menu.ts +++ b/lib/menu.ts @@ -10,7 +10,7 @@ import notify from './notify' 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 { showDefaultTray, showLoadingTray } from './tray' import { lockWindows, openFullWindow, openWindow, unlockWindows } from './window' async function parseRemotes(remotes: string[]) { @@ -38,9 +38,7 @@ async function parseRemotes(remotes: string[]) { id: `mount-${remote}`, text: 'Quick Mount', action: async () => { - await getMainTray().then((t) => t?.setVisible(false)) - - await getLoadingTray().then((t) => t?.setVisible(true)) + await showLoadingTray() try { const needsPlugin = await needsMountPlugin() @@ -153,8 +151,6 @@ async function parseRemotes(remotes: string[]) { })) } } - - await rebuildTrayMenu() } catch (error) { // await resetMainWindow() Sentry.captureException(error) @@ -164,8 +160,7 @@ async function parseRemotes(remotes: string[]) { }) } finally { await unlockWindows() - await getLoadingTray().then((t) => t?.setVisible(false)) - await getMainTray().then((t) => t?.setVisible(true)) + await showDefaultTray() } }, }) @@ -227,6 +222,7 @@ async function parseRemotes(remotes: string[]) { id: `remove-${remote}`, text: 'Remove', action: async () => { + await showLoadingTray() const answer = await ask( `Are you sure you want to remove ${remote}? This action cannot be reverted.`, { title: `Removing ${remote}`, kind: 'warning' } @@ -237,7 +233,7 @@ async function parseRemotes(remotes: string[]) { } await deleteRemote(remote) - // await rebuildTrayMenu() + await showDefaultTray() }, }) submenuItems.push(removeMenuItem) @@ -261,8 +257,8 @@ async function parseRemotes(remotes: string[]) { text: 'Unmount (' + currentMount.MountPoint.split('/').pop() + ')', action: async () => { try { + await showLoadingTray() await unmountRemote({ mountPoint: currentMount.MountPoint }) - await rebuildTrayMenu() await message( `Successfully unmounted ${remote} from ${currentMount.MountPoint.split('/').pop()}`, { @@ -276,6 +272,8 @@ async function parseRemotes(remotes: string[]) { kind: 'error', title: 'Unmount Error', }) + } finally { + await showDefaultTray() } }, }) diff --git a/lib/tray.ts b/lib/tray.ts index 42d5f15..b755a1d 100644 --- a/lib/tray.ts +++ b/lib/tray.ts @@ -10,72 +10,29 @@ import { platform } from '@tauri-apps/plugin-os' import { buildMenu } from './menu' import { resetMainWindow } from './window' -export async function getMainTray() { - return await TrayIcon.getById('main-tray') -} - -export async function getLoadingTray() { - return await TrayIcon.getById('loading-tray') -} - export async function triggerTrayRebuild() { return getAllWindows().then((windows) => { windows.find((w) => w.label === 'main')?.emit('rebuild-tray') }) } -export async function rebuildTrayMenu() { - console.log('[rebuildTrayMenu]') +let interval: NodeJS.Timeout | null = null - const tray = await getMainTray() - if (!tray) { - console.error('[rebuildTrayMenu] tray not found') - return - } - const newMenu = await buildMenu() - await tray.setMenu(newMenu) - - console.log('[rebuildTrayMenu] tray menu rebuilt') +async function getTray() { + return await TrayIcon.getById('main-tray') } -async function onTrayAction(event: TrayIconEvent) { - if (event.type === 'Click') { - console.log('[onTrayAction] tray clicked:', event) - - await resetMainWindow() - } -} - -// Initialize the tray -export async function initTray(): Promise { - try { - console.log('[initTray]') - const menu = await buildMenu() - console.log('[initTray] built menu') - - await TrayIcon.getById('loading-tray').then((t) => t?.setVisible(false)) - console.log('[initTray] set loading tray to false') - - await TrayIcon.new({ - id: 'main-tray', - icon: (await resolveResource('icons/favicon/icon.png'))!, - tooltip: 'Rclone', - menu, - menuOnLeftClick: true, - action: onTrayAction, - }) - } catch (error) { - Sentry.captureException(error) - console.error('[initTray] failed to create tray') - console.error(error) - } -} - -export async function initLoadingTray() { - console.log('[initLoadingTray]') +export async function showLoadingTray() { + console.log('[showLoadingTray]') if (platform() === 'linux') { - console.log('[initLoadingTray] platform is linux, skipping') + console.log('[showLoadingTray] platform is linux, skipping') + return + } + + const tray = await getTray() + if (!tray) { + console.error('[showLoadingTray] tray not found') return } @@ -93,26 +50,70 @@ export async function initLoadingTray() { }) const loadingMenu = await Menu.new({ - id: 'main-menu', + id: 'loading-menu', items: [quitItem], }) - const loadingTray = await TrayIcon.new({ - id: 'loading-tray', - icon: globeIconPath, - menu: loadingMenu, - }) + await tray.setMenu(loadingMenu) + await tray.setIcon(globeIconPath) + await tray.setTooltip('Loading...') let currentIcon = 1 - setInterval(async () => { + interval = setInterval(async () => { if (currentIcon > 17) { currentIcon = 1 } const globeIconPath = await resolveResource( `icons/favicon/frame_${currentIcon < 10 ? '0' : ''}${currentIcon}_delay-0.1s.png` ) - await loadingTray?.setIcon(globeIconPath) + await tray?.setIcon(globeIconPath) currentIcon += 1 }, 200) } + +export async function showDefaultTray() { + console.log('[showDefaultTray]') + + const tray = await getTray() + if (!tray) { + console.error('[showDefaultTray] tray not found') + return + } + + if (interval) { + clearInterval(interval) + interval = null + } + + const newMenu = await buildMenu() + await tray.setMenu(newMenu) + await tray.setIcon(await resolveResource('icons/favicon/icon.png')) + await tray.setTooltip('Rclone') + + console.log('[showDefaultTray] tray menu rebuilt') +} + +export async function initTray() { + try { + console.log('[initTray]') + + await TrayIcon.new({ + id: 'main-tray', + icon: (await resolveResource('icons/favicon/icon.png'))!, + tooltip: 'Rclone', + menuOnLeftClick: true, + action: async (event: TrayIconEvent) => { + if (event.type === 'Click') { + console.log('[onTrayAction] tray clicked:', event) + + await resetMainWindow() + } + }, + }) + } catch (error) { + Sentry.captureException(error) + console.error('[initTray] failed to create tray') + console.error(error) + } +} diff --git a/lib/window.ts b/lib/window.ts index aacc992..b45da57 100644 --- a/lib/window.ts +++ b/lib/window.ts @@ -8,7 +8,7 @@ import { } from '@tauri-apps/api/window' import { platform } from '@tauri-apps/plugin-os' import { useStore } from './store' -import { getLoadingTray, getMainTray } from './tray' +import { showDefaultTray, showLoadingTray } from './tray' export async function resetMainWindow() { const window = await getAllWindows().then((w) => w.find((w) => w.label === 'main')) @@ -93,7 +93,6 @@ export async function openWindow({ visibleOnAllWorkspaces: false, alwaysOnTop: true, visible: false, - // visible: platform() !== 'windows', focus: true, title: name, decorations: false, @@ -103,11 +102,9 @@ export async function openWindow({ backgroundThrottling: 'disabled', }) - await getMainTray().then((t) => t?.setVisible(false)) - await getLoadingTray().then((t) => t?.setVisible(true)) + await showLoadingTray() await new Promise((resolve) => setTimeout(resolve, isFirstWindow ? 900 : 150)) - await getLoadingTray().then((t) => t?.setVisible(false)) - await getMainTray().then((t) => t?.setVisible(true)) + await showDefaultTray() // await w.hide() await w.setSize(new LogicalSize(width, height)) diff --git a/main.ts b/main.ts index eb8ec36..1ab0840 100644 --- a/main.ts +++ b/main.ts @@ -23,7 +23,7 @@ import { import { compareVersions } from './lib/rclone/common' import { initRclone } from './lib/rclone/init' import { usePersistedStore, useStore } from './lib/store' -import { initLoadingTray, initTray, rebuildTrayMenu } from './lib/tray' +import { initTray, showDefaultTray, showLoadingTray } from './lib/tray' import { openSmallWindow } from './lib/window' import type { ScheduledTask } from './types/task' @@ -531,18 +531,11 @@ getCurrentWindow().listen('rebuild-tray', async (e) => { // wait for store to be updated await new Promise((resolve) => setTimeout(resolve, 250)) - await rebuildTrayMenu() + await showDefaultTray() }) -// function handleNetworkStatusChange() { -// console.log('Network status changed. Online:', navigator.onLine) -// // rebuildTrayMenu().catch(console.error) -// } - -// window.addEventListener('online', handleNetworkStatusChange) -// window.addEventListener('offline', handleNetworkStatusChange) - -initLoadingTray() +initTray() + .then(() => showLoadingTray()) .then(() => waitForHydration()) .then(() => checkVersion()) .then(() => validateInstance()) @@ -550,5 +543,5 @@ initLoadingTray() .then(() => onboardUser()) .then(() => startupMounts()) .then(() => resumeTasks()) - .then(() => initTray()) + .then(() => showDefaultTray()) .catch(console.error)