Skip to content

Commit 8e255dd

Browse files
committed
Load more horizontal
1 parent 1abef74 commit 8e255dd

File tree

4 files changed

+106
-4
lines changed

4 files changed

+106
-4
lines changed

app/src/main/java/com/hoc/pagination_mvi/ui/main/MainContract.kt

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ interface MainContract {
2424
?.state is PlaceholderState.Error
2525
}
2626

27+
fun canLoadNextPageHorizontal(): Boolean {
28+
val horizontalList =
29+
items.singleOrNull { it is Item.HorizontalList } as? Item.HorizontalList ?: return false
30+
return !horizontalList.isLoading &&
31+
horizontalList.error == null &&
32+
horizontalList.postItems.isNotEmpty() &&
33+
(horizontalList.items.singleOrNull { it is HorizontalItem.Placeholder } as? HorizontalItem.Placeholder)
34+
?.state == PlaceholderState.Idle
35+
}
36+
37+
fun getHorizontalListCount(): Int {
38+
val horizontalList =
39+
items.singleOrNull { it is Item.HorizontalList } as? Item.HorizontalList ?: return 0
40+
return horizontalList.postItems.size
41+
}
42+
2743
companion object Factory {
2844
@JvmStatic
2945
fun initial() = ViewState(
@@ -110,8 +126,8 @@ interface MainContract {
110126
object LoadNextPage : ViewIntent()
111127
object RetryLoadPage : ViewIntent()
112128

113-
object LoadNextPageHorizontal: ViewIntent()
114-
object RetryLoadPageHorizontal: ViewIntent()
129+
object LoadNextPageHorizontal : ViewIntent()
130+
object RetryLoadPageHorizontal : ViewIntent()
115131
}
116132

117133
sealed class PartialStateChange {
@@ -239,6 +255,63 @@ interface MainContract {
239255
}
240256
}
241257
}
258+
259+
sealed class PostNextPage : PartialStateChange() {
260+
data class Data(val posts: List<PostVS>) : PostNextPage()
261+
data class Error(val error: Throwable) : PostNextPage()
262+
object Loading : PostNextPage()
263+
264+
override fun reduce(vs: ViewState): ViewState {
265+
return when (this) {
266+
is Data -> {
267+
vs.copy(
268+
items = vs.items.map { item ->
269+
if (item is Item.HorizontalList) {
270+
val postItems = item.items.filterIsInstance<HorizontalItem.Post>() +
271+
this.posts.map { HorizontalItem.Post(it) }
272+
item.copy(
273+
items = postItems + HorizontalItem.Placeholder(PlaceholderState.Idle),
274+
postItems = postItems
275+
)
276+
} else {
277+
item
278+
}
279+
}
280+
)
281+
}
282+
is Error -> {
283+
vs.copy(
284+
items = vs.items.map { item ->
285+
if (item is Item.HorizontalList) {
286+
val postItems = item.items.filterIsInstance<HorizontalItem.Post>()
287+
item.copy(
288+
items = postItems + HorizontalItem.Placeholder(PlaceholderState.Error(error)),
289+
postItems = postItems
290+
)
291+
} else {
292+
item
293+
}
294+
}
295+
)
296+
}
297+
Loading -> {
298+
vs.copy(
299+
items = vs.items.map { item ->
300+
if (item is Item.HorizontalList) {
301+
val postItems = item.items.filterIsInstance<HorizontalItem.Post>()
302+
item.copy(
303+
items = postItems + HorizontalItem.Placeholder(PlaceholderState.Loading),
304+
postItems = postItems
305+
)
306+
} else {
307+
item
308+
}
309+
}
310+
)
311+
}
312+
}
313+
}
314+
}
242315
}
243316

244317
sealed class SingleEvent {
@@ -250,5 +323,6 @@ interface MainContract {
250323
fun photoFirstPageChanges(limit: Int): Observable<PartialStateChange.PhotoFirstPage>
251324

252325
fun postFirstPageChanges(limit: Int): Observable<PartialStateChange.PostFirstPage>
326+
fun postNextPageChanges(start: Int, limit: Int): Observable<PartialStateChange.PostNextPage>
253327
}
254328
}

app/src/main/java/com/hoc/pagination_mvi/ui/main/MainInteractorImpl.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,22 @@ class MainInteractorImpl @Inject constructor(
6666
}
6767
}
6868
}
69+
70+
override fun postNextPageChanges(
71+
start: Int,
72+
limit: Int
73+
): Observable<MainContract.PartialStateChange.PostNextPage> {
74+
return rxObservable(dispatchers.main) {
75+
send(MainContract.PartialStateChange.PostNextPage.Loading)
76+
try {
77+
getPostsUseCase(start = start, limit = limit)
78+
.map(::PostVS)
79+
.let { MainContract.PartialStateChange.PostNextPage.Data(it) }
80+
.let { send(it) }
81+
} catch (e: Exception) {
82+
delay(500)
83+
send(MainContract.PartialStateChange.PostNextPage.Error(e))
84+
}
85+
}
86+
}
6987
}

app/src/main/java/com/hoc/pagination_mvi/ui/main/MainVM.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,23 @@ class MainVM @Inject constructor(
6767
.exhaustMap { interactor.photoNextPageChanges(start = it, limit = PHOTO_PAGE_SIZE) }
6868
}
6969

70+
private val loadNextPageHorizontalProcessor =
71+
ObservableTransformer<ViewIntent.LoadNextPageHorizontal, PartialStateChange> { intents ->
72+
intents
73+
.withLatestFrom(stateObservable)
74+
.filter { (_, vs) -> vs.canLoadNextPageHorizontal() }
75+
.map { (_, vs) -> vs.getHorizontalListCount() }
76+
.exhaustMap { interactor.postNextPageChanges(start = it, limit = POST_PAGE_SIZE) }
77+
}
78+
7079
private val toPartialStateChange =
7180
ObservableTransformer<ViewIntent, PartialStateChange> { intents ->
7281
intents.publish { shared ->
7382
Observable.mergeArray(
7483
shared.ofType<ViewIntent.Initial>().compose(initialProcessor),
7584
shared.ofType<ViewIntent.LoadNextPage>().compose(nextPageProcessor),
76-
shared.ofType<ViewIntent.RetryLoadPage>().compose(retryLoadPageProcessor)
85+
shared.ofType<ViewIntent.RetryLoadPage>().compose(retryLoadPageProcessor),
86+
shared.ofType<ViewIntent.LoadNextPageHorizontal>().compose(loadNextPageHorizontalProcessor)
7787
)
7888
}
7989
}

app/src/main/res/layout/recycler_item_horizontal_placeholder.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools"
5-
android:layout_width="0dp"
5+
android:layout_width="wrap_content"
66
android:layout_height="match_parent"
77
tools:layout_height="200dp">
88

0 commit comments

Comments
 (0)