Coverage Summary for Class: UnhandledErrors (com.georgeci.moneysurfer.utils)

Class Class, % Method, % Branch, % Line, % Instruction, %
UnhandledErrors 100% (1/1) 100% (3/3) 100% (5/5) 100% (15/15)


 package com.georgeci.moneysurfer.utils
 
 import kotlinx.coroutines.channels.BufferOverflow
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableSharedFlow
 
 /**
  * Process-wide channel for throwables no feature handled itself: [MviViewModel.launch]
  * publishes here when the caller passed no `onError`, and the global error boundary in
  * `App.kt` renders them as a friendly error state (issue #78).
  *
  * A singleton rather than a DI-injected dependency on purpose — the alternative is
  * threading a reporter through the constructor of every one of the ~25 feature
  * ViewModels, for a channel that is genuinely global.
  *
  * Publishing here is *not* the reporting path: [MviViewModel.launch] logs the throwable
  * via Kermit at Error severity first, which is what reaches Crashlytics through
  * `CrashReportingLogWriter`. This flow only drives the UI fallback.
  */
 object UnhandledErrors {
 
     private val mutableErrors = MutableSharedFlow<Throwable>(
         extraBufferCapacity = 1,
         // A burst of failures (e.g. every widget on the dashboard failing at once) should
         // surface the newest one rather than block the emitting coroutine.
         onBufferOverflow = BufferOverflow.DROP_OLDEST,
     )
 
     val errors: Flow<Throwable> = mutableErrors
 
     fun report(error: Throwable) {
         mutableErrors.tryEmit(error)
     }
 }