Skip to content

Commit

Permalink
refactor paging favourite and match
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Apr 29, 2024
1 parent eb8f4fb commit ff24dea
Show file tree
Hide file tree
Showing 38 changed files with 518 additions and 390 deletions.
2 changes: 2 additions & 0 deletions composeApp/src/commonMain/kotlin/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import com.stslex.core.core.coreModule
import com.stslex.core.database.di.coreDatabaseModule
import com.stslex.core.database.di.userSettingsModule
import com.stslex.core.network.di.coreNetworkModule
import com.stslex.core.ui.di.coreUiModule
import com.stslex.core.ui.theme.AppTheme
import com.stslex.feature.auth.di.featureAuthModule
import com.stslex.feature.favourite.di.featureFavouriteModule
Expand Down Expand Up @@ -38,6 +39,7 @@ private fun KoinApplication.setupCommonModules() {
listOf(
appModule,
coreModule,
coreUiModule,
coreNetworkModule,
userSettingsModule,
coreDatabaseModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.stslex.core.core.coroutine

import com.stslex.core.core.AppDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow

Expand All @@ -17,6 +18,7 @@ interface AppCoroutineScope {
* @see AppDispatcher
* */
fun <T> launch(
start: CoroutineStart = CoroutineStart.DEFAULT,
onError: suspend (Throwable) -> Unit = {},
onSuccess: suspend CoroutineScope.(T) -> Unit = {},
action: suspend CoroutineScope.() -> T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.stslex.core.core.Logger
import com.stslex.core.core.coroutineExceptionHandler
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
Expand All @@ -24,10 +25,12 @@ class AppCoroutineScopeImpl(
}

override fun <T> launch(
start: CoroutineStart,
onError: suspend (Throwable) -> Unit,
onSuccess: suspend CoroutineScope.(T) -> Unit,
action: suspend CoroutineScope.() -> T
): Job = scope.launch(
start = start,
context = exceptionHandler(onError) + appDispatcher.default,
block = {
onSuccess(action())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import com.stslex.core.network.clients.match.client.MatchClient
import com.stslex.core.network.clients.match.client.MockMatchClientImpl
import com.stslex.core.network.clients.profile.client.ProfileClient
import com.stslex.core.network.clients.profile.client.ProfileClientImpl
import com.stslex.core.network.utils.PagingWorker
import com.stslex.core.network.utils.PagingWorkerImpl
import com.stslex.core.network.utils.token.AuthController
import com.stslex.core.network.utils.token.AuthControllerImpl
import org.koin.dsl.module
Expand Down Expand Up @@ -81,8 +79,4 @@ val coreNetworkModule = module {
userStore = get(),
)
}

factory<PagingWorker> {
PagingWorkerImpl()
}
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.stslex.core.ui.di

import com.stslex.core.ui.pager.pager.StorePagerFactory
import com.stslex.core.ui.pager.pager.StorePagerFactoryImpl
import org.koin.dsl.module

val coreUiModule = module {
factory<StorePagerFactory> {
StorePagerFactoryImpl()
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.stslex.core.ui.pager
package com.stslex.core.ui.pager.pager

import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.base.paging.PagingState
import com.stslex.core.ui.pager.states.PagerLoadEvents
import com.stslex.core.ui.pager.states.PagerLoadState
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow

Expand All @@ -17,7 +19,7 @@ interface StorePager<out Item : PagingItem> {

fun load()

fun refresh()
fun refresh(isForceLoad: Boolean)

fun retry()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.stslex.core.ui.pager.pager

import com.stslex.core.core.coroutine.AppCoroutineScope
import com.stslex.core.core.paging.PagingCoreData
import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.pager.utils.PagingMapper

interface StorePagerFactory {

fun <T : PagingItem, R : PagingCoreItem> create(
scope: AppCoroutineScope,
request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
mapper: PagingMapper<R, T>,
pageSize: Int = PagingCoreData.DEFAULT_PAGE_SIZE,
): StorePager<T>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.stslex.core.ui.pager.pager

import com.stslex.core.core.coroutine.AppCoroutineScope
import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.pager.utils.PagingMapper
import com.stslex.core.ui.pager.utils.PagingWorkerImpl

class StorePagerFactoryImpl : StorePagerFactory {

override fun <T : PagingItem, R : PagingCoreItem> create(
scope: AppCoroutineScope,
request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
mapper: PagingMapper<R, T>,
pageSize: Int
): StorePager<T> {
return StorePagerImpl(
pagingWorker = PagingWorkerImpl(scope = scope),
request = request,
mapper = mapper,
pageSize = pageSize
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.stslex.core.ui.pager
package com.stslex.core.ui.pager.pager

import com.stslex.core.core.coroutine.AppCoroutineScope
import com.stslex.core.core.paging.PagingCoreData
import com.stslex.core.core.paging.PagingCoreData.Companion.DEFAULT_PAGE
import com.stslex.core.core.paging.PagingCoreItem
Expand All @@ -9,6 +8,10 @@ import com.stslex.core.ui.base.mapToAppError
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.base.paging.PagingState
import com.stslex.core.ui.base.paging.pagingMap
import com.stslex.core.ui.pager.states.PagerLoadEvents
import com.stslex.core.ui.pager.states.PagerLoadState
import com.stslex.core.ui.pager.utils.PagingMapper
import com.stslex.core.ui.pager.utils.PagingWorker
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableSharedFlow
Expand All @@ -18,8 +21,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update

class StorePagerImpl<out T : PagingItem, in R : PagingCoreItem>(
private val pagingWorker: PagingWorker,
private val request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
private val scope: AppCoroutineScope,
private val mapper: PagingMapper<R, T>,
pageSize: Int = PagingCoreData.DEFAULT_PAGE_SIZE,
) : StorePager<T> {
Expand Down Expand Up @@ -57,14 +60,14 @@ class StorePagerImpl<out T : PagingItem, in R : PagingCoreItem>(
requestItems(isForceLoad = false)
}

override fun refresh() {
override fun refresh(isForceLoad: Boolean) {
_loadState.value = PagerLoadState.Refresh
_state.update { currentState ->
currentState.copy(
page = DEFAULT_PAGE
page = DEFAULT_PAGE,
)
}
requestItems(isForceLoad = true)
requestItems(isForceLoad = isForceLoad)
}

override fun retry() {
Expand All @@ -85,7 +88,7 @@ class StorePagerImpl<out T : PagingItem, in R : PagingCoreItem>(
return
}
loadJob?.cancel()
loadJob = scope.launch(
loadJob = pagingWorker.launch(
action = {
val page = state.value.page
val pageSize = state.value.pageSize
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stslex.core.ui.pager
package com.stslex.core.ui.pager.states

import com.stslex.core.ui.base.AppError

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stslex.core.ui.pager
package com.stslex.core.ui.pager.states

import com.stslex.core.ui.base.AppError

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.stslex.core.ui.pager
package com.stslex.core.ui.pager.utils

import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.ui.base.paging.PagingItem
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.stslex.core.ui.pager.utils

import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job

interface PagingWorker {

fun <T : PagingCoreItem> launch(
onError: suspend (Throwable) -> Unit = {},
onSuccess: suspend CoroutineScope.(PagingResponse<T>) -> Unit = {},
action: suspend CoroutineScope.() -> PagingResponse<T>,
): Job

fun cancel()
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.stslex.core.ui.pager.utils

import com.stslex.core.core.coroutine.AppCoroutineScope
import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import com.stslex.core.network.utils.currentTimeMs
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Job

class PagingWorkerImpl(
private val scope: AppCoroutineScope
) : PagingWorker {

private var job: Job? = null
private var nextPageJob: Job? = null
private var lastRequestTime = 0L

override fun <T : PagingCoreItem> launch(
onError: suspend (Throwable) -> Unit,
onSuccess: suspend CoroutineScope.(PagingResponse<T>) -> Unit,
action: suspend CoroutineScope.() -> PagingResponse<T>
): Job = if (lastRequestTime + REQUEST_DELAY > currentTimeMs) {
startRequest(
onError = onError,
onSuccess = onSuccess,
action = action,
start = CoroutineStart.LAZY
).apply {
nextPageJob = this
}
} else {
startRequest(
onError = onError,
onSuccess = onSuccess,
action = action,
)
}

override fun cancel() {
job?.cancel()
nextPageJob?.cancel()
}

private fun <T : PagingCoreItem> startRequest(
onError: suspend (Throwable) -> Unit,
onSuccess: suspend CoroutineScope.(PagingResponse<T>) -> Unit,
action: suspend CoroutineScope.() -> PagingResponse<T>,
start: CoroutineStart = CoroutineStart.DEFAULT,
): Job = scope
.launch(
start = start,
onError = onError,
onSuccess = onSuccess,
action = {
job = nextPageJob
nextPageJob = null
action()
}
).apply {
invokeOnCompletion {
nextPageJob?.start()
}
}

companion object {
private const val REQUEST_DELAY = 500L
}
}
Loading

0 comments on commit ff24dea

Please sign in to comment.