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

Verified Commit 4bbc9166 authored by Fahim M. Choudhury's avatar Fahim M. Choudhury
Browse files

refactor: extract usecases from SearchViewModelV2 to orchestrate cleanApk and PlayStore search

parent 9c54d2b3
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.data.search

import android.content.Context
import com.aurora.gplayapi.data.models.App
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.application.utils.toApplication
import foundation.e.apps.domain.search.PlayStoreAppMapper
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class PlayStoreAppMapperImpl @Inject constructor(
    @ApplicationContext private val context: Context,
) : PlayStoreAppMapper {
    override fun map(app: App): Application {
        return app.toApplication(context)
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -23,9 +23,11 @@ import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import foundation.e.apps.data.search.CleanApkSearchPagingRepository
import foundation.e.apps.data.search.PlayStoreAppMapperImpl
import foundation.e.apps.data.search.PlayStoreWebSearch
import foundation.e.apps.data.search.PlayStoreWebSearchImpl
import foundation.e.apps.data.search.SearchPagingRepository
import foundation.e.apps.domain.search.PlayStoreAppMapper
import javax.inject.Singleton

@Module
@@ -42,4 +44,10 @@ abstract class SearchPagingModule {
    abstract fun bindPlayStoreWebSearch(
        impl: PlayStoreWebSearchImpl
    ): PlayStoreWebSearch

    @Binds
    @Singleton
    abstract fun bindPlayStoreAppMapper(
        impl: PlayStoreAppMapperImpl
    ): PlayStoreAppMapper
}
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.domain.search

import androidx.paging.PagingData
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.search.CleanApkSearchParams
import foundation.e.apps.data.search.SearchPagingRepository
import foundation.e.apps.ui.search.v2.SearchTabType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapLatest
import javax.inject.Inject

class CleanApkSearchPagingUseCase @Inject constructor(
    private val searchPagingRepository: SearchPagingRepository,
) {
    @OptIn(ExperimentalCoroutinesApi::class)
    operator fun invoke(
        requests: Flow<SearchRequest?>,
        tab: SearchTabType,
        appSource: String,
        appType: String,
    ): Flow<PagingData<Application>> {
        return requests
            .filterNotNull()
            .mapLatest { request ->
                if (!request.visibleTabs.contains(tab) || request.query.isBlank()) {
                    flowOf(PagingData.empty<Application>())
                } else {
                    searchPagingRepository.cleanApkSearch(
                        CleanApkSearchParams(
                            keyword = request.query,
                            appSource = appSource,
                            appType = appType,
                        )
                    )
                }
            }
            .flatMapLatest { it }
    }
}
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.domain.search

import com.aurora.gplayapi.data.models.App
import foundation.e.apps.data.application.data.Application

interface PlayStoreAppMapper {
    fun map(app: App): Application
}
+64 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2026 e Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

package foundation.e.apps.domain.search

import androidx.paging.PagingData
import androidx.paging.map
import com.aurora.gplayapi.data.models.App
import foundation.e.apps.data.application.data.Application
import foundation.e.apps.data.search.PlayStorePagingRepository
import foundation.e.apps.ui.search.v2.SearchTabType
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import javax.inject.Inject

class PlayStoreSearchPagingUseCase @Inject constructor(
    private val playStorePagingRepository: PlayStorePagingRepository,
    private val playStoreAppMapper: PlayStoreAppMapper,
) {
    @OptIn(ExperimentalCoroutinesApi::class)
    operator fun invoke(
        requests: Flow<SearchRequest?>,
        pageSize: Int,
        tab: SearchTabType = SearchTabType.COMMON_APPS,
    ): Flow<PagingData<Application>> {
        return requests
            .filterNotNull()
            .mapLatest { request ->
                if (!request.visibleTabs.contains(tab) || request.query.isBlank()) {
                    flowOf(PagingData.empty<Application>())
                } else {
                    playStorePagingRepository.playStoreSearch(
                        query = request.query,
                        pageSize = pageSize,
                    ).map { pagingData: PagingData<App> ->
                        pagingData.map { app: App ->
                            playStoreAppMapper.map(app)
                        }
                    }
                }
            }
            .flatMapLatest { it }
    }
}
Loading