@ -45,26 +45,30 @@ class HealthNotifier(
" wantrunning-false " )
init {
// This roughly matches the iOS/macOS implementation in terms of debouncing, and ingoring
// health warnings in various states.
scope . launch {
healthStateFlow
. distinctUntilChanged { old , new -> old ?. Warnings ?. count ( ) == new ?. Warnings ?. count ( ) }
. combine ( ipnStateFlow , :: Pair )
. debounce ( 5 000)
. debounce ( 3 000)
. collect { pair ->
val health = pair . first
val ipnState = pair . second
// When the client is Stopped, no warnings should get added, and any warnings added
// previously should be removed.
if ( ipnState == Ipn . State . Stopped ) {
TSLog . d (
TAG ,
" Ignoring and dropping all pre-existing health messages in the Stopped state " )
dropAllWarnings ( )
return @collect
} else {
TSLog . d ( TAG , " Health updated: ${health?.Warnings?.keys?.sorted()} " )
health ?. Warnings ?. let {
notifyHealthUpdated ( it . values . mapNotNull { it } . toTypedArray ( ) )
// When the client is Stopped, requires Login or has no state, we should drop all
// existing warnings
when ( val ipnState = pair . second ) {
Ipn . State . NeedsLogin ,
Ipn . State . Stopped ,
Ipn . State . NoState -> {
TSLog . d ( TAG , " Ignoring and dropping all health messages in state ${ipnState} " )
dropAllWarnings ( )
return @collect
}
else -> {
TSLog . d ( TAG , " Health updated: ${health?.Warnings?.keys?.sorted()} " )
health ?. Warnings ?. let {
notifyHealthUpdated ( it . values . mapNotNull { it } . toTypedArray ( ) )
}
}
}
}