1 /* <lambda>null2 * Copyright (C) 2020 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.statusbar.notification.row.wrapper 18 19 import android.content.Context 20 import android.graphics.drawable.AnimatedImageDrawable 21 import android.view.View 22 import android.view.ViewGroup 23 import com.android.internal.widget.CachingIconView 24 import com.android.internal.widget.ConversationLayout 25 import com.android.internal.widget.MessagingGroup 26 import com.android.internal.widget.MessagingImageMessage 27 import com.android.internal.widget.MessagingLinearLayout 28 import com.android.systemui.res.R 29 import com.android.systemui.statusbar.notification.NotificationFadeAware 30 import com.android.systemui.statusbar.notification.NotificationUtils 31 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow 32 import com.android.systemui.statusbar.notification.row.wrapper.NotificationMessagingTemplateViewWrapper.setCustomImageMessageTransform 33 import com.android.systemui.util.children 34 35 /** 36 * Wraps a notification containing a conversation template 37 */ 38 class NotificationConversationTemplateViewWrapper constructor( 39 ctx: Context, 40 view: View, 41 row: ExpandableNotificationRow 42 ) : NotificationTemplateViewWrapper(ctx, view, row) { 43 44 private val minHeightWithActions: Int = NotificationUtils.getFontScaledHeight( 45 ctx, 46 R.dimen.notification_messaging_actions_min_height 47 ) 48 private val conversationLayout: ConversationLayout = view as ConversationLayout 49 50 private lateinit var conversationIconContainer: View 51 private lateinit var conversationIconView: CachingIconView 52 private lateinit var conversationBadgeBg: View 53 private lateinit var expandBtn: View 54 private lateinit var expandBtnContainer: View 55 private lateinit var imageMessageContainer: ViewGroup 56 private lateinit var messageContainers: ArrayList<MessagingGroup> 57 private lateinit var messagingLinearLayout: MessagingLinearLayout 58 private lateinit var conversationTitleView: View 59 private lateinit var importanceRing: View 60 private lateinit var appName: View 61 private var facePileBottomBg: View? = null 62 private var facePileBottom: View? = null 63 private var facePileTop: View? = null 64 65 private fun resolveViews() { 66 messagingLinearLayout = conversationLayout.messagingLinearLayout 67 imageMessageContainer = conversationLayout.imageMessageContainer 68 messageContainers = conversationLayout.messagingGroups 69 with(conversationLayout) { 70 conversationIconContainer = 71 requireViewById(com.android.internal.R.id.conversation_icon_container) 72 conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon) 73 conversationBadgeBg = 74 requireViewById(com.android.internal.R.id.conversation_icon_badge_bg) 75 expandBtn = requireViewById(com.android.internal.R.id.expand_button) 76 expandBtnContainer = requireViewById(com.android.internal.R.id.expand_button_container) 77 importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring) 78 appName = requireViewById(com.android.internal.R.id.app_name_text) 79 conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text) 80 facePileTop = findViewById(com.android.internal.R.id.conversation_face_pile_top) 81 facePileBottom = findViewById(com.android.internal.R.id.conversation_face_pile_bottom) 82 facePileBottomBg = 83 findViewById(com.android.internal.R.id.conversation_face_pile_bottom_background) 84 } 85 } 86 87 override fun onContentUpdated(row: ExpandableNotificationRow) { 88 // Reinspect the notification. Before the super call, because the super call also updates 89 // the transformation types and we need to have our values set by then. 90 resolveViews() 91 super.onContentUpdated(row) 92 } 93 94 override fun updateTransformedTypes() { 95 // This also clears the existing types 96 super.updateTransformedTypes() 97 98 mTransformationHelper.addTransformedView(TRANSFORMING_VIEW_TITLE, conversationTitleView) 99 addTransformedViews( 100 messagingLinearLayout, 101 appName 102 ) 103 104 setCustomImageMessageTransform(mTransformationHelper, imageMessageContainer) 105 106 addViewsTransformingToSimilar( 107 conversationIconView, 108 conversationBadgeBg, 109 expandBtn, 110 importanceRing, 111 facePileTop, 112 facePileBottom, 113 facePileBottomBg 114 ) 115 } 116 117 override fun getShelfTransformationTarget(): View? = 118 if (conversationLayout.isImportantConversation) 119 if (conversationIconView.visibility != View.GONE) 120 conversationIconView 121 else 122 // A notification with a fallback icon was set to important. Currently 123 // the transformation doesn't work for these and needs to be fixed. 124 // In the meantime those are using the icon. 125 super.getShelfTransformationTarget() 126 else 127 super.getShelfTransformationTarget() 128 129 override fun setRemoteInputVisible(visible: Boolean) = 130 conversationLayout.showHistoricMessages(visible) 131 132 override fun updateExpandability( 133 expandable: Boolean, 134 onClickListener: View.OnClickListener, 135 requestLayout: Boolean 136 ) = conversationLayout.updateExpandability(expandable, onClickListener) 137 138 override fun disallowSingleClick(x: Float, y: Float): Boolean { 139 val isOnExpandButton = expandBtnContainer.visibility == View.VISIBLE && 140 isOnView(expandBtnContainer, x, y) 141 return isOnExpandButton || super.disallowSingleClick(x, y) 142 } 143 144 override fun getMinLayoutHeight(): Int = 145 if (mActionsContainer != null && mActionsContainer.visibility != View.GONE) 146 minHeightWithActions 147 else 148 super.getMinLayoutHeight() 149 150 override fun setNotificationFaded(faded: Boolean) { 151 // Do not call super 152 NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded) 153 NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded) 154 } 155 156 // Starts or stops the animations in any drawables contained in this Conversation Notification. 157 override fun setAnimationsRunning(running: Boolean) { 158 // We apply to both the child message containers in a conversation group, 159 // and the top level image message container. 160 val containers = messageContainers.asSequence().map { it.messageContainer } + 161 sequenceOf(imageMessageContainer) 162 val drawables = 163 containers 164 .flatMap { it.children } 165 .mapNotNull { child -> 166 (child as? MessagingImageMessage)?.let { imageMessage -> 167 imageMessage.drawable as? AnimatedImageDrawable 168 } 169 } 170 drawables.toSet().forEach { 171 when { 172 running -> it.start() 173 !running -> it.stop() 174 } 175 } 176 } 177 } 178