Merge "Move click handler from XML to ViewModel (1/2)" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
28aa7dd51f
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<View>(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<LinearLayout>(android.R.id.background)
|
||||
|
||||
@@ -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<List<PeopleTileViewModel>> = _priorityTiles
|
||||
val priorityTiles: Flow<List<PeopleTileViewModel>> = _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<List<PeopleTileViewModel>> = _recentTiles
|
||||
val recentTiles: Flow<List<PeopleTileViewModel>> = _recentTiles.asStateFlow()
|
||||
|
||||
/** The ID of the widget currently being edited/added. */
|
||||
private val _appWidgetId = MutableStateFlow(INVALID_APPWIDGET_ID)
|
||||
val appWidgetId: StateFlow<Int> = _appWidgetId
|
||||
val appWidgetId: StateFlow<Int> = _appWidgetId.asStateFlow()
|
||||
|
||||
/** Whether the user journey is complete. */
|
||||
private val _isFinished = MutableStateFlow(false)
|
||||
val isFinished: StateFlow<Boolean> = _isFinished
|
||||
/** The result of this user journey. */
|
||||
private val _result = MutableStateFlow<Result?>(null)
|
||||
val result: StateFlow<Result?> = _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<PeopleTileViewModel> {
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user