UiEvents.kt
42 lines · 1.9 KB
Changed in: 0.5.0
| 1 | package dev.stave.ui.events |
| 2 | |
| 3 | import kotlinx.coroutines.channels.BufferOverflow |
| 4 | import kotlinx.coroutines.flow.MutableSharedFlow |
| 5 | import kotlinx.coroutines.flow.SharedFlow |
| 6 | import kotlinx.coroutines.flow.asSharedFlow |
| 7 | |
| 8 | /** |
| 9 | * App-wide bus for transient user-facing notifications. Emitters post strings; |
| 10 | * [dev.stave.desktop.ui.ToastHost] in StaveApp collects them into a small stack of |
| 11 | * Material Snackbar-style banners. |
| 12 | * |
| 13 | * **Design.** MutableSharedFlow with replay=0 (a toast that arrives before a |
| 14 | * collector is ready is dropped — we don't want last week's error flashing up on |
| 15 | * today's launch) and extraBufferCapacity=4 so a brief burst (e.g. three playlist |
| 16 | * loads failing in quick succession) queues rather than dropping. |
| 17 | * |
| 18 | * **What goes here.** Non-blocking informational messages that the user can safely |
| 19 | * ignore. Examples: "Lyrics unavailable for this track", "Couldn't reach LRCLIB", |
| 20 | * "Playlist saved to library", "Tag reader timed out". **Not** here: fatal errors |
| 21 | * that should prevent a user action from completing (those deserve a dialog), or |
| 22 | * status that's not time-bounded (those belong in the relevant screen's persistent |
| 23 | * UI). |
| 24 | */ |
| 25 | class UiEvents { |
| 26 | private val _messages = MutableSharedFlow<String>( |
| 27 | replay = 0, |
| 28 | extraBufferCapacity = 4, |
| 29 | onBufferOverflow = BufferOverflow.DROP_OLDEST, |
| 30 | ) |
| 31 | |
| 32 | /** Observe toast messages. Collectors are fire-and-forget; missed emissions |
| 33 | * while no collector is attached stay missed, which is what we want. */ |
| 34 | val messages: SharedFlow<String> = _messages.asSharedFlow() |
| 35 | |
| 36 | /** Post a toast. Non-suspending for convenience in non-coroutine call sites |
| 37 | * (IO error handlers, VLCJ callbacks). Drops on overflow — at which point the |
| 38 | * user probably has bigger problems than one dropped toast. */ |
| 39 | fun post(message: String) { |
| 40 | _messages.tryEmit(message) |
| 41 | } |
| 42 | } |


