From e5787f9787c6bf513e8a66808357ab43e90ead2e Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Mon, 25 Jul 2022 15:38:11 +0200 Subject: [PATCH] Move click handler from XML to ViewModel (1/2) This CL moves the click handler that is called when the "Got it" button of the (empty) PeopleSpaceActivity is clicked from XML to the PeopleViewModel. I missed it when I refactored this Activity in ag/19268008. Bug: 238993727 Test: Manual Change-Id: I7451589267aac5b07d0c979d5dde606e37915220 --- ...people_space_activity_no_conversations.xml | 1 - .../systemui/people/PeopleSpaceActivity.java | 40 +++++++----------- .../people/ui/view/PeopleViewBinder.kt | 22 ++++++---- .../people/ui/viewmodel/PeopleViewModel.kt | 42 ++++++++++++------- 4 files changed, 57 insertions(+), 48 deletions(-) diff --git a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml index e929169cfe3d9..a97c90c5e8aca 100644 --- a/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml +++ b/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml @@ -54,7 +54,6 @@ android:layout_height="wrap_content" android:layout_gravity="center" android:background="@drawable/rounded_bg_full_large_radius" - android:onClick="dismissActivity" android:text="@string/got_it" android:textColor="?androidprv:attr/textColorOnAccent" android:layout_marginBottom="60dp" diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java index e845aa85a121a..7cc95a158a140 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java @@ -22,7 +22,6 @@ import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID; import android.content.Intent; import android.os.Bundle; import android.util.Log; -import android.view.View; import android.view.ViewGroup; import androidx.activity.ComponentActivity; @@ -40,7 +39,6 @@ public class PeopleSpaceActivity extends ComponentActivity { private static final boolean DEBUG = PeopleSpaceUtils.DEBUG; private final PeopleViewModel.Factory mViewModelFactory; - private PeopleViewModel mViewModel; @Inject public PeopleSpaceActivity(PeopleViewModel.Factory viewModelFactory) { @@ -52,38 +50,32 @@ public class PeopleSpaceActivity extends ComponentActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setResult(RESULT_CANCELED); - mViewModel = new ViewModelProvider(this, mViewModelFactory).get(PeopleViewModel.class); + + PeopleViewModel viewModel = new ViewModelProvider(this, mViewModelFactory).get( + PeopleViewModel.class); // Update the widget ID coming from the intent. int widgetId = getIntent().getIntExtra(EXTRA_APPWIDGET_ID, INVALID_APPWIDGET_ID); - mViewModel.onWidgetIdChanged(widgetId); + viewModel.onWidgetIdChanged(widgetId); ViewGroup view = PeopleViewBinder.create(this); - PeopleViewBinder.bind(view, mViewModel, /* lifecycleOwner= */ this, - () -> { - finishActivity(); + PeopleViewBinder.bind(view, viewModel, /* lifecycleOwner= */ this, + (result) -> { + finishActivity(result); return null; }); setContentView(view); } - /** Finish activity with a successful widget configuration result. */ - private void finishActivity() { - if (DEBUG) Log.d(TAG, "Widget added!"); - setActivityResult(RESULT_OK); + private void finishActivity(PeopleViewModel.Result result) { + if (result instanceof PeopleViewModel.Result.Success) { + if (DEBUG) Log.d(TAG, "Widget added!"); + Intent data = ((PeopleViewModel.Result.Success) result).getData(); + setResult(RESULT_OK, data); + } else { + if (DEBUG) Log.d(TAG, "Activity dismissed with no widgets added!"); + setResult(RESULT_CANCELED); + } finish(); } - - /** Finish activity without choosing a widget. */ - public void dismissActivity(View v) { - if (DEBUG) Log.d(TAG, "Activity dismissed with no widgets added!"); - setResult(RESULT_CANCELED); - finish(); - } - - private void setActivityResult(int result) { - Intent resultValue = new Intent(); - resultValue.putExtra(EXTRA_APPWIDGET_ID, mViewModel.getAppWidgetId().getValue()); - setResult(result, resultValue); - } } diff --git a/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt b/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt index bc982cccaacdf..d8a429e5bb1a1 100644 --- a/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt @@ -41,7 +41,7 @@ import kotlinx.coroutines.launch /** A ViewBinder for [PeopleViewModel]. */ object PeopleViewBinder { - private const val TAG = "PeopleSpaceViewBinder" + private const val TAG = "PeopleViewBinder" /** * The [ViewOutlineProvider] used to clip the corner radius of the recent and priority lists. @@ -72,15 +72,15 @@ object PeopleViewBinder { view: ViewGroup, viewModel: PeopleViewModel, lifecycleOwner: LifecycleOwner, - onFinish: () -> Unit, + onResult: (PeopleViewModel.Result) -> Unit, ) { - // Call [onFinish] this activity when the ViewModel tells us so. + // Call [onResult] as soon as a result is available. lifecycleOwner.lifecycleScope.launch { lifecycleOwner.repeatOnLifecycle(CREATED) { - viewModel.isFinished.collect { isFinished -> - if (isFinished) { - viewModel.clearIsFinished() - onFinish() + viewModel.result.collect { result -> + if (result != null) { + viewModel.clearResult() + onResult(result) } } } @@ -104,7 +104,7 @@ object PeopleViewBinder { viewModel::onTileClicked, ) } else { - setNoConversationsContent(view) + setNoConversationsContent(view, viewModel::onUserJourneyCancelled) } } } @@ -119,7 +119,7 @@ object PeopleViewBinder { } } - private fun setNoConversationsContent(view: ViewGroup) { + private fun setNoConversationsContent(view: ViewGroup, onGotItClicked: () -> Unit) { // This should never happen. if (view.childCount > 1) { error("view has ${view.childCount} children, it should have maximum 1") @@ -140,6 +140,10 @@ object PeopleViewBinder { LayoutInflater.from(context) .inflate(R.layout.people_space_activity_no_conversations, /* root= */ view) + noConversationsView.findViewById(R.id.got_it_button).setOnClickListener { + onGotItClicked() + } + // The Tile preview has colorBackground as its background. Change it so it's different than // the activity's background. val item = noConversationsView.findViewById(android.R.id.background) diff --git a/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt b/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt index 17de991588b8f..0834a5ae75f6e 100644 --- a/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt @@ -16,8 +16,10 @@ package com.android.systemui.people.ui.viewmodel +import android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID import android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID import android.content.Context +import android.content.Intent import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider @@ -32,6 +34,7 @@ import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow /** * Models UI state for the people space, allowing the user to select which conversation should be @@ -49,7 +52,7 @@ class PeopleViewModel( * reactive and you have to manually call [onTileRefreshRequested] to refresh the tiles. */ private val _priorityTiles = MutableStateFlow(priorityTiles()) - val priorityTiles: Flow> = _priorityTiles + val priorityTiles: Flow> = _priorityTiles.asStateFlow() /** * The list of the priority tiles/conversations. @@ -58,15 +61,15 @@ class PeopleViewModel( * reactive and you have to manually call [onTileRefreshRequested] to refresh the tiles. */ private val _recentTiles = MutableStateFlow(recentTiles()) - val recentTiles: Flow> = _recentTiles + val recentTiles: Flow> = _recentTiles.asStateFlow() /** The ID of the widget currently being edited/added. */ private val _appWidgetId = MutableStateFlow(INVALID_APPWIDGET_ID) - val appWidgetId: StateFlow = _appWidgetId + val appWidgetId: StateFlow = _appWidgetId.asStateFlow() - /** Whether the user journey is complete. */ - private val _isFinished = MutableStateFlow(false) - val isFinished: StateFlow = _isFinished + /** The result of this user journey. */ + private val _result = MutableStateFlow(null) + val result: StateFlow = _result.asStateFlow() /** Refresh the [priorityTiles] and [recentTiles]. */ fun onTileRefreshRequested() { @@ -79,22 +82,28 @@ class PeopleViewModel( _appWidgetId.value = widgetId } - /** Clear [isFinished], setting it to false. */ - fun clearIsFinished() { - _isFinished.value = false + /** Clear [result], setting it to null. */ + fun clearResult() { + _result.value = null } /** Called when a tile is clicked. */ fun onTileClicked(tile: PeopleTileViewModel) { + val widgetId = _appWidgetId.value if (PeopleSpaceUtils.DEBUG) { Log.d( TAG, - "Put ${tile.username}'s shortcut ID: ${tile.key.shortcutId} for widget ID: " + - _appWidgetId.value + "Put ${tile.username}'s shortcut ID: ${tile.key.shortcutId} for widget ID $widgetId" ) } - widgetRepository.setWidgetTile(_appWidgetId.value, tile.key) - _isFinished.value = true + widgetRepository.setWidgetTile(widgetId, tile.key) + _result.value = + Result.Success(Intent().apply { putExtra(EXTRA_APPWIDGET_ID, appWidgetId.value) }) + } + + /** Called when this user journey is cancelled. */ + fun onUserJourneyCancelled() { + _result.value = Result.Cancelled } private fun priorityTiles(): List { @@ -143,7 +152,12 @@ class PeopleViewModel( } } + sealed class Result { + class Success(val data: Intent) : Result() + object Cancelled : Result() + } + companion object { - private const val TAG = "PeopleSpaceViewModel" + private const val TAG = "PeopleViewModel" } }