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

Commit 5818342a authored by Jordan Demeulenaere's avatar Jordan Demeulenaere Committed by Android (Google) Code Review
Browse files

Merge "Fix flicker of QS footer actions when restarting SystemUI (1/2)" into udc-dev

parents 029eb856 3b978757
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
    private final QSLogger mLogger;
    private final FooterActionsController mFooterActionsController;
    private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
    private final FooterActionsViewBinder mFooterActionsViewBinder;
    private final ListeningAndVisibilityLifecycleOwner mListeningAndVisibilityLifecycleOwner;
    private boolean mShowCollapsedOnKeyguard;
    private boolean mLastKeyguardAndExpanded;
@@ -177,6 +178,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
            DumpManager dumpManager, QSLogger qsLogger,
            FooterActionsController footerActionsController,
            FooterActionsViewModel.Factory footerActionsViewModelFactory,
            FooterActionsViewBinder footerActionsViewBinder,
            LargeScreenShadeInterpolator largeScreenShadeInterpolator,
            FeatureFlags featureFlags) {
        mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
@@ -193,6 +195,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
        mDumpManager = dumpManager;
        mFooterActionsController = footerActionsController;
        mFooterActionsViewModelFactory = footerActionsViewModelFactory;
        mFooterActionsViewBinder = footerActionsViewBinder;
        mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
    }

@@ -285,7 +288,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca

        if (!ComposeFacade.INSTANCE.isComposeAvailable()) {
            Log.d(TAG, "Binding the View implementation of the QS footer actions");
            FooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
            mFooterActionsViewBinder.bind(footerActionsView, mQSFooterActionsViewModel,
                    mListeningAndVisibilityLifecycleOwner);
            return;
        }
+9 −4
Original line number Diff line number Diff line
@@ -33,27 +33,27 @@ import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.R
import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.people.ui.view.PeopleViewBinder.bind
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsForegroundServicesButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsSecurityButtonViewModel
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

/** A ViewBinder for [FooterActionsViewBinder]. */
object FooterActionsViewBinder {
@SysUISingleton
class FooterActionsViewBinder @Inject constructor() {
    /** Create a view that can later be [bound][bind] to a [FooterActionsViewModel]. */
    @JvmStatic
    fun create(context: Context): LinearLayout {
        return LayoutInflater.from(context).inflate(R.layout.footer_actions, /* root= */ null)
            as LinearLayout
    }

    /** Bind [view] to [viewModel]. */
    @JvmStatic
    fun bind(
        view: LinearLayout,
        viewModel: FooterActionsViewModel,
@@ -98,6 +98,11 @@ object FooterActionsViewBinder {
        var previousForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null
        var previousUserSwitcher: FooterActionsButtonViewModel? = null

        // Set the initial visibility on the View directly so that we don't briefly show it for a
        // few frames before [viewModel.isVisible] is collected.
        view.isInvisible = !viewModel.isVisible.value

        // Listen for ViewModel updates when the View is attached.
        view.repeatWhenAttached {
            val attachedScope = this.lifecycleScope

+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ class FooterActionsViewModel(
     * the UI should still participate to the layout it is included in (i.e. in the View world it
     * should be INVISIBLE, not GONE).
     */
    private val _isVisible = MutableStateFlow(true)
    private val _isVisible = MutableStateFlow(false)
    val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()

    /** The alpha the UI rendering this ViewModel should have. */
+3 −1
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
    @Mock private QSSquishinessController mSquishinessController;
    @Mock private FooterActionsViewModel mFooterActionsViewModel;
    @Mock private FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
    @Mock private FooterActionsViewBinder mFooterActionsViewBinder;
    @Mock private LargeScreenShadeInterpolator mLargeScreenShadeInterpolator;
    @Mock private FeatureFlags mFeatureFlags;
    private View mQsFragmentView;
@@ -558,6 +559,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
                mock(QSLogger.class),
                mock(FooterActionsController.class),
                mFooterActionsViewModelFactory,
                mFooterActionsViewBinder,
                mLargeScreenShadeInterpolator,
                mFeatureFlags);
    }
@@ -584,7 +586,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
        when(mQsFragmentView.findViewById(R.id.header)).thenReturn(mHeader);
        when(mQsFragmentView.findViewById(android.R.id.edit)).thenReturn(new View(mContext));
        when(mQsFragmentView.findViewById(R.id.qs_footer_actions)).thenAnswer(
                invocation -> FooterActionsViewBinder.create(mContext));
                invocation -> new FooterActionsViewBinder().create(mContext));
    }

    private void setUpInflater() {
+3 −3
Original line number Diff line number Diff line
@@ -376,13 +376,13 @@ class FooterActionsViewModelTest : SysuiTestCase() {
    @Test
    fun isVisible() {
        val underTest = utils.footerActionsViewModel()
        assertThat(underTest.isVisible.value).isTrue()

        underTest.onVisibilityChangeRequested(visible = false)
        assertThat(underTest.isVisible.value).isFalse()

        underTest.onVisibilityChangeRequested(visible = true)
        assertThat(underTest.isVisible.value).isTrue()

        underTest.onVisibilityChangeRequested(visible = false)
        assertThat(underTest.isVisible.value).isFalse()
    }

    @Test