1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.bouncer.ui.binder 18 19 import android.text.TextUtils 20 import android.util.PluralsMessageFormatter 21 import androidx.lifecycle.Lifecycle 22 import androidx.lifecycle.repeatOnLifecycle 23 import com.android.keyguard.BouncerKeyguardMessageArea 24 import com.android.keyguard.KeyguardMessageArea 25 import com.android.keyguard.KeyguardMessageAreaController 26 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor 27 import com.android.systemui.bouncer.shared.model.Message 28 import com.android.systemui.bouncer.ui.BouncerMessageView 29 import com.android.systemui.flags.FeatureFlags 30 import com.android.systemui.flags.Flags 31 import com.android.systemui.lifecycle.repeatWhenAttached 32 import com.android.systemui.log.BouncerLogger 33 import kotlinx.coroutines.launch 34 35 object BouncerMessageViewBinder { 36 @JvmStatic 37 fun bind( 38 view: BouncerMessageView, 39 interactor: BouncerMessageInteractor, 40 factory: KeyguardMessageAreaController.Factory, 41 bouncerLogger: BouncerLogger, 42 featureFlags: FeatureFlags 43 ) { 44 view.repeatWhenAttached { 45 if (!featureFlags.isEnabled(Flags.REVAMPED_BOUNCER_MESSAGES)) { 46 view.primaryMessageView?.disable() 47 view.secondaryMessageView?.disable() 48 return@repeatWhenAttached 49 } 50 view.init(factory) 51 view.primaryMessage?.setIsVisible(true) 52 view.secondaryMessage?.setIsVisible(true) 53 repeatOnLifecycle(Lifecycle.State.STARTED) { 54 bouncerLogger.startBouncerMessageInteractor() 55 launch { 56 interactor.bouncerMessage.collect { 57 bouncerLogger.bouncerMessageUpdated(it) 58 updateView( 59 view.primaryMessage, 60 view.primaryMessageView, 61 message = it?.message, 62 allowTruncation = true, 63 ) 64 updateView( 65 view.secondaryMessage, 66 view.secondaryMessageView, 67 message = it?.secondaryMessage, 68 allowTruncation = false, 69 ) 70 view.requestLayout() 71 } 72 } 73 } 74 } 75 } 76 77 private fun updateView( 78 controller: KeyguardMessageAreaController<KeyguardMessageArea>?, 79 view: BouncerKeyguardMessageArea?, 80 message: Message?, 81 allowTruncation: Boolean = false, 82 ) { 83 if (view == null || controller == null) return 84 if (message?.message != null || message?.messageResId != null) { 85 controller.setIsVisible(true) 86 var newMessage = message.message ?: "" 87 if (message.messageResId != null && message.messageResId != 0) { 88 newMessage = view.resources.getString(message.messageResId) 89 if (message.formatterArgs != null) { 90 newMessage = 91 PluralsMessageFormatter.format( 92 view.resources, 93 message.formatterArgs, 94 message.messageResId 95 ) 96 } 97 } 98 controller.setMessage(newMessage, message.animate) 99 } else { 100 controller.setIsVisible(false) 101 controller.setMessage(0) 102 } 103 message?.colorState?.let { controller.setNextMessageColor(it) } 104 view.ellipsize = 105 if (allowTruncation) TextUtils.TruncateAt.END else TextUtils.TruncateAt.MARQUEE 106 } 107 } 108