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.view.View 21 import android.view.View.GONE 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.MessagingLinearLayout 26 import com.android.systemui.R 27 import com.android.systemui.statusbar.TransformableView 28 import com.android.systemui.statusbar.ViewTransformationHelper 29 import com.android.systemui.statusbar.notification.NotificationUtils 30 import com.android.systemui.statusbar.notification.TransformState 31 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow 32 import com.android.systemui.statusbar.notification.row.HybridNotificationView 33 34 /** 35 * Wraps a notification containing a conversation template 36 */ 37 class NotificationConversationTemplateViewWrapper constructor( 38 ctx: Context, 39 view: View, 40 row: ExpandableNotificationRow 41 ) : NotificationTemplateViewWrapper(ctx, view, row) { 42 43 private val minHeightWithActions: Int = NotificationUtils.getFontScaledHeight( 44 ctx, 45 R.dimen.notification_messaging_actions_min_height 46 ) 47 private val conversationLayout: ConversationLayout = view as ConversationLayout 48 49 private lateinit var conversationIconView: CachingIconView 50 private lateinit var conversationBadgeBg: View 51 private lateinit var expandButton: View 52 private lateinit var expandButtonContainer: View 53 private lateinit var expandButtonInnerContainer: View 54 private lateinit var imageMessageContainer: ViewGroup 55 private lateinit var messagingLinearLayout: MessagingLinearLayout 56 private lateinit var conversationTitleView: View 57 private lateinit var importanceRing: View 58 private lateinit var appName: View 59 private var facePileBottomBg: View? = null 60 private var facePileBottom: View? = null 61 private var facePileTop: View? = null 62 63 private fun resolveViews() { 64 messagingLinearLayout = conversationLayout.messagingLinearLayout 65 imageMessageContainer = conversationLayout.imageMessageContainer 66 with(conversationLayout) { 67 conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon) 68 conversationBadgeBg = 69 requireViewById(com.android.internal.R.id.conversation_icon_badge_bg) 70 expandButton = requireViewById(com.android.internal.R.id.expand_button) 71 expandButtonContainer = 72 requireViewById(com.android.internal.R.id.expand_button_container) 73 expandButtonInnerContainer = 74 requireViewById(com.android.internal.R.id.expand_button_inner_container) 75 importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring) 76 appName = requireViewById(com.android.internal.R.id.app_name_text) 77 conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text) 78 facePileTop = findViewById(com.android.internal.R.id.conversation_face_pile_top) 79 facePileBottom = findViewById(com.android.internal.R.id.conversation_face_pile_bottom) 80 facePileBottomBg = 81 findViewById(com.android.internal.R.id.conversation_face_pile_bottom_background) 82 } 83 } 84 85 override fun onContentUpdated(row: ExpandableNotificationRow) { 86 // Reinspect the notification. Before the super call, because the super call also updates 87 // the transformation types and we need to have our values set by then. 88 resolveViews() 89 super.onContentUpdated(row) 90 } 91 92 override fun updateTransformedTypes() { 93 // This also clears the existing types 94 super.updateTransformedTypes() 95 96 addTransformedViews( 97 messagingLinearLayout, 98 appName, 99 conversationTitleView) 100 101 // Let's ignore the image message container since that is transforming as part of the 102 // messages already 103 mTransformationHelper.setCustomTransformation( 104 object : ViewTransformationHelper.CustomTransformation() { 105 override fun transformTo( 106 ownState: TransformState, 107 otherView: TransformableView, 108 transformationAmount: Float 109 ): Boolean { 110 if (otherView is HybridNotificationView) { 111 return false 112 } 113 // we're hidden by default by the transformState 114 ownState.ensureVisible() 115 // Let's do nothing otherwise, this is already handled by the messages 116 return true 117 } 118 119 override fun transformFrom( 120 ownState: TransformState, 121 otherView: TransformableView, 122 transformationAmount: Float 123 ): Boolean = 124 transformTo(ownState, otherView, transformationAmount) 125 }, 126 imageMessageContainer.id 127 ) 128 129 addViewsTransformingToSimilar( 130 conversationIconView, 131 conversationBadgeBg, 132 expandButton, 133 importanceRing, 134 facePileTop, 135 facePileBottom, 136 facePileBottomBg 137 ) 138 } 139 140 override fun getExpandButton() = expandButtonInnerContainer 141 142 override fun setShelfIconVisible(visible: Boolean) { 143 if (conversationLayout.isImportantConversation) { 144 if (conversationIconView.visibility != GONE) { 145 conversationIconView.isForceHidden = visible 146 // We don't want the small icon to be hidden by the extended wrapper, as force 147 // hiding the conversationIcon will already do that via its listener. 148 return 149 } 150 } 151 super.setShelfIconVisible(visible) 152 } 153 154 override fun getShelfTransformationTarget(): View? = 155 if (conversationLayout.isImportantConversation) 156 if (conversationIconView.visibility != GONE) 157 conversationIconView 158 else 159 // A notification with a fallback icon was set to important. Currently 160 // the transformation doesn't work for these and needs to be fixed. 161 // In the meantime those are using the icon. 162 super.getShelfTransformationTarget() 163 else 164 super.getShelfTransformationTarget() 165 166 override fun setRemoteInputVisible(visible: Boolean) = 167 conversationLayout.showHistoricMessages(visible) 168 169 override fun updateExpandability(expandable: Boolean, onClickListener: View.OnClickListener?) = 170 conversationLayout.updateExpandability(expandable, onClickListener) 171 172 override fun disallowSingleClick(x: Float, y: Float): Boolean { 173 val isOnExpandButton = expandButtonContainer.visibility == View.VISIBLE && 174 isOnView(expandButtonContainer, x, y) 175 return isOnExpandButton || super.disallowSingleClick(x, y) 176 } 177 178 override fun getMinLayoutHeight(): Int = 179 if (mActionsContainer != null && mActionsContainer.visibility != View.GONE) 180 minHeightWithActions 181 else 182 super.getMinLayoutHeight() 183 184 private fun addTransformedViews(vararg vs: View?) = 185 vs.forEach { view -> view?.let(mTransformationHelper::addTransformedView) } 186 187 private fun addViewsTransformingToSimilar(vararg vs: View?) = 188 vs.forEach { view -> view?.let(mTransformationHelper::addViewTransformingToSimilar) } 189 } 190