Merge "ViewModel+Binder for NotificationStackScrollLayout" into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a987ab2837
@@ -33,12 +33,9 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController
|
||||
import com.android.systemui.statusbar.phone.NotificationIconContainer
|
||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
|
||||
import com.android.systemui.util.kotlin.getValue
|
||||
import dagger.Lazy
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* Controller class for [NotificationShelf]. This implementation serves as a temporary wrapper
|
||||
@@ -47,39 +44,12 @@ import kotlinx.coroutines.flow.onEach
|
||||
* removed, this class can go away and the ViewBinder can be used directly.
|
||||
*/
|
||||
@CentralSurfacesScope
|
||||
class NotificationShelfViewBinderWrapperControllerImpl
|
||||
@Inject
|
||||
constructor(
|
||||
private val shelf: NotificationShelf,
|
||||
private val viewModel: NotificationShelfViewModel,
|
||||
featureFlags: FeatureFlags,
|
||||
private val falsingManager: FalsingManager,
|
||||
hostControllerLazy: Lazy<NotificationStackScrollLayoutController>,
|
||||
private val notificationIconAreaController: NotificationIconAreaController,
|
||||
) : NotificationShelfController {
|
||||
|
||||
private val hostController: NotificationStackScrollLayoutController by hostControllerLazy
|
||||
class NotificationShelfViewBinderWrapperControllerImpl @Inject constructor() :
|
||||
NotificationShelfController {
|
||||
|
||||
override val view: NotificationShelf
|
||||
get() = unsupported
|
||||
|
||||
init {
|
||||
shelf.apply {
|
||||
setRefactorFlagEnabled(featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR))
|
||||
useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
|
||||
setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
|
||||
}
|
||||
}
|
||||
|
||||
fun init() {
|
||||
NotificationShelfViewBinder.bind(viewModel, shelf, falsingManager)
|
||||
hostController.setShelf(shelf)
|
||||
hostController.setOnNotificationRemovedListener { child, _ ->
|
||||
view.requestRoundnessResetFor(child)
|
||||
}
|
||||
notificationIconAreaController.setShelfIcons(shelf.shelfIcons)
|
||||
}
|
||||
|
||||
override val intrinsicHeight: Int
|
||||
get() = unsupported
|
||||
|
||||
@@ -99,21 +69,32 @@ constructor(
|
||||
get() = NotificationShelfController.throwIllegalFlagStateError(expected = true)
|
||||
}
|
||||
|
||||
/** Binds a [NotificationShelf] to its backend. */
|
||||
/** Binds a [NotificationShelf] to its [view model][NotificationShelfViewModel]. */
|
||||
object NotificationShelfViewBinder {
|
||||
fun bind(
|
||||
viewModel: NotificationShelfViewModel,
|
||||
shelf: NotificationShelf,
|
||||
viewModel: NotificationShelfViewModel,
|
||||
falsingManager: FalsingManager,
|
||||
featureFlags: FeatureFlags,
|
||||
notificationIconAreaController: NotificationIconAreaController,
|
||||
) {
|
||||
ActivatableNotificationViewBinder.bind(viewModel, shelf, falsingManager)
|
||||
shelf.repeatWhenAttached {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
viewModel.canModifyColorOfNotifications
|
||||
.onEach(shelf::setCanModifyColorOfNotifications)
|
||||
.launchIn(this)
|
||||
viewModel.isClickable.onEach(shelf::setCanInteract).launchIn(this)
|
||||
registerViewListenersWhileAttached(shelf, viewModel)
|
||||
shelf.apply {
|
||||
setRefactorFlagEnabled(true)
|
||||
useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
|
||||
setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
|
||||
// TODO(278765923): Replace with eventual NotificationIconContainerViewBinder#bind()
|
||||
notificationIconAreaController.setShelfIcons(shelfIcons)
|
||||
repeatWhenAttached {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
launch {
|
||||
viewModel.canModifyColorOfNotifications.collect(
|
||||
::setCanModifyColorOfNotifications
|
||||
)
|
||||
}
|
||||
launch { viewModel.isClickable.collect(::setCanInteract) }
|
||||
registerViewListenersWhileAttached(shelf, viewModel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2839,6 +2839,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
* @param listener callback for notification removed
|
||||
*/
|
||||
public void setOnNotificationRemovedListener(OnNotificationRemovedListener listener) {
|
||||
NotificationShelfController.assertRefactorFlagDisabled(mAmbientState.getFeatureFlags());
|
||||
mOnNotificationRemovedListener = listener;
|
||||
}
|
||||
|
||||
@@ -2852,10 +2853,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
|
||||
if (!mChildTransferInProgress) {
|
||||
onViewRemovedInternal(expandableView, this);
|
||||
}
|
||||
if (mOnNotificationRemovedListener != null) {
|
||||
mOnNotificationRemovedListener.onNotificationRemoved(
|
||||
expandableView,
|
||||
mChildTransferInProgress);
|
||||
if (mAmbientState.getFeatureFlags().isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
|
||||
mShelf.requestRoundnessResetFor(expandableView);
|
||||
} else {
|
||||
if (mOnNotificationRemovedListener != null) {
|
||||
mOnNotificationRemovedListener.onNotificationRemoved(
|
||||
expandableView,
|
||||
mChildTransferInProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,14 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGuts;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationSnooze;
|
||||
import com.android.systemui.statusbar.notification.stack.ui.viewbinder.NotificationListViewBinder;
|
||||
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
|
||||
import com.android.systemui.statusbar.phone.ScrimController;
|
||||
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
@@ -122,16 +125,17 @@ import com.android.systemui.tuner.TunerService;
|
||||
import com.android.systemui.util.Compile;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import kotlin.Unit;
|
||||
|
||||
/**
|
||||
* Controller for {@link NotificationStackScrollLayout}.
|
||||
*/
|
||||
@@ -151,6 +155,8 @@ public class NotificationStackScrollLayoutController {
|
||||
private final ConfigurationController mConfigurationController;
|
||||
private final ZenModeController mZenModeController;
|
||||
private final MetricsLogger mMetricsLogger;
|
||||
private final Optional<NotificationListViewModel> mViewModel;
|
||||
|
||||
private final DumpManager mDumpManager;
|
||||
private final FalsingCollector mFalsingCollector;
|
||||
private final FalsingManager mFalsingManager;
|
||||
@@ -175,6 +181,8 @@ public class NotificationStackScrollLayoutController {
|
||||
private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
|
||||
private final StackStateLogger mStackStateLogger;
|
||||
private final NotificationStackScrollLogger mLogger;
|
||||
private final NotificationIconAreaController mNotifIconAreaController;
|
||||
|
||||
private final GroupExpansionManager mGroupExpansionManager;
|
||||
private final NotifPipelineFlags mNotifPipelineFlags;
|
||||
private final SeenNotificationsProvider mSeenNotificationsProvider;
|
||||
@@ -642,6 +650,7 @@ public class NotificationStackScrollLayoutController {
|
||||
KeyguardBypassController keyguardBypassController,
|
||||
ZenModeController zenModeController,
|
||||
NotificationLockscreenUserManager lockscreenUserManager,
|
||||
Optional<NotificationListViewModel> nsslViewModel,
|
||||
MetricsLogger metricsLogger,
|
||||
DumpManager dumpManager,
|
||||
FalsingCollector falsingCollector,
|
||||
@@ -665,6 +674,7 @@ public class NotificationStackScrollLayoutController {
|
||||
StackStateLogger stackLogger,
|
||||
NotificationStackScrollLogger logger,
|
||||
NotificationStackSizeCalculator notificationStackSizeCalculator,
|
||||
NotificationIconAreaController notifIconAreaController,
|
||||
FeatureFlags featureFlags,
|
||||
NotificationTargetsHelper notificationTargetsHelper,
|
||||
SecureSettings secureSettings,
|
||||
@@ -686,6 +696,7 @@ public class NotificationStackScrollLayoutController {
|
||||
mKeyguardBypassController = keyguardBypassController;
|
||||
mZenModeController = zenModeController;
|
||||
mLockscreenUserManager = lockscreenUserManager;
|
||||
mViewModel = nsslViewModel;
|
||||
mMetricsLogger = metricsLogger;
|
||||
mDumpManager = dumpManager;
|
||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||
@@ -707,6 +718,7 @@ public class NotificationStackScrollLayoutController {
|
||||
mVisibilityLocationProviderDelegator = visibilityLocationProviderDelegator;
|
||||
mSeenNotificationsProvider = seenNotificationsProvider;
|
||||
mShadeController = shadeController;
|
||||
mNotifIconAreaController = notifIconAreaController;
|
||||
mFeatureFlags = featureFlags;
|
||||
mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
|
||||
mNotificationTargetsHelper = notificationTargetsHelper;
|
||||
@@ -820,6 +832,10 @@ public class NotificationStackScrollLayoutController {
|
||||
|
||||
mGroupExpansionManager.registerGroupExpansionChangeListener(
|
||||
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
|
||||
|
||||
mViewModel.ifPresent(
|
||||
vm -> NotificationListViewBinder
|
||||
.bind(mView, vm, mFalsingManager, mFeatureFlags, mNotifIconAreaController));
|
||||
}
|
||||
|
||||
private boolean isInVisibleLocation(NotificationEntry entry) {
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.stack.ui.viewbinder
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.plugins.FalsingManager
|
||||
import com.android.systemui.statusbar.NotificationShelf
|
||||
import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinder
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
|
||||
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController
|
||||
|
||||
/** Binds a [NotificationStackScrollLayout] to its [view model][NotificationListViewModel]. */
|
||||
object NotificationListViewBinder {
|
||||
@JvmStatic
|
||||
fun bind(
|
||||
view: NotificationStackScrollLayout,
|
||||
viewModel: NotificationListViewModel,
|
||||
falsingManager: FalsingManager,
|
||||
featureFlags: FeatureFlags,
|
||||
iconAreaController: NotificationIconAreaController,
|
||||
) {
|
||||
val shelf =
|
||||
LayoutInflater.from(view.context)
|
||||
.inflate(R.layout.status_bar_notification_shelf, view, false) as NotificationShelf
|
||||
NotificationShelfViewBinder.bind(
|
||||
shelf,
|
||||
viewModel.shelf,
|
||||
falsingManager,
|
||||
featureFlags,
|
||||
iconAreaController
|
||||
)
|
||||
view.setShelf(shelf)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.stack.ui.viewmodel
|
||||
|
||||
import com.android.systemui.flags.FeatureFlags
|
||||
import com.android.systemui.flags.Flags
|
||||
import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import java.util.Optional
|
||||
import javax.inject.Provider
|
||||
|
||||
/** ViewModel for the list of notifications. */
|
||||
class NotificationListViewModel(
|
||||
val shelf: NotificationShelfViewModel,
|
||||
)
|
||||
|
||||
@Module
|
||||
object NotificationListViewModelModule {
|
||||
@JvmStatic
|
||||
@Provides
|
||||
fun maybeProvideViewModel(
|
||||
featureFlags: FeatureFlags,
|
||||
shelfViewModel: Provider<NotificationShelfViewModel>,
|
||||
): Optional<NotificationListViewModel> =
|
||||
if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
|
||||
Optional.of(NotificationListViewModel(shelfViewModel.get()))
|
||||
} else {
|
||||
Optional.empty()
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfC
|
||||
import com.android.systemui.statusbar.notification.row.ui.viewmodel.ActivatableNotificationViewModelModule;
|
||||
import com.android.systemui.statusbar.notification.shelf.ui.viewbinder.NotificationShelfViewBinderWrapperControllerImpl;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
|
||||
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModelModule;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarBoundsProvider;
|
||||
@@ -87,7 +88,10 @@ import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
@Module(subcomponents = StatusBarFragmentComponent.class,
|
||||
includes = { ActivatableNotificationViewModelModule.class })
|
||||
includes = {
|
||||
ActivatableNotificationViewModelModule.class,
|
||||
NotificationListViewModelModule.class,
|
||||
})
|
||||
public abstract class StatusBarViewModule {
|
||||
|
||||
public static final String SHADE_HEADER = "large_screen_shade_header";
|
||||
@@ -117,9 +121,7 @@ public abstract class StatusBarViewModule {
|
||||
NotificationShelfComponent.Builder notificationShelfComponentBuilder,
|
||||
NotificationShelf notificationShelf) {
|
||||
if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
|
||||
NotificationShelfViewBinderWrapperControllerImpl impl = newImpl.get();
|
||||
impl.init();
|
||||
return impl;
|
||||
return newImpl.get();
|
||||
} else {
|
||||
NotificationShelfComponent component = notificationShelfComponentBuilder
|
||||
.notificationShelf(notificationShelf)
|
||||
|
||||
@@ -72,9 +72,11 @@ import com.android.systemui.statusbar.notification.collection.render.SectionHead
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
|
||||
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
|
||||
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
|
||||
import com.android.systemui.statusbar.phone.CentralSurfaces;
|
||||
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
|
||||
import com.android.systemui.statusbar.phone.KeyguardBypassController;
|
||||
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
|
||||
import com.android.systemui.statusbar.phone.ScrimController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||
@@ -92,6 +94,8 @@ import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Tests for {@link NotificationStackScrollLayoutController}.
|
||||
*/
|
||||
@@ -138,6 +142,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
||||
@Mock private FeatureFlags mFeatureFlags;
|
||||
@Mock private NotificationTargetsHelper mNotificationTargetsHelper;
|
||||
@Mock private SecureSettings mSecureSettings;
|
||||
@Mock private NotificationIconAreaController mIconAreaController;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor;
|
||||
@@ -430,6 +435,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
||||
mKeyguardBypassController,
|
||||
mZenModeController,
|
||||
mNotificationLockscreenUserManager,
|
||||
Optional.<NotificationListViewModel>empty(),
|
||||
mMetricsLogger,
|
||||
mDumpManager,
|
||||
new FalsingCollectorFake(),
|
||||
@@ -453,6 +459,7 @@ public class NotificationStackScrollLayoutControllerTest extends SysuiTestCase {
|
||||
mStackLogger,
|
||||
mLogger,
|
||||
mNotificationStackSizeCalculator,
|
||||
mIconAreaController,
|
||||
mFeatureFlags,
|
||||
mNotificationTargetsHelper,
|
||||
mSecureSettings,
|
||||
|
||||
Reference in New Issue
Block a user