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

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

Merge "Move click handler from XML to ViewModel (1/2)" into tm-qpr-dev

parents 9ef43b2f e5787f97
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -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"
+16 −24
Original line number Diff line number Diff line
@@ -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() {
    private void finishActivity(PeopleViewModel.Result result) {
        if (result instanceof PeopleViewModel.Result.Success) {
            if (DEBUG) Log.d(TAG, "Widget added!");
        setActivityResult(RESULT_OK);
        finish();
    }

    /** Finish activity without choosing a widget. */
    public void dismissActivity(View v) {
            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();
        }

    private void setActivityResult(int result) {
        Intent resultValue = new Intent();
        resultValue.putExtra(EXTRA_APPWIDGET_ID, mViewModel.getAppWidgetId().getValue());
        setResult(result, resultValue);
        finish();
    }
}
+13 −9
Original line number Diff line number Diff line
@@ -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)
+28 −14
Original line number Diff line number Diff line
@@ -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"
    }
}