@@ -36,6 +36,8 @@ import kotlinx.coroutines.CoroutineScope
3636import kotlinx.coroutines.Dispatchers
3737import kotlinx.coroutines.SupervisorJob
3838import kotlinx.coroutines.cancel
39+ import kotlinx.coroutines.flow.combine
40+ import kotlinx.coroutines.flow.first
3941import kotlinx.coroutines.launch
4042import kotlinx.serialization.encodeToString
4143import kotlinx.serialization.json.Json
@@ -141,17 +143,32 @@ class App : UninitializedApp(), libtailscale.AppContext, ViewModelStoreOwner {
141143 initViewModels()
142144 applicationScope.launch {
143145 Notifier .state.collect { state ->
144- val ableToStartVPN = state > Ipn .State .NeedsMachineAuth
145- // If VPN is stopped, show a disconnected notification. If it is running as a foregrround
146- // service, IPNService will show a connected notification.
147- if (state == Ipn .State .Stopped ) {
148- notifyStatus(false )
149- }
150- val vpnRunning = state == Ipn .State .Starting || state == Ipn .State .Running
151- updateConnStatus(ableToStartVPN)
152- QuickToggleService .setVPNRunning(vpnRunning)
146+ combine(Notifier .state, MDMSettings .forceEnabled.flow) { state, forceEnabled ->
147+ Pair (state, forceEnabled)
148+ }
149+ .collect { (state, hideDisconnectAction) ->
150+ val ableToStartVPN = state > Ipn .State .NeedsMachineAuth
151+ // If VPN is stopped, show a disconnected notification. If it is running as a
152+ // foreground
153+ // service, IPNService will show a connected notification.
154+ if (state == Ipn .State .Stopped ) {
155+ notifyStatus(vpnRunning = false , hideDisconnectAction = hideDisconnectAction.value)
156+ }
157+
158+ val vpnRunning = state == Ipn .State .Starting || state == Ipn .State .Running
159+ updateConnStatus(ableToStartVPN)
160+ QuickToggleService .setVPNRunning(vpnRunning)
161+
162+ // Update notification status when VPN is running
163+ if (vpnRunning) {
164+ notifyStatus(vpnRunning = true , hideDisconnectAction = hideDisconnectAction.value)
165+ }
166+ }
153167 }
154168 }
169+ applicationScope.launch {
170+ val hideDisconnectAction = MDMSettings .forceEnabled.flow.first()
171+ }
155172 }
156173
157174 private fun initViewModels () {
@@ -419,8 +436,8 @@ open class UninitializedApp : Application() {
419436 notificationManager.createNotificationChannel(channel)
420437 }
421438
422- fun notifyStatus (vpnRunning : Boolean ) {
423- notifyStatus(buildStatusNotification(vpnRunning))
439+ fun notifyStatus (vpnRunning : Boolean , hideDisconnectAction : Boolean ) {
440+ notifyStatus(buildStatusNotification(vpnRunning, hideDisconnectAction ))
424441 }
425442
426443 fun notifyStatus (notification : Notification ) {
@@ -438,7 +455,7 @@ open class UninitializedApp : Application() {
438455 notificationManager.notify(STATUS_NOTIFICATION_ID , notification)
439456 }
440457
441- fun buildStatusNotification (vpnRunning : Boolean ): Notification {
458+ fun buildStatusNotification (vpnRunning : Boolean , hideDisconnectAction : Boolean ): Notification {
442459 val message = getString(if (vpnRunning) R .string.connected else R .string.not_connected)
443460 val icon = if (vpnRunning) R .drawable.ic_notification else R .drawable.ic_notification_disabled
444461 val action =
@@ -460,19 +477,22 @@ open class UninitializedApp : Application() {
460477 PendingIntent .getActivity(
461478 this , 1 , intent, PendingIntent .FLAG_UPDATE_CURRENT or PendingIntent .FLAG_IMMUTABLE )
462479
463- return NotificationCompat .Builder (this , STATUS_CHANNEL_ID )
464- .setSmallIcon(icon)
465- .setContentTitle(" Tailscale" )
466- .setContentText(message)
467- .setAutoCancel(! vpnRunning)
468- .setOnlyAlertOnce(! vpnRunning)
469- .setOngoing(vpnRunning)
470- .setSilent(true )
471- .setOngoing(false )
472- .setPriority(NotificationCompat .PRIORITY_DEFAULT )
473- .addAction(NotificationCompat .Action .Builder (0 , actionLabel, pendingButtonIntent).build())
474- .setContentIntent(pendingIntent)
475- .build()
480+ val builder =
481+ NotificationCompat .Builder (this , STATUS_CHANNEL_ID )
482+ .setSmallIcon(icon)
483+ .setContentTitle(getString(R .string.app_name))
484+ .setContentText(message)
485+ .setAutoCancel(! vpnRunning)
486+ .setOnlyAlertOnce(! vpnRunning)
487+ .setOngoing(vpnRunning)
488+ .setSilent(true )
489+ .setPriority(NotificationCompat .PRIORITY_DEFAULT )
490+ .setContentIntent(pendingIntent)
491+ if (! vpnRunning || ! hideDisconnectAction) {
492+ builder.addAction(
493+ NotificationCompat .Action .Builder (0 , actionLabel, pendingButtonIntent).build())
494+ }
495+ return builder.build()
476496 }
477497
478498 fun addUserDisallowedPackageName (packageName : String ) {
0 commit comments