Coverage Summary for Class: SessionConfigOverlayImpl (com.georgeci.moneysurfer.appconfig)

Class Method, % Branch, % Line, % Instruction, %
SessionConfigOverlayImpl 100% (6/6) 100% (8/8) 100% (47/47)
SessionConfigOverlayImpl$special$$inlined$map$1 0% (0/2)
SessionConfigOverlayImpl$special$$inlined$map$1$1
SessionConfigOverlayImpl$special$$inlined$map$1$2 0% (0/1)
SessionConfigOverlayImpl$special$$inlined$map$1$2$1
Total 66.7% (6/9) 100% (8/8) 100% (47/47)


 package com.georgeci.moneysurfer.appconfig
 
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.update
 import org.koin.core.annotation.Single
 
 /**
  * [SessionConfigOverlay] over a `StateFlow` map — the whole layer, since there is no store to read.
  *
  * `hydrate()` is a no-op and `isDegraded` is never true: an in-memory map cannot fail to be read,
  * which is also why this is the one layer that needs no mirror plumbing.
  *
  * The state flow doubles as [changes], so holding or releasing values re-resolves every observed
  * key — that is what actually keeps the theme on screen through a logout.
  *
  * Every mutation goes through [update] rather than assigning `state.value`. The three callers run
  * on different coroutines — [release] from a settings write, [hold] from the account wipe, [clear]
  * from session start — and a read-modify-write between two of them loses one: a `release` racing a
  * `hold` would reinstate the entry the write was meant to retire, leaving the new value invisible
  * underneath it for the rest of the session.
  */
 @Single(binds = [SessionConfigOverlay::class])
 class SessionConfigOverlayImpl : SessionConfigOverlay {
 
     private val state = MutableStateFlow<Map<String, String>>(emptyMap())
 
     override fun <T : Any> peek(key: ConfigKey<T>): LayerValue<T> = key.layerValueOf(state.value[key.name])
 
     override val changes: Flow<Unit> = state.map { }
 
     override suspend fun hydrate() = Unit
 
     override fun hold(values: Map<String, String>) {
         state.update { it + values }
     }
 
     override fun release(name: String) {
         state.update { it - name }
     }
 
     override fun clear() {
         state.value = emptyMap()
     }
 }