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

Commit e5787f97 authored by Jordan Demeulenaere's avatar Jordan Demeulenaere
Browse files

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
parent 6a6b2bb5
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"
    }
}