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

Commit 433e13b4 authored by Santiago Etchebehere's avatar Santiago Etchebehere
Browse files

Handle the case of no grid options available

Fixes: 271343879
Test: manually checked with a fake empty URI and added
unit test in GridInteractorTest to test new behavior
Change-Id: I95918b5a73711efb137cbcc35cea1a36324f25a6

Change-Id: I25b83eb5e31cbd0d27e1f599fc5aaa6018fdb20a
parent 5577bacd
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ public class GridOptionsManager implements CustomizationManager<GridOption> {

    private final LauncherGridOptionsProvider mProvider;
    private final ThemesUserEventLogger mEventLogger;
    private int mGridOptionSize = -1;

    /** Returns the {@link GridOptionsManager} instance. */
    public static GridOptionsManager getInstance(Context context) {
@@ -73,16 +74,17 @@ public class GridOptionsManager implements CustomizationManager<GridOption> {

    @Override
    public boolean isAvailable() {
        int gridOptionSize = 0;
        if (mGridOptionSize < 0) {
            try {
            gridOptionSize = sExecutorService.submit(() -> {
                mGridOptionSize = sExecutorService.submit(() -> {
                    List<GridOption> gridOptions = mProvider.fetch(/* reload= */true);
                    return gridOptions == null ? 0 : gridOptions.size();
                }).get();
            } catch (InterruptedException | ExecutionException e) {
                Log.w(TAG, "could not get gridOptionSize", e);
            }
        return gridOptionSize > 1 && mProvider.areGridsAvailable();
        }
        return mGridOptionSize > 1 && mProvider.areGridsAvailable();
    }

    @Override
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ public class GridSectionController implements CustomizationSectionController<Gri

    @Override
    public void release() {
        if (mIsRevampedUiEnabled) {
        if (mIsRevampedUiEnabled && mGridOptionsManager.isAvailable()) {
            mGridOptionsManager.getOptionChangeObservable(/* handler= */ null).removeObserver(
                    mOptionChangeObserver
            );
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ public class LauncherGridOptionsProvider {

    /**
     * Returns an observable that receives a new value each time that the grid options are changed.
     * Do not call if {@link #areGridsAvailable()} returns false
     */
    public LiveData<Object> getOptionChangeObservable(
            @Nullable Handler handler) {
+7 −2
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext

interface GridRepository {
    val optionChanges: Flow<Unit>
    suspend fun isAvailable(): Boolean
    fun getOptionChanges(): Flow<Unit>
    suspend fun getOptions(): GridOptionItemsModel
}

@@ -45,7 +46,11 @@ class GridRepositoryImpl(
    private val backgroundDispatcher: CoroutineDispatcher,
) : GridRepository {

    override val optionChanges: Flow<Unit> =
    override suspend fun isAvailable(): Boolean {
        return withContext(backgroundDispatcher) { manager.isAvailable }
    }

    override fun getOptionChanges(): Flow<Unit> =
        manager.getOptionChangeObservable(/* handler= */ null).asFlow().map {}

    private val selectedOption = MutableStateFlow<GridOption?>(null)
+27 −16
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import javax.inject.Provider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
@@ -34,22 +37,30 @@ class GridInteractor(
    private val snapshotRestorer: Provider<GridSnapshotRestorer>,
) {
    val options: Flow<GridOptionItemsModel> =
        flow { emit(repository.isAvailable()) }
            .flatMapLatest { isAvailable ->
                if (isAvailable) {
                    // this upstream flow tells us each time the options are changed.
        repository.optionChanges
            // when we start, we pretend the options _just_ changed. This way, we load something as
            // soon as possible into the flow so it's ready by the time the first observer starts to
            // observe.
                    repository
                        .getOptionChanges()
                        // when we start, we pretend the options _just_ changed. This way, we load
                        // something as soon as possible into the flow so it's ready by the time the
                        // first observer starts to observe.
                        .onStart { emit(Unit) }
                        // each time the options changed, we load them.
                        .map { reload() }
                        // we place the loaded options in a SharedFlow so downstream observers all
            // share the same flow and don't trigger a new one each time they want to start
            // observing.
                        // share the same flow and don't trigger a new one each time they want to
                        // start observing.
                        .shareIn(
                            scope = applicationScope,
                            started = SharingStarted.WhileSubscribed(),
                            replay = 1,
                        )
                } else {
                    emptyFlow()
                }
            }

    suspend fun setSelectedOption(model: GridOptionItemModel) {
        model.onSelected.invoke()
Loading