diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..56a1a9a --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +Pixabay \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b589d56 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..3d2d36b --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..6109387 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,39 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6806f5a --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,53 @@ + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..148fdd2 --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0ad17cb --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/build-logic/.gitignore b/build-logic/.gitignore new file mode 100644 index 0000000..ac96206 --- /dev/null +++ b/build-logic/.gitignore @@ -0,0 +1 @@ +.gradle/ \ No newline at end of file diff --git a/build-logic/.gradle/8.7/executionHistory/executionHistory.bin b/build-logic/.gradle/8.7/executionHistory/executionHistory.bin deleted file mode 100644 index 04641e1..0000000 Binary files a/build-logic/.gradle/8.7/executionHistory/executionHistory.bin and /dev/null differ diff --git a/build-logic/.gradle/8.7/executionHistory/executionHistory.lock b/build-logic/.gradle/8.7/executionHistory/executionHistory.lock deleted file mode 100644 index 50d326c..0000000 Binary files a/build-logic/.gradle/8.7/executionHistory/executionHistory.lock and /dev/null differ diff --git a/build-logic/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/build-logic/.gradle/buildOutputCleanup/buildOutputCleanup.lock deleted file mode 100644 index 7cbd852..0000000 Binary files a/build-logic/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ diff --git a/build-logic/.gradle/buildOutputCleanup/cache.properties b/build-logic/.gradle/buildOutputCleanup/cache.properties deleted file mode 100644 index c70171b..0000000 --- a/build-logic/.gradle/buildOutputCleanup/cache.properties +++ /dev/null @@ -1,2 +0,0 @@ -#Wed Jul 24 13:11:02 CEST 2024 -gradle.version=8.7 diff --git a/build-logic/.gradle/buildOutputCleanup/outputFiles.bin b/build-logic/.gradle/buildOutputCleanup/outputFiles.bin deleted file mode 100644 index 8e9a042..0000000 Binary files a/build-logic/.gradle/buildOutputCleanup/outputFiles.bin and /dev/null differ diff --git a/build-logic/.gradle/file-system.probe b/build-logic/.gradle/file-system.probe deleted file mode 100644 index 7d504d7..0000000 Binary files a/build-logic/.gradle/file-system.probe and /dev/null differ diff --git a/core/ui/src/main/kotlin/dev/adriankuta/pixabay/core/ui/SearchField.kt b/core/ui/src/main/kotlin/dev/adriankuta/pixabay/core/ui/SearchField.kt index 5a385b7..379c08f 100644 --- a/core/ui/src/main/kotlin/dev/adriankuta/pixabay/core/ui/SearchField.kt +++ b/core/ui/src/main/kotlin/dev/adriankuta/pixabay/core/ui/SearchField.kt @@ -23,6 +23,7 @@ fun SearchField( value = query, onValueChange = onQueryChange, modifier = modifier, + maxLines = 1, placeholder = { if (hint != null) { Text(text = hint) diff --git a/data/build.gradle.kts b/data/build.gradle.kts index b7b975d..3c29364 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -1,3 +1,5 @@ +import java.util.Properties + @Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { alias(libs.plugins.convention.android.library) @@ -9,10 +11,15 @@ android { buildFeatures { buildConfig = true } - defaultConfig { - buildConfigField("String", "PIXABAY_API_KEY", "\"\"") + val localPropertiesFile = project.rootProject.file("local.properties") + val properties = Properties() + properties.load(localPropertiesFile.inputStream()) + + val apiKey = properties.getProperty("PIXABAY_API_KEY") ?: "" + buildConfigField("String", "PIXABAY_API_KEY", "\"$apiKey\"") } + } dependencies { 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 0de1b41..d02fa8f 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 @@ -9,10 +9,13 @@ 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) @Module internal class PersistanceModule { + + @Singleton @Provides fun provideRoomDb(@ApplicationContext context: Context): AppDatabase { return Room.databaseBuilder( 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 7cfc6a8..d910c2a 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 @@ -75,6 +75,6 @@ internal class PixabayImageRepository @Inject constructor( companion object { const val NETWORK_PAGE_SIZE = 30 - const val USE_CACHE_PAGER = false + const val USE_CACHE_PAGER = true } } \ No newline at end of file diff --git a/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailRoute.kt b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailRoute.kt index 7761499..9a704db 100644 --- a/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailRoute.kt +++ b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/PhotoDetailRoute.kt @@ -14,7 +14,6 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -34,6 +33,7 @@ import dev.adriankuta.pixabay.core.ui.R.drawable import dev.adriankuta.pixabay.core.ui.R.string import dev.adriankuta.pixabay.core.ui.StatsItem import dev.adriankuta.pixabay.data.model.PixabayImage +import dev.adriankuta.pixabay.feature.details.di.PhotoDetailsViewModelFactory @Composable @@ -41,15 +41,15 @@ fun PhotoDetailRoute( photoId: Int, onBack: () -> Unit, modifier: Modifier = Modifier, - viewModel: PhotoDetailViewModel = hiltViewModel() + viewModel: PhotoDetailViewModel = hiltViewModel( + creationCallback = { factory: PhotoDetailsViewModelFactory -> + factory.create(photoId) + } + ) ) { val uiState by viewModel.uiState.collectAsState() - LaunchedEffect(photoId) { - viewModel.loadImage(photoId) - } - PhotoDetailScreen( state = uiState, modifier = modifier 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 91db8c6..02b1794 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 @@ -1,31 +1,26 @@ -@file:OptIn(ExperimentalCoroutinesApi::class) - package dev.adriankuta.pixabay.feature.details import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject import dagger.hilt.android.lifecycle.HiltViewModel import dev.adriankuta.pixabay.data.repository.ImageRepository -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.MutableStateFlow +import dev.adriankuta.pixabay.feature.details.di.PhotoDetailsViewModelFactory import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.filterNotNull +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import javax.inject.Inject -@HiltViewModel -class PhotoDetailViewModel @Inject constructor( - private val imageRepository: ImageRepository +@HiltViewModel(assistedFactory = PhotoDetailsViewModelFactory::class) +class PhotoDetailViewModel @AssistedInject constructor( + private val imageRepository: ImageRepository, + @Assisted private val imageId: Int ) : ViewModel() { - private val _idToLoad = MutableStateFlow(null) - - private val loadedData = _idToLoad - .filterNotNull() - .map { id -> - imageRepository.searchImageById(id) - } + private val loadedData = flow { + emit(imageRepository.searchImageById(imageId)) + } val uiState = loadedData .map { PhotoDetailUiState.Success(it) } @@ -34,9 +29,4 @@ class PhotoDetailViewModel @Inject constructor( started = SharingStarted.WhileSubscribed(stopTimeoutMillis = 5000), initialValue = PhotoDetailUiState.Loading ) - - - fun loadImage(id: Int) { - _idToLoad.value = id - } } \ No newline at end of file diff --git a/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/di/PhotoDetailsViewModelFactory.kt b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/di/PhotoDetailsViewModelFactory.kt new file mode 100644 index 0000000..42e05fc --- /dev/null +++ b/feature/details/src/main/kotlin/dev/adriankuta/pixabay/feature/details/di/PhotoDetailsViewModelFactory.kt @@ -0,0 +1,9 @@ +package dev.adriankuta.pixabay.feature.details.di + +import dagger.assisted.AssistedFactory +import dev.adriankuta.pixabay.feature.details.PhotoDetailViewModel + +@AssistedFactory +internal interface PhotoDetailsViewModelFactory { + fun create(imageId: Int): PhotoDetailViewModel +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 27ef67e..3aecf0c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,13 +1,13 @@ [versions] androidxNavigation = "2.7.7" androidGradlePlugin = "8.1.4" -agp = "8.6.0-beta01" +agp = "8.6.0-beta02" coilCompose = "2.6.0" composeCompiler = "1.5.14" kotlin = "1.9.24" kotlinSerialization = "2.0.0" coreKtx = "1.13.1" -androidxHilt = "1.0.0" +androidxHilt = "1.2.0" junit = "4.13.2" junitVersion = "1.2.1" espressoCore = "3.6.1"