Skip to content

Commit

Permalink
Reference #6, move Search classes to new mapping with RemoteDataSource
Browse files Browse the repository at this point in the history
  • Loading branch information
herrbert74 committed Oct 24, 2024
1 parent ec06b59 commit af4c2b8
Show file tree
Hide file tree
Showing 27 changed files with 225 additions and 119 deletions.
1 change: 1 addition & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.github.michaelbull.result.Ok
import com.zsoltbertalan.flickslate.search.domain.api.GenreRepository
import com.zsoltbertalan.flickslate.search.domain.api.SearchRepository
import com.zsoltbertalan.flickslate.search.repository.SearchRepositoryModule
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import com.zsoltbertalan.flickslate.shared.testhelper.GenreMother
import dagger.Module
import dagger.Provides
Expand All @@ -22,7 +23,7 @@ class MockSearchRepositoryModule {
@Singleton
fun provideGenreRepository(): GenreRepository {
return mockk {
coEvery { getGenresList() } returns flowOf(Ok(GenreMother.createGenreList()))
coEvery { getGenresList() } returns flowOf(Ok(GenresReply( GenreMother.createGenreList())))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.zsoltbertalan.flickslate.movies.data.network.model

import com.zsoltbertalan.flickslate.movies.domain.model.MovieDetail
import com.zsoltbertalan.flickslate.search.data.network.model.GenreDto
import com.zsoltbertalan.flickslate.search.data.network.model.toGenreList
import com.zsoltbertalan.flickslate.search.data.network.model.toGenresReply
import kotlinx.serialization.Serializable

@Suppress("PropertyName", "ConstructorParameterNaming")
Expand Down Expand Up @@ -31,5 +31,5 @@ fun MovieDetailsDto.toMovieDetail() = MovieDetail(
this.vote_average,
this.poster_path,
this.backdrop_path,
this.genres.toGenreList(),
this.genres.toGenresReply(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.zsoltbertalan.flickslate.search.data

import com.zsoltbertalan.flickslate.search.data.api.GenreDataSource
import com.zsoltbertalan.flickslate.search.data.api.GenreMoviesDataSource
import com.zsoltbertalan.flickslate.search.data.db.GenreDao
import com.zsoltbertalan.flickslate.search.data.db.GenreMoviesDao
import com.zsoltbertalan.flickslate.search.data.network.GenreMoviesRemoteDataSource
import com.zsoltbertalan.flickslate.search.data.network.GenreRemoteDataSource
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
interface SearchDataModule {

@Binds
fun bindGenreDataSource(genreDao: GenreDao): GenreDataSource.Local

@Binds
fun bindGenreRemoteDataSource(genreRemoteDataSource: GenreRemoteDataSource): GenreDataSource.Remote

@Binds
fun bindGenreMoviesDataSource(genreMoviesDao: GenreMoviesDao): GenreMoviesDataSource.Local

@Binds
fun bindGenreMoviesRemoteDataSource(
genreMoviesRemoteDataSource: GenreMoviesRemoteDataSource
): GenreMoviesDataSource.Remote

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.zsoltbertalan.flickslate.search.data.api

import com.zsoltbertalan.flickslate.shared.domain.model.Genre
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import com.zsoltbertalan.flickslate.shared.util.Outcome
import kotlinx.coroutines.flow.Flow

interface GenreDataSource {

interface Local {

suspend fun purgeDatabase()

suspend fun insertGenres(genres: List<Genre>)

suspend fun insertEtag(etag: String)

suspend fun getEtag(): String

fun getGenres(): Flow<GenresReply>

fun getGenre(id: String): Genre

}

interface Remote {

suspend fun getGenres(etag: String): Outcome<GenresReply>

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.zsoltbertalan.flickslate.search.data.api

import com.zsoltbertalan.flickslate.movies.domain.model.Movie
import com.zsoltbertalan.flickslate.shared.domain.model.PageData
import com.zsoltbertalan.flickslate.shared.domain.model.PagingReply
import com.zsoltbertalan.flickslate.shared.util.Outcome
import kotlinx.coroutines.flow.Flow

interface GenreMoviesDataSource {

interface Local {

suspend fun purgeDatabase()

suspend fun insertGenreMovies(movies: List<Movie>, page: Int)

suspend fun insertGenreMoviesPageData(page: PageData)

fun getGenreMovies(page: Int): Flow<PagingReply<Movie>?>

}

interface Remote {

suspend fun getGenreMovies(genreId: Int, page: Int?): Outcome<PagingReply<Movie>>

}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.zsoltbertalan.flickslate.search.data.db

import com.zsoltbertalan.flickslate.search.data.api.GenreDataSource
import com.zsoltbertalan.flickslate.shared.async.IoDispatcher
import com.zsoltbertalan.flickslate.shared.domain.model.Genre
import com.zsoltbertalan.flickslate.search.data.db.model.EtagDbo
import com.zsoltbertalan.flickslate.search.data.db.model.GenreDbo
import com.zsoltbertalan.flickslate.search.data.db.model.toDbo
import com.zsoltbertalan.flickslate.search.data.db.model.toGenre
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import io.realm.kotlin.Realm
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query
Expand All @@ -21,7 +23,7 @@ import javax.inject.Singleton
class GenreDao @Inject constructor(
private val realm: Realm,
@IoDispatcher private val ioContext: CoroutineDispatcher,
) : GenreDataSource {
) : GenreDataSource.Local {

override suspend fun purgeDatabase() {
realm.write {
Expand All @@ -42,13 +44,17 @@ class GenreDao @Inject constructor(
}
}

override suspend fun getEtag(): String = withContext(ioContext){
override suspend fun getEtag(): String = withContext(ioContext) {
return@withContext realm.query<EtagDbo>("id = $0", "genres").first().find()?.etag ?: ""
}

override fun getGenres(): Flow<List<Genre>> {
return realm.query(GenreDbo::class).asFlow().map { dbo -> dbo.list.map { it.toGenre() } }.flowOn(ioContext)
}
override fun getGenres(): Flow<GenresReply> =
realm.query(GenreDbo::class)
.asFlow()
.map { dbo ->
val etag = getEtag()
GenresReply(dbo.list.map { it.toGenre() }, etag)
}.flowOn(ioContext)

override fun getGenre(id: String): Genre {
return realm.query<GenreDbo>("id = $0", id).first().find()?.toGenre() ?: Genre()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.zsoltbertalan.flickslate.search.data.db
import com.zsoltbertalan.flickslate.shared.async.IoDispatcher
import com.zsoltbertalan.flickslate.shared.util.runCatchingUnit
import com.zsoltbertalan.flickslate.movies.domain.model.Movie
import com.zsoltbertalan.flickslate.search.data.api.GenreMoviesDataSource
import com.zsoltbertalan.flickslate.shared.domain.model.PageData
import com.zsoltbertalan.flickslate.shared.domain.model.PagingReply
import com.zsoltbertalan.flickslate.search.data.db.model.GenreMovieDbo
Expand All @@ -24,7 +25,7 @@ import javax.inject.Singleton
class GenreMoviesDao @Inject constructor(
private val realm: Realm,
@IoDispatcher private val ioContext: CoroutineDispatcher,
) : GenreMoviesDataSource {
) : GenreMoviesDataSource.Local {

override suspend fun purgeDatabase() {
realm.write {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.zsoltbertalan.flickslate.search.data.network

import com.zsoltbertalan.flickslate.movies.data.network.model.MoviesReplyDto
import com.zsoltbertalan.flickslate.movies.data.network.model.toMoviesReply
import com.zsoltbertalan.flickslate.movies.domain.model.Movie
import com.zsoltbertalan.flickslate.search.data.api.GenreMoviesDataSource
import com.zsoltbertalan.flickslate.shared.domain.model.PagingReply
import com.zsoltbertalan.flickslate.shared.util.Outcome
import com.zsoltbertalan.flickslate.shared.util.safeCallWithMetadata
import retrofit2.Response
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class GenreMoviesRemoteDataSource @Inject constructor(
private val searchService: SearchService
) : GenreMoviesDataSource.Remote {

override suspend fun getGenreMovies(genreId: Int, page: Int?): Outcome<PagingReply<Movie>> {
return safeCallWithMetadata(
{ searchService.getGenreMovie(withGenres = genreId, page = page) },
Response<MoviesReplyDto>::toMoviesReply
)
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.zsoltbertalan.flickslate.search.data.network

import com.zsoltbertalan.flickslate.search.data.api.GenreDataSource
import com.zsoltbertalan.flickslate.search.data.network.model.GenreReplyDto
import com.zsoltbertalan.flickslate.search.data.network.model.toGenresReply
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import com.zsoltbertalan.flickslate.shared.util.Outcome
import com.zsoltbertalan.flickslate.shared.util.safeCallWithMetadata
import retrofit2.Response
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class GenreRemoteDataSource @Inject constructor(
private val searchService: SearchService
) : GenreDataSource.Remote {

override suspend fun getGenres(etag: String): Outcome<GenresReply> {
return safeCallWithMetadata(
{ searchService.getGenres(ifNoneMatch = etag) },
Response<GenreReplyDto>::toGenresReply
)
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package com.zsoltbertalan.flickslate.search.data.network
import com.zsoltbertalan.flickslate.BuildConfig
import com.zsoltbertalan.flickslate.movies.data.network.model.MoviesReplyDto
import com.zsoltbertalan.flickslate.search.data.network.model.GenreReplyDto
import com.zsoltbertalan.flickslate.tv.data.network.URL_DISCOVER_MOVIE
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

const val URL_GENRE = "genre/movie/list"
const val URL_MOVIES_SEARCH = "search/movie"
const val URL_DISCOVER_MOVIE = "discover/movie"

interface SearchService {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.zsoltbertalan.flickslate.search.data.network.model
import com.babestudios.base.data.mapNullInputList
import com.zsoltbertalan.flickslate.shared.domain.model.Genre
import kotlinx.serialization.Serializable
import retrofit2.Response

@Serializable
data class GenreDto(
Expand All @@ -12,4 +13,4 @@ data class GenreDto(

fun GenreDto.toGenre(): Genre = Genre(this.id, this.name)

fun List<GenreDto>?.toGenreList(): List<Genre> = mapNullInputList(this) { genre -> genre.toGenre() }
fun List<GenreDto>?.toGenresReply(): List<Genre> = mapNullInputList(this) { genre -> genre.toGenre() }
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package com.zsoltbertalan.flickslate.search.data.network.model

import com.babestudios.base.data.mapNullInputList
import com.zsoltbertalan.flickslate.movies.data.network.model.toMoviesReply
import com.zsoltbertalan.flickslate.shared.domain.model.Genre
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import kotlinx.serialization.Serializable
import retrofit2.Response

@Serializable
data class GenreReplyDto(
val genres: List<GenreDto> = emptyList(),
)

fun GenreReplyDto.toGenres(): List<Genre> = this.genres.toGenreList()
fun GenreReplyDto.toGenres(): List<Genre> = this.genres.toGenresReply()

fun Response<GenreReplyDto>.toGenresReply(): GenresReply {
val body = this.body()!!
val genres = body.genres
val etag = this.headers()["etag"] ?: ""
return GenresReply(genres.map { it.toGenre() }, etag)
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.zsoltbertalan.flickslate.search.domain.api

import com.zsoltbertalan.flickslate.shared.util.Outcome
import com.zsoltbertalan.flickslate.shared.domain.model.Genre
import com.zsoltbertalan.flickslate.movies.domain.model.Movie
import com.zsoltbertalan.flickslate.shared.domain.model.GenresReply
import com.zsoltbertalan.flickslate.shared.domain.model.PagingReply
import com.zsoltbertalan.flickslate.shared.util.Outcome
import kotlinx.coroutines.flow.Flow

interface GenreRepository {

fun getGenresList(): Flow<Outcome<List<Genre>>>
fun getGenresList(): Flow<Outcome<GenresReply>>
fun getGenreDetail(genreId: Int, page: Int): Flow<Outcome<PagingReply<Movie>>>

}
Loading

0 comments on commit af4c2b8

Please sign in to comment.