From a3c103f30feb1307d3c6fb643959207cbec681e5 Mon Sep 17 00:00:00 2001 From: Jonathan Nobels Date: Fri, 23 Jan 2026 11:13:13 -0500 Subject: [PATCH] android: drop health warnings in Stopped and NeedsLogin state fixes tailscale/corp#36233 We should be dropping health warnings in the NeedsLogin state. This matches the behaviour of iOS and macOS. Signed-off-by: Jonathan Nobels --- .../ipn/ui/notifier/HealthNotifier.kt | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/android/src/main/java/com/tailscale/ipn/ui/notifier/HealthNotifier.kt b/android/src/main/java/com/tailscale/ipn/ui/notifier/HealthNotifier.kt index 17d86a9..3af7e25 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/notifier/HealthNotifier.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/notifier/HealthNotifier.kt @@ -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()) + } } } }