diff --git a/core/ui/src/main/res/drawable/ic_comment.xml b/core/ui/src/main/res/drawable/ic_comment.xml index 948e187..23c59dc 100644 --- a/core/ui/src/main/res/drawable/ic_comment.xml +++ b/core/ui/src/main/res/drawable/ic_comment.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="960" android:viewportHeight="960"> - + diff --git a/core/ui/src/main/res/drawable/ic_download.xml b/core/ui/src/main/res/drawable/ic_download.xml index 6c95661..e815f15 100644 --- a/core/ui/src/main/res/drawable/ic_download.xml +++ b/core/ui/src/main/res/drawable/ic_download.xml @@ -3,7 +3,7 @@ android:height="24dp" android:viewportWidth="960" android:viewportHeight="960"> - + diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 1f49072..d0d1bcd 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -25,6 +25,8 @@ android { dependencies { implementation(libs.androidx.paging.compose) + + //Kotlin Serialization implementation(libs.kotlinx.serialization.json) //Ktor diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/Result.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/Result.kt new file mode 100644 index 0000000..d9d1a75 --- /dev/null +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/Result.kt @@ -0,0 +1,8 @@ +package dev.adriankuta.pixabay.data + +fun Result.isSuccess() = this is Result.Success + +sealed interface Result { + data class Success(val data: T) : Result + data class Error(val exception: Throwable) : Result +} \ No newline at end of file diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/NetworkModule.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/NetworkModule.kt index 0e0e7b7..26ebed1 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/NetworkModule.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/NetworkModule.kt @@ -31,7 +31,7 @@ internal abstract class NetworkModule { @Singleton @Provides fun provideKtorClient(): HttpClient { - val httpClient = HttpClient(Android) { + return HttpClient(Android) { install(ContentNegotiation) { json( Json { @@ -53,8 +53,6 @@ internal abstract class NetworkModule { socketTimeout = 100_000 } } - return httpClient } - } } \ No newline at end of file diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/PersistanceModule.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/PersistanceModule.kt index d02fa8f..6d720e4 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/PersistanceModule.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/di/PersistanceModule.kt @@ -8,7 +8,6 @@ import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import dev.adriankuta.pixabay.data.room.AppDatabase -import dev.adriankuta.pixabay.data.room.dao.PixabayImagesDao import javax.inject.Singleton @InstallIn(SingletonComponent::class) diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/dto/response/SearchPixabayImagesResponse.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/dto/response/SearchPixabayImagesResponse.kt index b1f2112..f94be5f 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/dto/response/SearchPixabayImagesResponse.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/dto/response/SearchPixabayImagesResponse.kt @@ -1,6 +1,5 @@ package dev.adriankuta.pixabay.data.dto.response -import io.ktor.resources.Resource import kotlinx.serialization.Serializable @Serializable diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/ImageRepository.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/ImageRepository.kt index e590ca6..bb43236 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/ImageRepository.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/ImageRepository.kt @@ -1,14 +1,15 @@ package dev.adriankuta.pixabay.data.repository import androidx.paging.PagingData +import dev.adriankuta.pixabay.data.Result import dev.adriankuta.pixabay.data.model.PixabayImage import kotlinx.coroutines.flow.Flow interface ImageRepository { - suspend fun searchImageById(id: Int): PixabayImage + suspend fun searchImageById(id: Int): Result - suspend fun searchImages(query: String, page: Int, pageSize: Int): List + suspend fun searchImages(query: String, page: Int, pageSize: Int): Result> fun getSearchResultStream(query: String): Flow> } \ No newline at end of file diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/PixabayImageRepository.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/PixabayImageRepository.kt index 1bed424..90686e1 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/PixabayImageRepository.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/repository/PixabayImageRepository.kt @@ -7,6 +7,7 @@ import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData import androidx.paging.map +import dev.adriankuta.pixabay.data.Result import dev.adriankuta.pixabay.data.model.PixabayImage import dev.adriankuta.pixabay.data.network.PixabayService import dev.adriankuta.pixabay.data.paging.PixabayPagingSource @@ -16,31 +17,38 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import timber.log.Timber import javax.inject.Inject -import javax.inject.Named internal class PixabayImageRepository @Inject constructor( private val database: AppDatabase, private val pixabayService: PixabayService ) : ImageRepository { - override suspend fun searchImageById(id: Int): PixabayImage { + override suspend fun searchImageById(id: Int): Result { return runCatching { pixabayService.searchImageById(id.toString()) }.mapCatching { response -> - PixabayImage(response.hits.first()) + Result.Success(PixabayImage(response.hits.first())) }.onFailure { e -> Timber.e(e) - }.getOrThrow() + }.getOrElse { + Result.Error(it) + } } - override suspend fun searchImages(query: String, page: Int, pageSize: Int): List { + override suspend fun searchImages( + query: String, + page: Int, + pageSize: Int + ): Result> { return runCatching { pixabayService.searchImages(query, page, pageSize) }.mapCatching { response -> - response.hits.map { PixabayImage(it) } + Result.Success(response.hits.map { PixabayImage(it) }) }.onFailure { e -> Timber.e(e) - }.getOrThrow() + }.getOrElse { + Result.Error(it) + } } override fun getSearchResultStream(query: String): Flow> { diff --git a/data/src/main/kotlin/dev/adriankuta/pixabay/data/room/entity/PixabayImageEntity.kt b/data/src/main/kotlin/dev/adriankuta/pixabay/data/room/entity/PixabayImageEntity.kt index f960521..1ae0514 100644 --- a/data/src/main/kotlin/dev/adriankuta/pixabay/data/room/entity/PixabayImageEntity.kt +++ b/data/src/main/kotlin/dev/adriankuta/pixabay/data/room/entity/PixabayImageEntity.kt @@ -33,7 +33,7 @@ internal data class PixabayImageEntity( @ColumnInfo(COLUMN_USER) val user: String, @ColumnInfo(COLUMN_USER_IMAGE_URL) val userImageURL: String, -) { + ) { constructor(pixabayImageResponse: PixabayImageResponse, queryUsed: String) : this( id = pixabayImageResponse.id, diff --git a/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailViewModel.kt b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailViewModel.kt index 02b1794..f390458 100644 --- a/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailViewModel.kt +++ b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import dagger.assisted.Assisted import dagger.assisted.AssistedInject import dagger.hilt.android.lifecycle.HiltViewModel +import dev.adriankuta.pixabay.data.Result import dev.adriankuta.pixabay.data.repository.ImageRepository import dev.adriankuta.pixabay.feature.details.di.PhotoDetailsViewModelFactory import kotlinx.coroutines.flow.SharingStarted @@ -23,7 +24,12 @@ class PhotoDetailViewModel @AssistedInject constructor( } val uiState = loadedData - .map { PhotoDetailUiState.Success(it) } + .map { + when (it) { + is Result.Success -> PhotoDetailUiState.Success(it.data) + is Result.Error -> PhotoDetailUiState.Error + } + } .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000), diff --git a/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchRoute.kt b/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchRoute.kt index 2d8b1a8..abd2a98 100644 --- a/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchRoute.kt +++ b/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchRoute.kt @@ -17,7 +17,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.paging.LoadState diff --git a/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchUiState.kt b/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchUiState.kt index ff087c9..7791de4 100644 --- a/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchUiState.kt +++ b/feature/search/src/main/kotlin/dev/adriankuta/pixabay/feature/search/SearchUiState.kt @@ -1,7 +1,5 @@ package dev.adriankuta.pixabay.feature.search -import dev.adriankuta.pixabay.data.model.PixabayImage - data class SearchUiState( val query: String = ""