| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.systemui.statusbar.notification.row.wrapper |
| |
| import android.content.Context |
| import android.view.View |
| import android.view.View.GONE |
| import android.view.ViewGroup |
| import com.android.internal.widget.CachingIconView |
| import com.android.internal.widget.ConversationLayout |
| import com.android.internal.widget.MessagingLinearLayout |
| import com.android.systemui.R |
| import com.android.systemui.statusbar.TransformableView |
| import com.android.systemui.statusbar.ViewTransformationHelper |
| import com.android.systemui.statusbar.notification.NotificationUtils |
| import com.android.systemui.statusbar.notification.TransformState |
| import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow |
| import com.android.systemui.statusbar.notification.row.HybridNotificationView |
| |
| /** |
| * Wraps a notification containing a conversation template |
| */ |
| class NotificationConversationTemplateViewWrapper constructor( |
| ctx: Context, |
| view: View, |
| row: ExpandableNotificationRow |
| ) : NotificationTemplateViewWrapper(ctx, view, row) { |
| |
| private val minHeightWithActions: Int = NotificationUtils.getFontScaledHeight( |
| ctx, |
| R.dimen.notification_messaging_actions_min_height |
| ) |
| private val conversationLayout: ConversationLayout = view as ConversationLayout |
| |
| private lateinit var conversationIconView: CachingIconView |
| private lateinit var conversationBadgeBg: View |
| private lateinit var expandButton: View |
| private lateinit var expandButtonContainer: View |
| private lateinit var expandButtonInnerContainer: View |
| private lateinit var imageMessageContainer: ViewGroup |
| private lateinit var messagingLinearLayout: MessagingLinearLayout |
| private lateinit var conversationTitleView: View |
| private lateinit var importanceRing: View |
| private lateinit var appName: View |
| private var facePileBottomBg: View? = null |
| private var facePileBottom: View? = null |
| private var facePileTop: View? = null |
| |
| private fun resolveViews() { |
| messagingLinearLayout = conversationLayout.messagingLinearLayout |
| imageMessageContainer = conversationLayout.imageMessageContainer |
| with(conversationLayout) { |
| conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon) |
| conversationBadgeBg = |
| requireViewById(com.android.internal.R.id.conversation_icon_badge_bg) |
| expandButton = requireViewById(com.android.internal.R.id.expand_button) |
| expandButtonContainer = |
| requireViewById(com.android.internal.R.id.expand_button_container) |
| expandButtonInnerContainer = |
| requireViewById(com.android.internal.R.id.expand_button_inner_container) |
| importanceRing = requireViewById(com.android.internal.R.id.conversation_icon_badge_ring) |
| appName = requireViewById(com.android.internal.R.id.app_name_text) |
| conversationTitleView = requireViewById(com.android.internal.R.id.conversation_text) |
| facePileTop = findViewById(com.android.internal.R.id.conversation_face_pile_top) |
| facePileBottom = findViewById(com.android.internal.R.id.conversation_face_pile_bottom) |
| facePileBottomBg = |
| findViewById(com.android.internal.R.id.conversation_face_pile_bottom_background) |
| } |
| } |
| |
| override fun onContentUpdated(row: ExpandableNotificationRow) { |
| // Reinspect the notification. Before the super call, because the super call also updates |
| // the transformation types and we need to have our values set by then. |
| resolveViews() |
| super.onContentUpdated(row) |
| } |
| |
| override fun updateTransformedTypes() { |
| // This also clears the existing types |
| super.updateTransformedTypes() |
| |
| addTransformedViews( |
| messagingLinearLayout, |
| appName, |
| conversationTitleView) |
| |
| // Let's ignore the image message container since that is transforming as part of the |
| // messages already |
| mTransformationHelper.setCustomTransformation( |
| object : ViewTransformationHelper.CustomTransformation() { |
| override fun transformTo( |
| ownState: TransformState, |
| otherView: TransformableView, |
| transformationAmount: Float |
| ): Boolean { |
| if (otherView is HybridNotificationView) { |
| return false |
| } |
| // we're hidden by default by the transformState |
| ownState.ensureVisible() |
| // Let's do nothing otherwise, this is already handled by the messages |
| return true |
| } |
| |
| override fun transformFrom( |
| ownState: TransformState, |
| otherView: TransformableView, |
| transformationAmount: Float |
| ): Boolean = |
| transformTo(ownState, otherView, transformationAmount) |
| }, |
| imageMessageContainer.id |
| ) |
| |
| addViewsTransformingToSimilar( |
| conversationIconView, |
| conversationBadgeBg, |
| expandButton, |
| importanceRing, |
| facePileTop, |
| facePileBottom, |
| facePileBottomBg |
| ) |
| } |
| |
| override fun getExpandButton() = expandButtonInnerContainer |
| |
| override fun setShelfIconVisible(visible: Boolean) { |
| if (conversationLayout.isImportantConversation) { |
| if (conversationIconView.visibility != GONE) { |
| conversationIconView.isForceHidden = visible |
| // We don't want the small icon to be hidden by the extended wrapper, as force |
| // hiding the conversationIcon will already do that via its listener. |
| return |
| } |
| } |
| super.setShelfIconVisible(visible) |
| } |
| |
| override fun getShelfTransformationTarget(): View? = |
| if (conversationLayout.isImportantConversation) |
| if (conversationIconView.visibility != GONE) |
| conversationIconView |
| else |
| // A notification with a fallback icon was set to important. Currently |
| // the transformation doesn't work for these and needs to be fixed. |
| // In the meantime those are using the icon. |
| super.getShelfTransformationTarget() |
| else |
| super.getShelfTransformationTarget() |
| |
| override fun setRemoteInputVisible(visible: Boolean) = |
| conversationLayout.showHistoricMessages(visible) |
| |
| override fun updateExpandability(expandable: Boolean, onClickListener: View.OnClickListener?) = |
| conversationLayout.updateExpandability(expandable, onClickListener) |
| |
| override fun disallowSingleClick(x: Float, y: Float): Boolean { |
| val isOnExpandButton = expandButtonContainer.visibility == View.VISIBLE && |
| isOnView(expandButtonContainer, x, y) |
| return isOnExpandButton || super.disallowSingleClick(x, y) |
| } |
| |
| override fun getMinLayoutHeight(): Int = |
| if (mActionsContainer != null && mActionsContainer.visibility != View.GONE) |
| minHeightWithActions |
| else |
| super.getMinLayoutHeight() |
| |
| private fun addTransformedViews(vararg vs: View?) = |
| vs.forEach { view -> view?.let(mTransformationHelper::addTransformedView) } |
| |
| private fun addViewsTransformingToSimilar(vararg vs: View?) = |
| vs.forEach { view -> view?.let(mTransformationHelper::addViewTransformingToSimilar) } |
| } |