|
|
|
|
@ -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(5000)
|
|
|
|
|
.debounce(3000)
|
|
|
|
|
.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())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|