Loading packages/SystemUI/res/layout/people_space_activity_no_conversations.xml +0 −1 Original line number Diff line number Diff line Loading @@ -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" Loading packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java +16 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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(); } } packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt +13 −9 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) } } } Loading @@ -104,7 +104,7 @@ object PeopleViewBinder { viewModel::onTileClicked, ) } else { setNoConversationsContent(view) setNoConversationsContent(view, viewModel::onUserJourneyCancelled) } } } Loading @@ -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") Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt +28 −14 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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. Loading @@ -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() { Loading @@ -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> { Loading Loading @@ -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" } } Loading
packages/SystemUI/res/layout/people_space_activity_no_conversations.xml +0 −1 Original line number Diff line number Diff line Loading @@ -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" Loading
packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java +16 −24 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading @@ -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(); } }
packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt +13 −9 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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) } } } Loading @@ -104,7 +104,7 @@ object PeopleViewBinder { viewModel::onTileClicked, ) } else { setNoConversationsContent(view) setNoConversationsContent(view, viewModel::onUserJourneyCancelled) } } } Loading @@ -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") Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt +28 −14 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading @@ -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. Loading @@ -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() { Loading @@ -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> { Loading Loading @@ -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" } }