Skip to content

refactor: replace snackbars with persistent info popups#315

Open
fioan89 wants to merge 2 commits into
mainfrom
replace-snackars-with-modal-dialogs
Open

refactor: replace snackbars with persistent info popups#315
fioan89 wants to merge 2 commits into
mainfrom
replace-snackars-with-modal-dialogs

Conversation

@fioan89

@fioan89 fioan89 commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

ui.showSnackbar has a few issues that make it unreliable for surfacing errors and notifications:

  • Limited lifetime: a snackbar launched while the window is hidden is often never shown if more than a few seconds pass before the window becomes visible.
  • Only the last of several snackbars launched in a row is displayed.
  • Toolbox keeps the coroutine suspended for the snackbar's lifetime and cancels (rather than resumes) it on dismissal, propagating the cancel to the caller and skipping any follow-up code such as resetting the busy state.

Switch to ui.showInfoPopup, which is backed by a persistent dialog state: it is still rendered once the window becomes visible, resumes normally on dismissal, and is serialized via a mutex so popups are shown one after another instead of overwriting each other.

Since popups render after the window becomes visible, the ErrorReporter buffer-and-flush abstraction is no longer needed. Remove it along with the parallel errorBuffer in CoderRemoteProvider and the visibilityState plumbing threaded through the setup wizard steps; errors are now shown directly where they occur.

ui.showSnackbar has a few issues that make it unreliable for surfacing
errors and notifications:

- Limited lifetime: a snackbar launched while the window is hidden is
  often never shown if more than a few seconds pass before the window
  becomes visible.
- Only the last of several snackbars launched in a row is displayed.
- Toolbox keeps the coroutine suspended for the snackbar's lifetime and
  cancels (rather than resumes) it on dismissal, propagating the cancel
  to the caller and skipping any follow-up code such as resetting the
  busy state.

Switch to ui.showInfoPopup, which is backed by a persistent dialog
state: it is still rendered once the window becomes visible, resumes
normally on dismissal, and is serialized via a mutex so popups are shown
one after another instead of overwriting each other.

Since popups render after the window becomes visible, the ErrorReporter
buffer-and-flush abstraction is no longer needed. Remove it along with
the parallel errorBuffer in CoderRemoteProvider and the visibilityState
plumbing threaded through the setup wizard steps; errors are now shown
directly where they occur.
@linear-code

linear-code Bot commented Jun 5, 2026

Copy link
Copy Markdown

DEVEX-408

@fioan89

fioan89 commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator Author

)
break
}
context.logger.error(ex, "workspace polling error encountered")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it may be worth distinguishing this error log from the one above it, unless they suggest the same issue and remedy

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Thx.

Comment on lines +41 to +46
/**
* Serializes popups so they are shown one after another. [ToolboxUi.showInfoPopup] is
* backed by a single dialog slot, so launching two popups concurrently would cause the
* second to replace the first before the user ever sees it.
*/
private val popupMutex = Mutex()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is my lack of Kotlin knowledge showing, but isn't a mutex just going to prevent two popups at once? does this actually queue them up to be shown one after another as the comment suggests?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the initial issue was that two showSnackbar from the same coroutine ended up showing only one of them (usually the last one). showInfoPopup however do not have this issue, however if you have two coroutines (running in parallel either in a thread pool under the same dispatcher or threads from different dispatchers ) launching the showInfoPopup then you'd get a similar behavior, only one pop-up. To be honest I might have been overly defensive because up until now we always launch from coroutines running on the same dispatcher (the default one), so we don't need the mutex right now. Let me revert this part back

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants