Compare commits
	
		
			1 Commits
		
	
	
		
			develop
			...
			feature/er
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 3490ee7514 | 
| @@ -4,6 +4,6 @@ | ||||
|     android:viewportWidth="960" | ||||
|     android:viewportHeight="960"> | ||||
|     <path | ||||
|       android:pathData="M280,560h400q17,0 28.5,-11.5T720,520q0,-17 -11.5,-28.5T680,480L280,480q-17,0 -28.5,11.5T240,520q0,17 11.5,28.5T280,560ZM280,440h400q17,0 28.5,-11.5T720,400q0,-17 -11.5,-28.5T680,360L280,360q-17,0 -28.5,11.5T240,400q0,17 11.5,28.5T280,440ZM280,320h400q17,0 28.5,-11.5T720,280q0,-17 -11.5,-28.5T680,240L280,240q-17,0 -28.5,11.5T240,280q0,17 11.5,28.5T280,320ZM160,720q-33,0 -56.5,-23.5T80,640v-480q0,-33 23.5,-56.5T160,80h640q33,0 56.5,23.5T880,160v623q0,27 -24.5,37.5T812,812l-92,-92L160,720ZM754,640 L800,685v-525L160,160v480h594ZM160,640v-480,480Z" | ||||
|       android:fillColor="#5f6368"/> | ||||
|         android:fillColor="#5f6368" | ||||
|         android:pathData="M280,560h400q17,0 28.5,-11.5T720,520q0,-17 -11.5,-28.5T680,480L280,480q-17,0 -28.5,11.5T240,520q0,17 11.5,28.5T280,560ZM280,440h400q17,0 28.5,-11.5T720,400q0,-17 -11.5,-28.5T680,360L280,360q-17,0 -28.5,11.5T240,400q0,17 11.5,28.5T280,440ZM280,320h400q17,0 28.5,-11.5T720,280q0,-17 -11.5,-28.5T680,240L280,240q-17,0 -28.5,11.5T240,280q0,17 11.5,28.5T280,320ZM160,720q-33,0 -56.5,-23.5T80,640v-480q0,-33 23.5,-56.5T160,80h640q33,0 56.5,23.5T880,160v623q0,27 -24.5,37.5T812,812l-92,-92L160,720ZM754,640 L800,685v-525L160,160v480h594ZM160,640v-480,480Z" /> | ||||
| </vector> | ||||
|   | ||||
| @@ -4,6 +4,6 @@ | ||||
|     android:viewportWidth="960" | ||||
|     android:viewportHeight="960"> | ||||
|     <path | ||||
|       android:pathData="M480,623q-8,0 -15,-2.5t-13,-8.5L308,468q-12,-12 -11.5,-28t11.5,-28q12,-12 28.5,-12.5T365,411l75,75v-286q0,-17 11.5,-28.5T480,160q17,0 28.5,11.5T520,200v286l75,-75q12,-12 28.5,-11.5T652,412q11,12 11.5,28T652,468L508,612q-6,6 -13,8.5t-15,2.5ZM240,800q-33,0 -56.5,-23.5T160,720v-80q0,-17 11.5,-28.5T200,600q17,0 28.5,11.5T240,640v80h480v-80q0,-17 11.5,-28.5T760,600q17,0 28.5,11.5T800,640v80q0,33 -23.5,56.5T720,800L240,800Z" | ||||
|       android:fillColor="#5f6368"/> | ||||
|         android:fillColor="#5f6368" | ||||
|         android:pathData="M480,623q-8,0 -15,-2.5t-13,-8.5L308,468q-12,-12 -11.5,-28t11.5,-28q12,-12 28.5,-12.5T365,411l75,75v-286q0,-17 11.5,-28.5T480,160q17,0 28.5,11.5T520,200v286l75,-75q12,-12 28.5,-11.5T652,412q11,12 11.5,28T652,468L508,612q-6,6 -13,8.5t-15,2.5ZM240,800q-33,0 -56.5,-23.5T160,720v-80q0,-17 11.5,-28.5T200,600q17,0 28.5,11.5T240,640v80h480v-80q0,-17 11.5,-28.5T760,600q17,0 28.5,11.5T800,640v80q0,33 -23.5,56.5T720,800L240,800Z" /> | ||||
| </vector> | ||||
|   | ||||
| @@ -25,6 +25,8 @@ android { | ||||
| dependencies { | ||||
|     implementation(libs.androidx.paging.compose) | ||||
|  | ||||
|  | ||||
|     //Kotlin Serialization | ||||
|     implementation(libs.kotlinx.serialization.json) | ||||
|  | ||||
|     //Ktor | ||||
|   | ||||
| @@ -0,0 +1,8 @@ | ||||
| package dev.adriankuta.pixabay.data | ||||
|  | ||||
| fun <T> Result<T>.isSuccess() = this is Result.Success<T> | ||||
|  | ||||
| sealed interface Result<out T> { | ||||
|     data class Success<out T>(val data: T) : Result<T> | ||||
|     data class Error(val exception: Throwable) : Result<Nothing> | ||||
| } | ||||
| @@ -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 | ||||
|         } | ||||
|  | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -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) | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| package dev.adriankuta.pixabay.data.dto.response | ||||
|  | ||||
| import io.ktor.resources.Resource | ||||
| import kotlinx.serialization.Serializable | ||||
|  | ||||
| @Serializable | ||||
|   | ||||
| @@ -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<PixabayImage> | ||||
|  | ||||
|     suspend fun searchImages(query: String, page: Int, pageSize: Int): List<PixabayImage> | ||||
|     suspend fun searchImages(query: String, page: Int, pageSize: Int): Result<List<PixabayImage>> | ||||
|  | ||||
|     fun getSearchResultStream(query: String): Flow<PagingData<PixabayImage>> | ||||
| } | ||||
| @@ -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<PixabayImage> { | ||||
|         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<PixabayImage> { | ||||
|     override suspend fun searchImages( | ||||
|         query: String, | ||||
|         page: Int, | ||||
|         pageSize: Int | ||||
|     ): Result<List<PixabayImage>> { | ||||
|         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<PagingData<PixabayImage>> { | ||||
|   | ||||
| @@ -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), | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -1,7 +1,5 @@ | ||||
| package dev.adriankuta.pixabay.feature.search | ||||
|  | ||||
| import dev.adriankuta.pixabay.data.model.PixabayImage | ||||
|  | ||||
|  | ||||
| data class SearchUiState( | ||||
|     val query: String = "" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user