diff --git a/common/src/main/java/com/github/sikv/photos/common/ActivityPermissionManager.kt b/common/src/main/java/com/github/sikv/photos/common/ActivityPermissionManager.kt
index a140f8d1..151689f9 100644
--- a/common/src/main/java/com/github/sikv/photos/common/ActivityPermissionManager.kt
+++ b/common/src/main/java/com/github/sikv/photos/common/ActivityPermissionManager.kt
@@ -2,13 +2,13 @@ package com.github.sikv.photos.common
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
-import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.util.UUID
class ActivityPermissionManager(
- private val activity: AppCompatActivity
+ private val activity: FragmentActivity
) : DefaultLifecycleObserver {
private val key = UUID.randomUUID().toString()
diff --git a/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/DynamicPhotoItem.kt b/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/DynamicPhotoItem.kt
new file mode 100644
index 00000000..544d2436
--- /dev/null
+++ b/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/DynamicPhotoItem.kt
@@ -0,0 +1,53 @@
+package com.github.sikv.photos.compose.ui
+
+import androidx.compose.runtime.Composable
+import com.github.sikv.photos.domain.ListLayout
+import com.github.sikv.photos.domain.Photo
+
+@Composable
+fun DynamicPhotoItem(
+ photo: Photo,
+ isFavorite: Boolean,
+ listLayout: ListLayout,
+ onPhotoClick: (Photo) -> Unit,
+ onPhotoAttributionClick: (Photo) -> Unit,
+ onPhotoActionsClick: (Photo) -> Unit,
+ onToggleFavoriteClick: (Photo) -> Unit,
+ onSharePhotoClick: (Photo) -> Unit,
+ onDownloadPhotoClick: (Photo) -> Unit
+) {
+ when (listLayout) {
+ ListLayout.LIST -> {
+ PhotoItem(
+ photo = photo,
+ isFavorite = isFavorite,
+ onClick = {
+ onPhotoClick(photo)
+ },
+ onAttributionClick = {
+ onPhotoAttributionClick(photo)
+ },
+ onMoreClick = {
+ onPhotoActionsClick(photo)
+ },
+ onToggleFavorite = {
+ onToggleFavoriteClick(photo)
+ },
+ onShareClick = {
+ onSharePhotoClick(photo)
+ },
+ onDownloadClick = {
+ onDownloadPhotoClick(photo)
+ }
+ )
+ }
+ ListLayout.GRID -> {
+ PhotoItemCompact(
+ photo = photo,
+ onClick = {
+ onPhotoClick(photo)
+ }
+ )
+ }
+ }
+}
diff --git a/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/SwitchLayoutAction.kt b/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/SwitchLayoutAction.kt
new file mode 100644
index 00000000..e152500e
--- /dev/null
+++ b/compose-ui/src/main/java/com/github/sikv/photos/compose/ui/SwitchLayoutAction.kt
@@ -0,0 +1,28 @@
+package com.github.sikv.photos.compose.ui
+
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import com.github.sikv.photos.domain.ListLayout
+
+@Composable
+fun SwitchLayoutAction(
+ listLayout: ListLayout,
+ onSwitchLayoutClick: () -> Unit
+) {
+ val icon = when (listLayout) {
+ ListLayout.LIST -> R.drawable.ic_view_grid_24dp
+ ListLayout.GRID -> R.drawable.ic_view_list_24dp
+ }
+
+ IconButton(
+ onClick = onSwitchLayoutClick
+ ) {
+ Icon(
+ painter = painterResource(id = icon),
+ contentDescription = stringResource(id = R.string.switch_layout)
+ )
+ }
+}
diff --git a/compose-ui/src/main/res/values/strings.xml b/compose-ui/src/main/res/values/strings.xml
index d85896a3..7c240ac7 100644
--- a/compose-ui/src/main/res/values/strings.xml
+++ b/compose-ui/src/main/res/values/strings.xml
@@ -4,4 +4,5 @@
Share
Download
More
+ Switch layout
diff --git a/feature/curated-photos/build.gradle b/feature/curated-photos/build.gradle
index 3ae5755c..a329f25e 100644
--- a/feature/curated-photos/build.gradle
+++ b/feature/curated-photos/build.gradle
@@ -40,6 +40,7 @@ dependencies {
implementation libs.inject
kapt libs.hilt.compiler
implementation libs.hilt.android
+ implementation libs.androidx.hilt.navigation.compose
implementation libs.androidx.paging.runtime
implementation libs.androidx.paging.compose
diff --git a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosFragment.kt b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosFragment.kt
index 21ed4212..fccc019f 100644
--- a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosFragment.kt
+++ b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosFragment.kt
@@ -6,8 +6,8 @@ import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
+import com.github.sikv.photo.usecase.PhotoActionsUseCase
import com.github.sikv.photos.navigation.args.PhotoDetailsFragmentArguments
import com.github.sikv.photos.navigation.route.PhotoDetailsRoute
import com.google.accompanist.themeadapter.material3.Mdc3Theme
@@ -20,7 +20,8 @@ class CuratedPhotosFragment : Fragment() {
@Inject
lateinit var photoDetailsRoute: PhotoDetailsRoute
- private val viewModel: CuratedPhotosViewModel by viewModels()
+ @Inject
+ lateinit var photoActionsUseCase: PhotoActionsUseCase
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
@@ -31,10 +32,19 @@ class CuratedPhotosFragment : Fragment() {
setContent {
Mdc3Theme {
CuratedPhotosScreen(
- onGoToPhotoDetails = { photo ->
+ onPhotoClick = { photo ->
photoDetailsRoute.present(findNavController(), PhotoDetailsFragmentArguments(photo))
},
- viewModel = viewModel
+ onPhotoAttributionClick = photoActionsUseCase::photoAttributionClick,
+ onPhotoActionsClick = { photo ->
+ photoActionsUseCase.openMoreActions(requireNotNull(activity), photo)
+ },
+ onSharePhotoClick = { photo ->
+ photoActionsUseCase.sharePhoto(requireNotNull(activity), photo)
+ },
+ onDownloadPhotoClick = { photo ->
+ photoActionsUseCase.downloadPhoto(requireNotNull(activity), photo)
+ }
)
}
}
diff --git a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosScreen.kt b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosScreen.kt
index c9d6860b..8878fbf3 100644
--- a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosScreen.kt
+++ b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosScreen.kt
@@ -2,29 +2,28 @@ package com.github.sikv.photos.curated
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
+import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.paging.compose.collectAsLazyPagingItems
-import com.github.sikv.photos.common.ui.findActivity
-import com.github.sikv.photos.compose.ui.PhotoItem
-import com.github.sikv.photos.compose.ui.PhotoItemCompact
+import com.github.sikv.photos.compose.ui.DynamicPhotoItem
import com.github.sikv.photos.compose.ui.Scaffold
-import com.github.sikv.photos.domain.ListLayout
+import com.github.sikv.photos.compose.ui.SwitchLayoutAction
import com.github.sikv.photos.domain.Photo
// TODO: Add loading indicator.
@Composable
internal fun CuratedPhotosScreen(
- onGoToPhotoDetails: (Photo) -> Unit,
- viewModel: CuratedPhotosViewModel,
+ onPhotoClick: (Photo) -> Unit,
+ onPhotoAttributionClick: (Photo) -> Unit,
+ onPhotoActionsClick: (Photo) -> Unit,
+ onSharePhotoClick: (Photo) -> Unit,
+ onDownloadPhotoClick: (Photo) -> Unit,
+ viewModel: CuratedPhotosViewModel = hiltViewModel(),
) {
val photos = viewModel.getCuratedPhotos().collectAsLazyPagingItems()
val listLayout by viewModel.listLayoutState.collectAsStateWithLifecycle()
@@ -32,7 +31,10 @@ internal fun CuratedPhotosScreen(
Scaffold(
title = { Text(stringResource(id = R.string.photos)) },
actions = {
- SwitchLayoutAction(viewModel = viewModel)
+ SwitchLayoutAction(
+ listLayout = listLayout,
+ onSwitchLayoutClick = viewModel::switchListLayout
+ )
}
) {
LazyVerticalGrid(
@@ -40,81 +42,21 @@ internal fun CuratedPhotosScreen(
) {
items(photos.itemCount) { index ->
photos[index]?.let { photo ->
- Photo(
+ val isFavorite by viewModel.isFavorite(photo).collectAsStateWithLifecycle(initialValue = false)
+
+ DynamicPhotoItem(
photo = photo,
+ isFavorite = isFavorite,
listLayout = listLayout,
- viewModel = viewModel,
- onGoToPhotoDetails = onGoToPhotoDetails
+ onPhotoClick = onPhotoClick,
+ onPhotoAttributionClick = onPhotoAttributionClick,
+ onPhotoActionsClick = onPhotoActionsClick,
+ onToggleFavoriteClick = viewModel::toggleFavorite,
+ onSharePhotoClick = onSharePhotoClick,
+ onDownloadPhotoClick = onDownloadPhotoClick
)
}
}
}
}
}
-
-@Composable
-private fun Photo(
- photo: Photo,
- listLayout: ListLayout,
- viewModel: CuratedPhotosViewModel,
- onGoToPhotoDetails: (Photo) -> Unit
-) {
- val context = LocalContext.current
- val isFavorite by viewModel.isFavorite(photo).collectAsStateWithLifecycle(initialValue = false)
-
- when (listLayout) {
- ListLayout.LIST -> {
- PhotoItem(
- photo = photo,
- isFavorite = isFavorite,
- onClick = {
- onGoToPhotoDetails(photo)
- },
- onAttributionClick = {
- viewModel.onPhotoAttributionClick(context.findActivity(), photo)
- },
- onMoreClick = {
- viewModel.openActions(context.findActivity(), photo)
- },
- onToggleFavorite = {
- viewModel.toggleFavorite(photo)
- },
- onShareClick = {
- viewModel.sharePhoto(context.findActivity(), photo)
- },
- onDownloadClick = {
- viewModel.downloadPhoto(context.findActivity(), photo)
- }
- )
- }
- ListLayout.GRID -> {
- PhotoItemCompact(
- photo = photo,
- onClick = {
- onGoToPhotoDetails(photo)
- }
- )
- }
- }
-}
-
-@Composable
-private fun SwitchLayoutAction(
- viewModel: CuratedPhotosViewModel
-) {
- val listLayout by viewModel.listLayoutState.collectAsStateWithLifecycle()
-
- val icon = when (listLayout) {
- ListLayout.LIST -> R.drawable.ic_view_grid_24dp
- ListLayout.GRID -> R.drawable.ic_view_list_24dp
- }
-
- IconButton(
- onClick = viewModel::switchListLayout
- ) {
- Icon(
- painter = painterResource(id = icon),
- contentDescription = stringResource(id = R.string.switch_layout)
- )
- }
-}
diff --git a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosViewModel.kt b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosViewModel.kt
index 6ecb8f71..581da073 100644
--- a/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosViewModel.kt
+++ b/feature/curated-photos/src/main/java/com/github/sikv/photos/curated/CuratedPhotosViewModel.kt
@@ -1,18 +1,12 @@
package com.github.sikv.photos.curated
-import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
-import com.github.sikv.photo.usecase.DownloadPhotoUseCase
-import com.github.sikv.photo.usecase.PhotoActionsUseCase
import com.github.sikv.photos.common.PreferencesService
-import com.github.sikv.photos.common.ui.openUrl
import com.github.sikv.photos.config.ConfigProvider
-import com.github.sikv.photos.data.createShareIntent
import com.github.sikv.photos.data.repository.FavoritesRepository2
import com.github.sikv.photos.data.repository.PhotosRepository
import com.github.sikv.photos.domain.ListLayout
@@ -30,9 +24,7 @@ internal class CuratedPhotosViewModel @Inject constructor(
private val photosRepository: PhotosRepository,
private val favoritesRepository: FavoritesRepository2,
private val preferencesService: PreferencesService,
- private val configProvider: ConfigProvider,
- private val photoActionsUseCase: PhotoActionsUseCase,
- private val downloadPhotoUseCase: DownloadPhotoUseCase
+ private val configProvider: ConfigProvider
) : ViewModel() {
private val mutableListLayoutState = MutableStateFlow(preferencesService.getCuratedListLayout())
@@ -51,40 +43,6 @@ internal class CuratedPhotosViewModel @Inject constructor(
}
}
- // TODO: This is temporary solution!
- // Will be refactored after migration to Compose Navigation is finished.
- fun onPhotoAttributionClick(activity: AppCompatActivity, photo: Photo) {
- photo.getPhotoPhotographerUrl()?.let { photographerUrl ->
- activity.openUrl(photographerUrl)
- } ?: run {
- activity.openUrl(photo.getPhotoShareUrl())
- }
- }
-
- // TODO: This is temporary solution!
- // Will be refactored after migration to Compose Navigation is finished.
- fun openActions(activity: AppCompatActivity, photo: Photo) {
- photoActionsUseCase.openActions(activity.supportFragmentManager, photo) { message ->
- Toast.makeText(activity, message, Toast.LENGTH_SHORT)
- .show()
- }
- }
-
- // TODO: This is temporary solution!
- // Will be refactored after migration to Compose Navigation is finished.
- fun downloadPhoto(activity: AppCompatActivity, photo: Photo) {
- downloadPhotoUseCase.download(activity, photo) { message ->
- Toast.makeText(activity, message, Toast.LENGTH_SHORT)
- .show()
- }
- }
-
- // TODO: This is temporary solution!
- // Will be refactored after migration to Compose Navigation is finished.
- fun sharePhoto(activity: AppCompatActivity, photo: Photo) {
- activity.startActivity(photo.createShareIntent())
- }
-
fun switchListLayout() {
when (listLayoutState.value) {
ListLayout.LIST -> {
diff --git a/feature/curated-photos/src/main/res/values/strings.xml b/feature/curated-photos/src/main/res/values/strings.xml
index d1894e14..461a9af6 100644
--- a/feature/curated-photos/src/main/res/values/strings.xml
+++ b/feature/curated-photos/src/main/res/values/strings.xml
@@ -1,5 +1,4 @@
Photos
- Switch layout
diff --git a/photo-usecase/src/main/java/com/github/sikv/photo/usecase/DownloadPhotoUseCase.kt b/photo-usecase/src/main/java/com/github/sikv/photo/usecase/DownloadPhotoUseCase.kt
index e2651620..49204f82 100644
--- a/photo-usecase/src/main/java/com/github/sikv/photo/usecase/DownloadPhotoUseCase.kt
+++ b/photo-usecase/src/main/java/com/github/sikv/photo/usecase/DownloadPhotoUseCase.kt
@@ -2,7 +2,7 @@ package com.github.sikv.photo.usecase
import android.Manifest
import android.os.Build
-import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.FragmentActivity
import com.github.sikv.photos.common.ActivityPermissionManager
import com.github.sikv.photos.common.DownloadService
import com.github.sikv.photos.common.ui.openAppSettings
@@ -14,7 +14,7 @@ class DownloadPhotoUseCase @Inject constructor(
private val downloadService: DownloadService
) {
- fun download(activity: AppCompatActivity, photo: Photo, onShowMessage: (String) -> Unit) {
+ fun download(activity: FragmentActivity, photo: Photo, onShowMessage: (String) -> Unit) {
val permissionManager = ActivityPermissionManager(activity)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {
@@ -41,7 +41,7 @@ class DownloadPhotoUseCase @Inject constructor(
}
private fun downloadPhotoInternal(
- activity: AppCompatActivity,
+ activity: FragmentActivity,
photo: Photo,
onShowMessage: (String) -> Unit
) {
diff --git a/photo-usecase/src/main/java/com/github/sikv/photo/usecase/PhotoActionsUseCase.kt b/photo-usecase/src/main/java/com/github/sikv/photo/usecase/PhotoActionsUseCase.kt
index 33a01232..72391b52 100644
--- a/photo-usecase/src/main/java/com/github/sikv/photo/usecase/PhotoActionsUseCase.kt
+++ b/photo-usecase/src/main/java/com/github/sikv/photo/usecase/PhotoActionsUseCase.kt
@@ -1,9 +1,12 @@
package com.github.sikv.photo.usecase
import android.content.Context
-import androidx.fragment.app.FragmentManager
+import android.content.Intent
+import android.widget.Toast
+import androidx.fragment.app.FragmentActivity
import com.github.sikv.photos.common.ui.OptionsBottomSheetDialog
import com.github.sikv.photos.common.ui.copyText
+import com.github.sikv.photos.common.ui.openUrl
import com.github.sikv.photos.domain.Photo
import com.github.sikv.photos.navigation.args.SetWallpaperFragmentArguments
import com.github.sikv.photos.navigation.route.SetWallpaperRoute
@@ -12,14 +15,36 @@ import javax.inject.Inject
class PhotoActionsUseCase @Inject constructor(
@ApplicationContext private val context: Context,
- private val setWallpaperRoute: SetWallpaperRoute
+ private val setWallpaperRoute: SetWallpaperRoute,
+ private val downloadPhotoUseCase: DownloadPhotoUseCase
) {
- fun openActions(
- fragmentManager: FragmentManager,
- photo: Photo,
- onShowMessage: (String) -> Unit
- ) {
+ fun photoAttributionClick(photo: Photo) {
+ photo.getPhotoPhotographerUrl()?.let { photographerUrl ->
+ context.openUrl(photographerUrl)
+ } ?: run {
+ context.openUrl(photo.getPhotoShareUrl())
+ }
+ }
+
+ fun sharePhoto(activity: FragmentActivity, photo: Photo) {
+ val intent = Intent()
+
+ intent.action = Intent.ACTION_SEND
+ intent.putExtra(Intent.EXTRA_TEXT, photo.getPhotoShareUrl())
+ intent.type = "text/plain"
+
+ activity.startActivity(intent)
+ }
+
+ fun downloadPhoto(activity: FragmentActivity, photo: Photo) {
+ downloadPhotoUseCase.download(activity, photo) { message ->
+ Toast.makeText(activity, message, Toast.LENGTH_SHORT)
+ .show()
+ }
+ }
+
+ fun openMoreActions(activity: FragmentActivity, photo: Photo) {
val options = listOf(
context.getString(R.string.set_wallpaper),
context.getString(R.string.copy_link)
@@ -29,7 +54,7 @@ class PhotoActionsUseCase @Inject constructor(
when (index) {
// Set Wallpaper
0 -> {
- setWallpaperRoute.present(fragmentManager, SetWallpaperFragmentArguments(photo))
+ setWallpaperRoute.present(activity.supportFragmentManager, SetWallpaperFragmentArguments(photo))
}
// Copy Link
1 -> {
@@ -37,11 +62,13 @@ class PhotoActionsUseCase @Inject constructor(
val text = photo.getPhotoShareUrl()
context.copyText(label, text)
- onShowMessage(context.getString(R.string.link_copied))
+
+ Toast.makeText(activity, context.getString(R.string.link_copied), Toast.LENGTH_SHORT)
+ .show()
}
}
}
- dialog.show(fragmentManager)
+ dialog.show(activity.supportFragmentManager)
}
}