Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 460b5fee authored by Andreas Miko's avatar Andreas Miko
Browse files

Refactor NotificationMenuRowPlugin to not require the GutsContent to be a View

For legacy reasons the design of the interface forced us to require
a dummy view instead of being able to provide a ComposeView directly
and keep it separate from the GutsContent interface.

This change should be no-op everywhere. I separated out this refactor
to mitigate the risk of introducing BundleHeaderGuts UI together with
this change.

Bug: 409748420
Test: REFACTOR_ONLY
Flag: EXEMPT refactor
Change-Id: I0ae0b921938022d6ed5dc71b4936aaf4ac070dac
parent 9c34de6c
Loading
Loading
Loading
Loading
+1 −10
Original line number Diff line number Diff line
@@ -53,25 +53,16 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.theme.PlatformTheme
import com.android.internal.R
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderGutsViewModel

fun createBundleHeaderGutsComposeView(
    context: Context,
    viewModel: BundleHeaderGutsViewModel,
): ComposeView {
fun createBundleHeaderGutsComposeView(context: Context): ComposeView {
    return ComposeView(context).apply {
        repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                initOnBackPressureDispatcherOwner(this@repeatWhenAttached.lifecycle)
                setContent {
                    // TODO(b/399588047): Check if we can init PlatformTheme once instead of once
                    //  per ComposeView
                    PlatformTheme { BundleHeaderGuts(viewModel) }
                }
            }
        }
    }
+7 −1
Original line number Diff line number Diff line
@@ -58,7 +58,13 @@ public interface NotificationMenuRowPlugin extends Plugin {

        public View getMenuView();

        public View getGutsView();
        /**
         * The guts content that provides the [View] to be displayed.
         *
         * @return Object of type [NotificationGuts.GutsContent]. The interface is not known in this
         *          module, therefore only the implementation returns the proper type.
         */
        Object getGutsContent();

        public String getContentDescription();

+20 −23
Original line number Diff line number Diff line
@@ -17,31 +17,22 @@
package com.android.systemui.statusbar.notification.row

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.theme.PlatformTheme
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.notifications.ui.composable.row.BundleHeaderGuts
import com.android.systemui.notifications.ui.composable.row.createBundleHeaderGutsComposeView
import com.android.systemui.statusbar.notification.collection.BundleEntryAdapter
import com.android.systemui.statusbar.notification.row.NotificationGuts.GutsContent
import com.android.systemui.statusbar.notification.row.ui.viewmodel.BundleHeaderGutsViewModel

/**
 * This View is a container for a ComposeView and implements GutsContent. Technically, this should
 * not be a View as GutsContent could just return the ComposeView directly for getContentView().
 * Unfortunately, the legacy design of `NotificationMenuRowPlugin.MenuItem.getGutsView()` forces the
 * GutsContent to be a View itself. Therefore this class is a view that just holds the ComposeView.
 *
 * A redesign of `NotificationMenuRowPlugin.MenuItem.getGutsView()` to return GutsContent instead is
 * desired but it lacks proper module dependencies. As soon as this class does not need to inherit
 * from View it can just return the ComposeView directly instead.
 */
class BundleHeaderGutsContent
@JvmOverloads
constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
    FrameLayout(context, attrs, defStyleAttr), GutsContent {
/** The guts content that provides the view to be displayed when a bundle header is long pressed. */
class BundleHeaderGutsContent(context: Context) : GutsContent {

    private var composeView: ComposeView? = null
    private var composeView: ComposeView = createBundleHeaderGutsComposeView(context)
    private var gutsParent: NotificationGuts? = null

    fun bindNotification(
@@ -50,8 +41,6 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
        onDoneClicked: () -> Unit = {},
        onDismissClicked: () -> Unit = {},
    ) {
        if (composeView != null) return

        val repository = (row.entryAdapter as BundleEntryAdapter).entry.bundleRepository
        val viewModel =
            BundleHeaderGutsViewModel(
@@ -61,8 +50,16 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
                onDoneClicked = onDoneClicked,
                onDismissClicked = onDismissClicked,
            )
        composeView = createBundleHeaderGutsComposeView(context, viewModel)
        addView(composeView)

        composeView.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                composeView.setContent {
                    // TODO(b/399588047): Check if we can init PlatformTheme once instead of once
                    //  per ComposeView
                    PlatformTheme { BundleHeaderGuts(viewModel) }
                }
            }
        }
    }

    override fun setGutsParent(listener: NotificationGuts?) {
@@ -70,11 +67,11 @@ constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
    }

    override fun getContentView(): View {
        return this
        return composeView
    }

    override fun getActualHeight(): Int {
        return composeView?.measuredHeight ?: 0
        return composeView.measuredHeight
    }

    override fun handleCloseControls(save: Boolean, force: Boolean): Boolean {
+5 −6
Original line number Diff line number Diff line
@@ -1566,8 +1566,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
    }

    public void setGutsView(MenuItem item) {
        if (getGuts() != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
            getGuts().setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
        if (getGuts() != null
                && item.getGutsContent() instanceof NotificationGuts.GutsContent gutsContent) {
            getGuts().setGutsContent(gutsContent);
        }
    }

@@ -2604,10 +2605,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
            menuItem = provider.getLongpressMenuItem(mContext);
        }
        if (SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY == semanticAction
                && menuItem.getGutsView() instanceof NotificationConversationInfo) {
            NotificationConversationInfo info =
                    (NotificationConversationInfo) menuItem.getGutsView();
            info.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
                && menuItem.getGutsContent() instanceof NotificationConversationInfo gutsContent) {
            gutsContent.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);
        }
        doLongClickCallback(x, y, menuItem);
    }
+1 −6
Original line number Diff line number Diff line
@@ -135,11 +135,6 @@ public class NotificationGuts extends FrameLayout {
         * view on the lockscreen
         */
        boolean needsFalsingProtection();

        /**
         * Equivalent to {@link View#setAccessibilityDelegate(AccessibilityDelegate)}
         */
        void setAccessibilityDelegate(AccessibilityDelegate gutsContentAccessibilityDelegate);
    }

    public interface OnGutsClosedListener {
@@ -174,7 +169,7 @@ public class NotificationGuts extends FrameLayout {

    public void setGutsContent(GutsContent content) {
        content.setGutsParent(this);
        content.setAccessibilityDelegate(mGutsContentAccessibilityDelegate);
        content.getContentView().setAccessibilityDelegate(mGutsContentAccessibilityDelegate);
        mGutsContent = content;
        removeAllViews();
        addView(mGutsContent.getContentView());
Loading