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

Commit 23f85533 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update app widget size when resized" into main

parents 34579ccc 3267e525
Loading
Loading
Loading
Loading
+40 −1
Original line number Diff line number Diff line
@@ -17,19 +17,30 @@
package com.android.systemui.communal.ui.binder

import android.content.Context
import android.os.Bundle
import android.util.SizeF
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.ui.unit.IntSize
import androidx.core.view.doOnLayout
import com.android.app.tracing.coroutines.flow.flowOn
import com.android.app.tracing.coroutines.launch
import com.android.systemui.Flags.communalWidgetResizing
import com.android.systemui.common.ui.view.onLayoutChanged
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.util.WidgetViewFactory
import com.android.systemui.util.kotlin.DisposableHandles
import com.android.systemui.util.kotlin.toDp
import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged

object CommunalAppWidgetHostViewBinder {
    private const val TAG = "CommunalAppWidgetHostViewBinder"
@@ -37,9 +48,11 @@ object CommunalAppWidgetHostViewBinder {
    fun bind(
        context: Context,
        applicationScope: CoroutineScope,
        mainContext: CoroutineContext,
        backgroundContext: CoroutineContext,
        container: FrameLayout,
        model: CommunalContentModel.WidgetContent.Widget,
        size: SizeF,
        size: SizeF?,
        factory: WidgetViewFactory,
    ): DisposableHandle {
        val disposables = DisposableHandles()
@@ -49,6 +62,22 @@ object CommunalAppWidgetHostViewBinder {
                val widget = factory.createWidget(context, model, size)
                waitForLayout(container)
                container.post { container.setView(widget) }
                if (communalWidgetResizing()) {
                    // Update the app widget size in the background.
                    launch("$TAG#updateSize", backgroundContext) {
                        container.sizeFlow().flowOn(mainContext).distinctUntilChanged().collect {
                            (width, height) ->
                            widget.updateAppWidgetSize(
                                /* newOptions = */ Bundle(),
                                /* minWidth = */ width,
                                /* minHeight = */ height,
                                /* maxWidth = */ width,
                                /* maxHeight = */ height,
                                /* ignorePadding = */ true,
                            )
                        }
                    }
                }
            }

        disposables += DisposableHandle { loadingJob.cancel() }
@@ -69,3 +98,13 @@ private fun ViewGroup.setView(view: View) {
    (view.parent as? ViewGroup)?.removeView(view)
    addView(view)
}

private fun View.sizeAsDp(): IntSize = IntSize(width.toDp(context), height.toDp(context))

private fun View.sizeFlow(): Flow<IntSize> = conflatedCallbackFlow {
    if (isLaidOut && !isLayoutRequested) {
        trySend(sizeAsDp())
    }
    val disposable = onLayoutChanged { trySend(sizeAsDp()) }
    awaitClose { disposable.dispose() }
}
+10 −2
Original line number Diff line number Diff line
@@ -25,13 +25,17 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.Flags.communalWidgetResizing
import com.android.systemui.communal.domain.model.CommunalContentModel
import com.android.systemui.communal.ui.binder.CommunalAppWidgetHostViewBinder
import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
import com.android.systemui.communal.util.WidgetViewFactory
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dagger.qualifiers.UiBackground
import com.android.systemui.res.R
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DisposableHandle

@@ -39,6 +43,8 @@ class CommunalAppWidgetSection
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    @Main private val mainContext: CoroutineContext,
    @UiBackground private val backgroundContext: CoroutineContext,
    private val factory: WidgetViewFactory,
) {

@@ -76,10 +82,12 @@ constructor(
                            context = context,
                            container = this,
                            model = model,
                            size = size,
                            size = if (!communalWidgetResizing()) size else null,
                            factory = factory,
                            applicationScope = applicationScope,
                        )
                            mainContext = mainContext,
                            backgroundContext = backgroundContext,
                        ),
                    )

                    accessibilityDelegate = viewModel.widgetAccessibilityDelegate
+11 −9
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ constructor(
    suspend fun createWidget(
        context: Context,
        model: CommunalContentModel.WidgetContent.Widget,
        size: SizeF,
        size: SizeF?,
    ): CommunalAppWidgetHostView =
        withContext("$TAG#createWidget", uiBgContext) {
            val view =
@@ -54,6 +54,7 @@ constructor(
            // Instead of setting the view as the listener directly, we wrap the view in a delegate
            // which ensures the callbacks always get called on the main thread.
            appWidgetHost.setListener(model.appWidgetId, listenerFactory.create(view))
            if (size != null) {
                view.updateAppWidgetSize(
                    /* newOptions = */ Bundle(),
                    /* minWidth = */ size.width.toInt(),
@@ -62,6 +63,7 @@ constructor(
                    /* maxHeight = */ size.height.toInt(),
                    /* ignorePadding = */ true,
                )
            }
            view
        }