fix: improve tray menu state management to prevent rapid icon flickering during concurrent sync operations#346
Conversation
…ing during concurrent sync operations
| trayInstance.setImage.mockClear(); | ||
| trayInstance.setToolTip.mockClear(); |
There was a problem hiding this comment.
Why you do the mockclear after calling?
In rallity without these mocks, on the assert you would only assert that inly has been called once right? Maybe it is easier to read that way, what do you think?
There was a problem hiding this comment.
These need to be cleared here because there are previous calls that interfere with this test's assert; without clearing them, two previous calls that are false are counted, which interferes with the purpose of the test
| traySetup.setTrayStatus('SYNCING'); // file A starts | ||
| traySetup.setTrayStatus('SYNCING'); // file B starts | ||
| traySetup.setTrayStatus('IDLE'); // file A finishes | ||
| trayMenuInstance.setState.mockClear(); |
There was a problem hiding this comment.
This is a simulation of concurrent uploads of multiple files being uploaded to the drive at the same time; each file updates the icon's status separately.
| traySetup.setTrayStatus('IDLE'); | ||
|
|
||
| // Then | ||
| call(trayMenuInstance.setState).toBe('IDLE'); |
There was a problem hiding this comment.
Shouldnt it prevail the alert icon over the idle? Since we got an operation that got an "alert"?
There was a problem hiding this comment.
The problem with this icon priority system is that when there are multiple simultaneous uploads, the tray displays the most recently updated icon.
|



What is Changed / Added
Added a two-layer fix in the tray icon module to prevent flickering when many files are synced concurrently:
1. Reference counter in
setTrayStatus(tray-setup.ts)activeSyncCountto track the number of in-flight sync operations.SYNCINGincrements the counter and updates the tray immediately.IDLEdecrements the counter and only updates the tray when the counter reaches zero (all operations finished).ALERTalso decrements the counter, since an error terminates its associated operation.resetTrayStatus()for session boundaries (login/logout) to force a state and reset the counter, preventing the icon from getting stuck on SYNCING after a logout mid-upload.2. State deduplication in
TrayMenu.setState(tray-menu.ts)currentStatefield toTrayMenu.setStatenow returns early when called with the state that is already displayed, skipping the nativesetImageandsetToolTipcalls entirely.Session boundary call sites (
register-session-event-handlers.ts,register-app-ready-flow.ts) updated to useresetTrayStatusinstead ofsetTrayStatuson login/logout.Why
On Linux, Electron's tray relies on the AppIndicator/StatusNotifierItem DBus protocol. Every call to
tray.setImage()sends a DBus message that causes the system tray to fully re-render, which momentarily dismisses any open popup menu.Previously, each individual file operation called
setTrayStatus('SYNCING')on start andsetTrayStatus('IDLE')on completion. When uploading a folder with many files, or pasting multiple files at once onto the virtual drive, this produced rapid SYNCING → IDLE → SYNCING → IDLE cycles — one full cycle per file. Each cycle triggered twosetImagecalls, causing the tray menu to flicker uncontrollably and become unclickable.With both fixes combined, the number of real
setImagecalls is capped at two for any batch of concurrent operations: one when the first operation starts (IDLE → SYNCING) and one when the last one finishes (SYNCING → IDLE).