Skip to content

Commit

Permalink
add paging UI component
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Apr 30, 2024
1 parent fb4b961 commit 44b4b7b
Show file tree
Hide file tree
Showing 18 changed files with 112 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ interface PagingCoreData<out T : PagingCoreItem> {

const val DEFAULT_PAGE_SIZE = 15
const val DEFAULT_PAGE = 0
const val DEFAULT_PAGE_OFFSET = 0.5f
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.stslex.core.ui.base.paging

import androidx.compose.runtime.Stable
import com.stslex.core.core.paging.PagingCoreData

@Stable
data class PagingConfig(
val pageSize: Int,
val pageOffset: Float = PagingCoreData.DEFAULT_PAGE_OFFSET
) {

companion object {

val DEFAULT = PagingConfig(
pageSize = PagingCoreData.DEFAULT_PAGE_SIZE,
pageOffset = PagingCoreData.DEFAULT_PAGE_OFFSET
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import androidx.compose.runtime.Stable
import com.stslex.core.core.asyncMap
import com.stslex.core.core.paging.PagingCoreData
import com.stslex.core.core.paging.PagingCoreData.Companion.DEFAULT_PAGE
import com.stslex.core.core.paging.PagingCoreData.Companion.DEFAULT_PAGE_SIZE
import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import kotlinx.collections.immutable.ImmutableList
Expand All @@ -23,10 +22,10 @@ data class PagingState<out T : PagingItem>(
companion object {

fun <T : PagingItem> default(
pageSize: Int = DEFAULT_PAGE_SIZE,
pagingConfig: PagingConfig,
) = PagingState(
page = DEFAULT_PAGE,
pageSize = pageSize,
pageSize = pagingConfig.pageSize,
total = 0,
hasMore = true,
result = persistentListOf<T>(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.stslex.core.ui.base.paging

import androidx.compose.runtime.Stable
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlin.math.roundToInt

@Stable
data class PagingUiState<out T : PagingItem>(
val items: ImmutableList<T>,
val hasMore: Boolean,
val total: Int,
val config: PagingConfig
) {

val pageOffset: Int = (config.pageSize * config.pageOffset).roundToInt()

companion object {

fun <T : PagingItem> default(config: PagingConfig) = PagingUiState(
items = persistentListOf<T>(),
total = 0,
hasMore = true,
config = config
)
}
}

fun <T : PagingItem> PagingState<T>.toUi(
pagingConfig: PagingConfig
): PagingUiState<T> = PagingUiState(
items = result,
hasMore = hasMore,
total = total,
config = pagingConfig
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
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.PagingConfig
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.pager.utils.PagingMapper

Expand All @@ -13,6 +13,6 @@ interface StorePagerFactory {
scope: AppCoroutineScope,
request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
mapper: PagingMapper<R, T>,
pageSize: Int = PagingCoreData.DEFAULT_PAGE_SIZE,
config: PagingConfig
): StorePager<T>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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.PagingConfig
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.pager.utils.PagingMapper
import com.stslex.core.ui.pager.utils.PagingWorkerImpl
Expand All @@ -13,13 +14,13 @@ class StorePagerFactoryImpl : StorePagerFactory {
scope: AppCoroutineScope,
request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
mapper: PagingMapper<R, T>,
pageSize: Int
config: PagingConfig
): StorePager<T> {
return StorePagerImpl(
pagingWorker = PagingWorkerImpl(scope = scope),
request = request,
mapper = mapper,
pageSize = pageSize
pagingConfig = config
)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.stslex.core.ui.pager.pager

import com.stslex.core.core.paging.PagingCoreData
import com.stslex.core.core.paging.PagingCoreData.Companion.DEFAULT_PAGE
import com.stslex.core.core.paging.PagingCoreItem
import com.stslex.core.core.paging.PagingResponse
import com.stslex.core.ui.base.mapToAppError
import com.stslex.core.ui.base.paging.PagingConfig
import com.stslex.core.ui.base.paging.PagingItem
import com.stslex.core.ui.base.paging.PagingState
import com.stslex.core.ui.base.paging.pagingMap
Expand All @@ -24,10 +24,10 @@ class StorePagerImpl<out T : PagingItem, in R : PagingCoreItem>(
private val pagingWorker: PagingWorker,
private val request: suspend (page: Int, pageSize: Int) -> PagingResponse<R>,
private val mapper: PagingMapper<R, T>,
pageSize: Int = PagingCoreData.DEFAULT_PAGE_SIZE,
pagingConfig: PagingConfig,
) : StorePager<T> {

private val _state = MutableStateFlow<PagingState<T>>(PagingState.default(pageSize))
private val _state = MutableStateFlow<PagingState<T>>(PagingState.default(pagingConfig))
override val state = _state.asStateFlow()

private val _loadState = MutableStateFlow<PagerLoadState>(PagerLoadState.Initial)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal fun FavouriteScreen(
when (state.screen) {
is FavouriteScreenState.Content -> FavouriteScreenContent(
state = state.screen,
items = state.pagingState.result,
items = state.paging.items,
query = state.query,
isLoading = state.isLoading,
onItemClick = { uuid ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
Expand All @@ -18,7 +17,6 @@ import androidx.compose.ui.text.style.TextAlign
import com.stslex.core.ui.theme.AppDimension
import com.stslex.feature.favourite.ui.model.FavouriteModel

@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun FavouriteScreenContentItem(
item: FavouriteModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.stslex.feature.favourite.ui.store

import androidx.compose.runtime.Stable
import com.stslex.core.ui.base.paging.PagingState
import com.stslex.core.ui.base.paging.PagingConfig
import com.stslex.core.ui.base.paging.PagingUiState
import com.stslex.core.ui.mvi.Store
import com.stslex.core.ui.mvi.Store.Event.Snackbar
import com.stslex.feature.favourite.ui.model.FavouriteModel
Expand All @@ -15,7 +16,7 @@ interface FavouriteStore : Store<State, Event, Action> {
data class State(
val uuid: String,
val query: String,
val pagingState: PagingState<FavouriteModel>,
val paging: PagingUiState<FavouriteModel>,
val screen: FavouriteScreenState,
val isLoading: Boolean
) : Store.State {
Expand All @@ -25,7 +26,7 @@ interface FavouriteStore : Store<State, Event, Action> {
val INITIAL = State(
uuid = "",
query = "",
pagingState = PagingState.default(),
paging = PagingUiState.default(PagingConfig.DEFAULT),
screen = FavouriteScreenState.Shimmer,
isLoading = true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.stslex.feature.favourite.ui.store

import com.stslex.core.core.AppDispatcher
import com.stslex.core.ui.base.mapToAppError
import com.stslex.core.ui.base.paging.toUi
import com.stslex.core.ui.mvi.BaseStore
import com.stslex.core.ui.mvi.Store.Event.Snackbar
import com.stslex.core.ui.pager.pager.StorePager
Expand Down Expand Up @@ -44,7 +45,8 @@ class FavouriteStoreImpl(
)
},
scope = scope,
mapper = { it.toUI() }
mapper = { it.toUI() },
config = state.value.paging.config
)

override fun process(action: Action) {
Expand All @@ -69,7 +71,7 @@ class FavouriteStoreImpl(
pager.state.launch { pagerState ->
updateState { currentState ->
currentState.copy(
pagingState = pagerState
paging = pagerState.toUi(currentState.paging.config)
)
}
}
Expand Down Expand Up @@ -116,20 +118,20 @@ class FavouriteStoreImpl(

private fun actionLikeClick(action: Action.LikeClick) {
if (likeJob?.isActive == true) return
val items = state.value.pagingState.result.toMutableList()
val items = state.value.paging.items.toMutableList()
val itemIndex = items
.indexOfFirst {
it.uuid == action.uuid
}
.takeIf { it != -1 }
?: return
val item = state.value.pagingState.result.getOrNull(itemIndex) ?: return
val item = state.value.paging.items.getOrNull(itemIndex) ?: return
val newItem = item.copy(isFavourite = item.isFavourite.not())
items[itemIndex] = newItem
updateState { state ->
state.copy(
pagingState = state.pagingState.copy(
result = items.toImmutableList()
paging = state.paging.copy(
items = items.toImmutableList()
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ internal fun FollowerScreen(
when (state.screen) {
is FollowerScreenState.Content -> {
LazyColumn {
items(state.pagingState.result.size) { index ->
items(state.paging.items.size) { index ->
Text(
"test: ${state.pagingState.result[index].username}"
"test: ${state.paging.items[index].username}"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.stslex.feature.follower.ui.store

import androidx.compose.runtime.Stable
import com.stslex.core.ui.base.paging.PagingState
import com.stslex.core.ui.base.paging.PagingConfig
import com.stslex.core.ui.base.paging.PagingUiState
import com.stslex.core.ui.mvi.Store
import com.stslex.core.ui.mvi.Store.Event.Snackbar
import com.stslex.feature.follower.navigation.FollowerScreenArgs
Expand All @@ -15,18 +16,16 @@ interface FollowerStore : Store<State, Event, Action> {
@Stable
data class State(
val type: FollowerScreenArgs,
val pagingState: PagingState<FollowerModel>,
val paging: PagingUiState<FollowerModel>,
val screen: FollowerScreenState,
val query: String
) : Store.State {

companion object {

const val DEFAULT_PAGE = -1

val INITIAL = State(
type = FollowerScreenArgs.Follower(""),
pagingState = PagingState.default(),
paging = PagingUiState.default(PagingConfig.DEFAULT),
screen = FollowerScreenState.Shimmer,
query = ""
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.stslex.feature.follower.ui.store

import com.stslex.core.core.AppDispatcher
import com.stslex.core.ui.base.mapToAppError
import com.stslex.core.ui.base.paging.toUi
import com.stslex.core.ui.mvi.BaseStore
import com.stslex.core.ui.mvi.Store.Event.Snackbar
import com.stslex.core.ui.pager.pager.StorePager
Expand Down Expand Up @@ -50,7 +51,8 @@ class FollowerStoreImpl(
}
},
scope = scope,
mapper = { it.toUi() }
mapper = { it.toUi() },
config = state.value.paging.config
)

override fun process(action: Action) {
Expand All @@ -72,7 +74,7 @@ class FollowerStoreImpl(
pager.state.launch { pagerState ->
updateState { currentState ->
currentState.copy(
pagingState = pagerState
paging = pagerState.toUi(currentState.paging.config)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private fun MatchScreen(
) {
when (val screen = state.screen) {
is MatchScreenState.Content -> MatchScreenContent(
state = state.pagingState,
state = state.paging,
screen = screen,
onAction = onAction
)
Expand Down
Loading

0 comments on commit 44b4b7b

Please sign in to comment.