Skip to content

Commit a3bfdc8

Browse files
authored
Merge pull request #59 from CodandoTV/feature/10_streams_pagination_support
[ISSUE-10, ISSUE-54] - Adicionando a lib Paging 3
2 parents dd9860e + 59f7bc6 commit a3bfdc8

File tree

20 files changed

+326
-157
lines changed

20 files changed

+326
-157
lines changed

app/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ android {
77
}
88

99
composeOptions {
10-
kotlinCompilerExtensionVersion = Versions.composeCompilerVersion
10+
kotlinCompilerExtensionVersion = Versions.compose_compiler_version
1111
}
1212
}
1313
dependencies {

buildSrc/src/main/java/Dependencies.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface GroupLibs {
66

77
object Dependencies {
88
const val runnerPackage = "androidx.test.runner.AndroidJUnitRunner"
9-
const val coil = "io.coil-kt:coil-compose:${Versions.coilVersion}"
9+
const val coil = "io.coil-kt:coil-compose:${Versions.coil_version}"
1010
const val lottie = "com.airbnb.android:lottie-compose:${Versions.lottie}"
1111

1212
object Module {
@@ -147,16 +147,17 @@ object Dependencies {
147147
}
148148

149149
object Compose : GroupLibs {
150-
const val composeBomVersion = "androidx.compose:compose-bom:${Versions.composeBomVersion}"
150+
const val composeBomVersion = "androidx.compose:compose-bom:${Versions.compose_bom_version}"
151151
const val composeUI = "androidx.compose.ui:ui"
152152
const val coposeUIToolingPreview = "androidx.compose.ui:ui-tooling-preview"
153153
const val composeActivityCompose =
154-
"androidx.activity:activity-compose:${Versions.composeActivity}"
154+
"androidx.activity:activity-compose:${Versions.compose_activity}"
155155
const val composeUITooling = "androidx.compose.ui:ui-tooling"
156-
const val composeMaterial3 = "androidx.compose.material3:material3:${Versions.composeMaterial3Version}"
157-
const val composeNavigation = "androidx.navigation:navigation-compose:${Versions.composeNavigationVersion}"
158-
const val composeIcons = "androidx.compose.material:material-icons-extended:${Versions.composeIcons}"
159-
const val lifecycleComposeRuntime = "androidx.lifecycle:lifecycle-runtime-compose:${Versions.lifecycleComposeRuntime}"
156+
const val composeMaterial3 = "androidx.compose.material3:material3:${Versions.compose_material_3_version}"
157+
const val composeNavigation = "androidx.navigation:navigation-compose:${Versions.compose_navigation_version}"
158+
const val composeIcons = "androidx.compose.material:material-icons-extended:${Versions.compose_icons}"
159+
const val lifecycleComposeRuntime = "androidx.lifecycle:lifecycle-runtime-compose:${Versions.lifecycle_compose_runtime}"
160+
const val pagingCompose = "androidx.paging:paging-compose:${Versions.paging_compose}"
160161

161162
override val list: List<String>
162163
get() = listOf(
@@ -167,7 +168,8 @@ object Dependencies {
167168
Compose.composeMaterial3,
168169
Compose.composeNavigation,
169170
Compose.composeIcons,
170-
Compose.lifecycleComposeRuntime
171+
Compose.lifecycleComposeRuntime,
172+
Compose.pagingCompose
171173
)
172174
}
173175
}

buildSrc/src/main/java/Versions.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ object Versions {
2828
const val compose_version = "1.4.2"
2929
const val retrofit = "2.9.0"
3030

31-
const val composeBomVersion = "2023.01.00"
32-
const val composeCompilerVersion = "1.4.2"
33-
const val composeMaterial3Version = "1.0.1"
34-
const val composeActivity = "1.5.0"
35-
const val composeIcons = "1.4.3"
36-
const val composeNavigationVersion = "2.5.3"
37-
const val lifecycleComposeRuntime = "2.6.1"
31+
const val compose_bom_version = "2023.01.00"
32+
const val compose_compiler_version = "1.4.2"
33+
const val compose_material_3_version = "1.0.1"
34+
const val compose_activity = "1.5.0"
35+
const val compose_icons = "1.4.3"
36+
const val compose_navigation_version = "2.5.3"
37+
const val lifecycle_compose_runtime = "2.6.1"
38+
const val paging_compose = "1.0.0-alpha20"
3839

39-
const val coilVersion = "2.3.0"
40+
const val coil_version = "2.3.0"
4041

4142
const val lottie = "5.2.0"
4243
}

core-navigation/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ android {
77
}
88

99
composeOptions {
10-
kotlinCompilerExtensionVersion = Versions.composeCompilerVersion
10+
kotlinCompilerExtensionVersion = Versions.compose_compiler_version
1111
}
1212
}
1313

core-shared-ui/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ android {
88
}
99

1010
composeOptions {
11-
kotlinCompilerExtensionVersion = Versions.composeCompilerVersion
11+
kotlinCompilerExtensionVersion = Versions.compose_compiler_version
1212
}
1313
}
1414

feature-list-streams/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ android {
77
}
88

99
composeOptions {
10-
kotlinCompilerExtensionVersion = Versions.composeCompilerVersion
10+
kotlinCompilerExtensionVersion = Versions.compose_compiler_version
1111
}
1212

1313
dependencies {
Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,52 @@
11
package com.codandotv.streamplayerapp.feature_list_streams.list.data
22

3+
import androidx.paging.Pager
4+
import androidx.paging.PagingConfig
5+
import androidx.paging.PagingData
36
import com.codandotv.streamplayerapp.core_networking.handleError.toFlow
4-
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.model.ListStream
5-
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.toListStream
7+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.model.Genre
8+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.model.Stream
9+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.toGenres
10+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.toStream
611
import kotlinx.coroutines.CoroutineDispatcher
7-
import kotlinx.coroutines.Dispatchers
812
import kotlinx.coroutines.flow.*
913

1014
interface ListStreamRepository {
11-
suspend fun getMovies(): Flow<List<ListStream>>
15+
suspend fun getGenres(): Flow<List<Genre>>
16+
17+
suspend fun topRatedStream(): Flow<Stream>
18+
19+
fun loadMovies(genre: Genre): Flow<PagingData<Stream>>
1220
}
1321

1422
class ListStreamRepositoryImpl(
1523
private val service: ListStreamService,
1624
private val dispatcher: CoroutineDispatcher,
1725
) : ListStreamRepository {
1826

19-
override suspend fun getMovies(): Flow<List<ListStream>> =
20-
service.getGenres()
21-
.toFlow()
22-
.map {
23-
it.genres
24-
}
25-
.map { genres ->
26-
genres.map { genre ->
27-
service.getMovies(genre.id.toString())
28-
.toFlow()
29-
.map {
30-
it.toListStream(
31-
genre.name
32-
)
33-
}.first()
34-
}
35-
}.flowOn(dispatcher)
27+
override suspend fun getGenres(): Flow<List<Genre>> {
28+
return service.getGenres().toFlow().map { it.toGenres() }
29+
}
30+
31+
override suspend fun topRatedStream() = service.getTopRatedMovies().toFlow().map {
32+
it.results.first { it.poster_path != null }.toStream()
33+
}
34+
35+
override fun loadMovies(genre: Genre): Flow<PagingData<Stream>> {
36+
return Pager(
37+
config = PagingConfig(
38+
pageSize = PAGE_SIZE,
39+
maxSize = MAX_SIZE,
40+
),
41+
pagingSourceFactory = {
42+
StreamDataSource(service, genreName = genre.name, genreId = genre.id)
43+
},
44+
initialKey = 1
45+
).flow
46+
}
47+
48+
companion object {
49+
private const val PAGE_SIZE = 20
50+
private const val MAX_SIZE = 500
51+
}
3652
}

feature-list-streams/src/main/java/com/codandotv/streamplayerapp/feature_list_streams/list/data/ListStreamService.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,23 @@ package com.codandotv.streamplayerapp.feature_list_streams.list.data
33
import com.codandotv.streamplayerapp.core_networking.handleError.NetworkResponse
44
import com.codandotv.streamplayerapp.feature_list_streams.list.data.model.GenresResponse
55
import com.codandotv.streamplayerapp.feature_list_streams.list.data.model.ListStreamResponse
6+
import com.codandotv.streamplayerapp.feature_list_streams.list.data.model.StreamResponse
67
import retrofit2.http.GET
78
import retrofit2.http.Query
89

910
interface ListStreamService {
1011
@GET("discover/movie")
1112
suspend fun getMovies(@Query("with_genres") genres: String) : NetworkResponse<ListStreamResponse>
1213

14+
@GET("discover/movie")
15+
suspend fun getPaginatedMovies(@Query("with_genres") genres: String, @Query("page") page: Int) : NetworkResponse<ListStreamResponse>
16+
1317
@GET("genre/movie/list")
1418
suspend fun getGenres(): NetworkResponse<GenresResponse>
19+
20+
@GET("discover/movie")
21+
suspend fun getTopRatedMovies(
22+
@Query("sort_by") sortBy: String = "vote_average.desc",
23+
@Query("page") page: Int = 1
24+
): NetworkResponse<ListStreamResponse>
1525
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.codandotv.streamplayerapp.feature_list_streams.list.data
2+
3+
import androidx.paging.PagingSource
4+
import androidx.paging.PagingState
5+
import com.codandotv.streamplayerapp.core_networking.handleError.NetworkResponse
6+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.model.Stream
7+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.toListStream
8+
9+
class StreamDataSource(
10+
private val service: ListStreamService,
11+
private val genreId: Long,
12+
private val genreName: String,
13+
) : PagingSource<Int, Stream>() {
14+
15+
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Stream> {
16+
val nextPageNumber = params.key ?: START_PAGE_INDEX
17+
18+
return try {
19+
val response = service.getPaginatedMovies(
20+
genres = genreId.toString(),
21+
page = nextPageNumber
22+
)
23+
24+
if (response is NetworkResponse.Success) {
25+
LoadResult.Page(
26+
data = response.value.toListStream(genreName).streams,
27+
prevKey = if (nextPageNumber > 1) nextPageNumber - 1 else null,
28+
nextKey = nextPageNumber.plus(1)
29+
)
30+
} else {
31+
throw IllegalStateException("Something wrong")
32+
}
33+
} catch (exception: Exception) {
34+
LoadResult.Error(exception)
35+
}
36+
}
37+
38+
override fun getRefreshKey(state: PagingState<Int, Stream>): Int? = null
39+
40+
companion object {
41+
private const val START_PAGE_INDEX = 1
42+
}
43+
}

feature-list-streams/src/main/java/com/codandotv/streamplayerapp/feature_list_streams/list/di/ListStreamModule.kt

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import com.codandotv.streamplayerapp.core_shared.qualifier.QualifierDispatcherIO
44
import com.codandotv.streamplayerapp.feature_list_streams.list.data.ListStreamRepository
55
import com.codandotv.streamplayerapp.feature_list_streams.list.data.ListStreamRepositoryImpl
66
import com.codandotv.streamplayerapp.feature_list_streams.list.data.ListStreamService
7+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.GetTopRatedStream
8+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.GetTopRatedStreamImpl
9+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.GetGenresUseCase
10+
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.GetGenresUseCaseImpl
711
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.ListStreamAnalytics
812
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.ListStreamAnalyticsImpl
913
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.ListStreamUseCase
1014
import com.codandotv.streamplayerapp.feature_list_streams.list.domain.ListStreamUseCaseImpl
11-
import com.codandotv.streamplayerapp.feature_list_streams.list.presentation.ListStreamUiModelImpl
12-
import com.codandotv.streamplayerapp.feature_list_streams.list.presentation.ListStreamUimodel
1315
import com.codandotv.streamplayerapp.feature_list_streams.list.presentation.screens.ListStreamViewModel
1416
import org.koin.androidx.viewmodel.dsl.viewModel
1517
import org.koin.dsl.module
@@ -19,16 +21,30 @@ object ListStreamModule {
1921
val module = module {
2022
viewModel {
2123
ListStreamViewModel(
22-
uiModel = get(),
23-
useCase = get(),
24+
listStreams = get(),
25+
listGenres = get(),
26+
latestStream = get()
2427
)
2528
}
29+
2630
factory<ListStreamUseCase> {
2731
ListStreamUseCaseImpl(
2832
repository = get()
2933
)
3034
}
3135

36+
factory<GetGenresUseCase> {
37+
GetGenresUseCaseImpl(
38+
repository = get()
39+
)
40+
}
41+
42+
factory<GetTopRatedStream> {
43+
GetTopRatedStreamImpl(
44+
repository = get()
45+
)
46+
}
47+
3248
factory<ListStreamAnalytics> {
3349
ListStreamAnalyticsImpl()
3450
}
@@ -41,11 +57,5 @@ object ListStreamModule {
4157
}
4258

4359
factory { get<Retrofit>().create(ListStreamService::class.java) }
44-
45-
factory<ListStreamUimodel> {
46-
ListStreamUiModelImpl(
47-
resources = get()
48-
)
49-
}
5060
}
5161
}

0 commit comments

Comments
 (0)