From 4c5292e7ea32cbcbc4c886c2ccec869626bc884f Mon Sep 17 00:00:00 2001 From: WeiHe Date: Sat, 2 Dec 2023 22:30:52 +0800 Subject: [PATCH] feat: Add PhotoSearchScreen refactor: Rename photolibrary module to photo --- app/build.gradle.kts | 2 +- .../com/wei/picquest/navigation/PqNavHost.kt | 10 +- .../navigation/TopLevelDestination.kt | 6 +- .../main/java/com/wei/picquest/ui/PqApp.kt | 3 + .../java/com/wei/picquest/ui/PqAppState.kt | 8 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- .../core/designsystem/component/Navigation.kt | 6 +- .../core/designsystem/icon/PqIcons.kt | 4 - feature/{photolibrary => photo}/.gitignore | 0 .../{photolibrary => photo}/build.gradle.kts | 2 +- .../src/main/AndroidManifest.xml | 0 .../photo}/photolibrary/PhotoLibraryScreen.kt | 61 +++------ .../photolibrary/PhotoLibraryViewModel.kt | 13 +- .../photolibrary/PhotoLibraryViewState.kt | 5 +- .../component/LayoutSwitchWarningDialog.kt | 4 +- .../navigation/PhotoLibraryNavigation.kt | 50 ++++++++ .../photo/photosearch/PhotoSearchScreen.kt | 119 ++++++++++++++++++ .../photo/photosearch/PhotoSearchViewModel.kt | 18 +++ .../photo/photosearch/PhotoSearchViewState.kt | 12 ++ .../navigation/PhotoSearchNavigation.kt | 27 ++++ .../main/res/drawable/placeholder_image.png | Bin .../src/main/res/values-zh-rTW/strings.xml | 0 .../src/main/res/values/strings.xml | 0 .../navigation/PhotoLibraryNavigation.kt | 23 ---- settings.gradle.kts | 2 +- 26 files changed, 280 insertions(+), 99 deletions(-) rename feature/{photolibrary => photo}/.gitignore (100%) rename feature/{photolibrary => photo}/build.gradle.kts (75%) rename feature/{photolibrary => photo}/src/main/AndroidManifest.xml (100%) rename feature/{photolibrary/src/main/java/com/wei/picquest/feature/photolibrary => photo/src/main/java/com/wei/picquest/feature/photo}/photolibrary/PhotoLibraryScreen.kt (89%) rename feature/{photolibrary/src/main/java/com/wei/picquest/feature/photolibrary => photo/src/main/java/com/wei/picquest/feature/photo}/photolibrary/PhotoLibraryViewModel.kt (80%) rename feature/{photolibrary/src/main/java/com/wei/picquest/feature/photolibrary => photo/src/main/java/com/wei/picquest/feature/photo}/photolibrary/PhotoLibraryViewState.kt (68%) rename feature/{photolibrary/src/main/java/com/wei/picquest/feature/photolibrary => photo/src/main/java/com/wei/picquest/feature/photo}/photolibrary/component/LayoutSwitchWarningDialog.kt (91%) create mode 100644 feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/navigation/PhotoLibraryNavigation.kt create mode 100644 feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchScreen.kt create mode 100644 feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewModel.kt create mode 100644 feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewState.kt create mode 100644 feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/navigation/PhotoSearchNavigation.kt rename feature/{photolibrary => photo}/src/main/res/drawable/placeholder_image.png (100%) rename feature/{photolibrary => photo}/src/main/res/values-zh-rTW/strings.xml (100%) rename feature/{photolibrary => photo}/src/main/res/values/strings.xml (100%) delete mode 100644 feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/navigation/PhotoLibraryNavigation.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 72fd56f..a542a30 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -67,7 +67,7 @@ android { dependencies { implementation(project(":feature:home")) - implementation(project(":feature:photolibrary")) + implementation(project(":feature:photo")) // TODO Wei // implementation(project(":feature:contactme")) diff --git a/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt b/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt index 4062567..68c21d6 100644 --- a/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt +++ b/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt @@ -7,7 +7,9 @@ import androidx.window.layout.DisplayFeature import com.wei.picquest.core.designsystem.ui.DeviceOrientation import com.wei.picquest.feature.home.home.navigation.homeGraph import com.wei.picquest.feature.home.home.navigation.homeRoute -import com.wei.picquest.feature.photolibrary.photolibrary.navigation.photoLibraryGraph +import com.wei.picquest.feature.photo.photolibrary.navigation.navigateToPhotoLibrary +import com.wei.picquest.feature.photo.photolibrary.navigation.photoLibraryGraph +import com.wei.picquest.feature.photo.photosearch.navigation.photoSearchGraph import com.wei.picquest.ui.PqAppState /** @@ -37,8 +39,12 @@ fun PqNavHost( homeGraph( navController = navController, ) - photoLibraryGraph( + photoSearchGraph( navController = navController, + onSearchClick = navController::navigateToPhotoLibrary, + nestedGraphs = { + photoLibraryGraph(navController = navController) + }, ) } } diff --git a/app/src/main/java/com/wei/picquest/navigation/TopLevelDestination.kt b/app/src/main/java/com/wei/picquest/navigation/TopLevelDestination.kt index 7a22f9c..751c06e 100644 --- a/app/src/main/java/com/wei/picquest/navigation/TopLevelDestination.kt +++ b/app/src/main/java/com/wei/picquest/navigation/TopLevelDestination.kt @@ -21,11 +21,11 @@ enum class TopLevelDestination( iconTextId = R.string.home, titleTextId = R.string.home, ), - PHOTO_LIBRARY( + PHOTO( selectedIcon = PqIcons.PhotoLibrary, unselectedIcon = PqIcons.PhotoLibraryBorder, - iconTextId = R.string.photo_library, - titleTextId = R.string.photo_library, + iconTextId = R.string.photo, + titleTextId = R.string.photo, ), CONTACT_ME( selectedIcon = PqIcons.ContactMe, diff --git a/app/src/main/java/com/wei/picquest/ui/PqApp.kt b/app/src/main/java/com/wei/picquest/ui/PqApp.kt index 23bd43f..088bb9a 100644 --- a/app/src/main/java/com/wei/picquest/ui/PqApp.kt +++ b/app/src/main/java/com/wei/picquest/ui/PqApp.kt @@ -58,6 +58,7 @@ import com.wei.picquest.core.manager.SnackbarState import com.wei.picquest.core.utils.UiText import com.wei.picquest.navigation.PqNavHost import com.wei.picquest.navigation.TopLevelDestination +import timber.log.Timber @OptIn( ExperimentalMaterial3Api::class, @@ -294,6 +295,8 @@ private fun PqBottomBar( private fun NavDestination?.isTopLevelDestinationInHierarchy(destination: TopLevelDestination) = this?.hierarchy?.any { + Timber.e("PQ isTopLevelDestinationInHierarchy " + it.route.toString()) + Timber.e("PQ destination " + destination.name.toString()) it.route?.contains(destination.name, true) ?: false } ?: false diff --git a/app/src/main/java/com/wei/picquest/ui/PqAppState.kt b/app/src/main/java/com/wei/picquest/ui/PqAppState.kt index 15698f1..5eed23d 100644 --- a/app/src/main/java/com/wei/picquest/ui/PqAppState.kt +++ b/app/src/main/java/com/wei/picquest/ui/PqAppState.kt @@ -27,8 +27,8 @@ import com.wei.picquest.core.designsystem.ui.isBookPosture import com.wei.picquest.core.designsystem.ui.isSeparating import com.wei.picquest.feature.home.home.navigation.homeRoute import com.wei.picquest.feature.home.home.navigation.navigateToHome -import com.wei.picquest.feature.photolibrary.photolibrary.navigation.navigateToPhotoLibrary -import com.wei.picquest.feature.photolibrary.photolibrary.navigation.photoLibraryRoute +import com.wei.picquest.feature.photo.photosearch.navigation.navigateToPhotoSearch +import com.wei.picquest.feature.photo.photosearch.navigation.photoSearchRoute import com.wei.picquest.navigation.TopLevelDestination import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted @@ -151,7 +151,7 @@ class PqAppState( val currentTopLevelDestination: TopLevelDestination? @Composable get() = when (currentDestination?.route) { homeRoute -> TopLevelDestination.HOME - photoLibraryRoute -> TopLevelDestination.PHOTO_LIBRARY + photoSearchRoute -> TopLevelDestination.PHOTO else -> null } @@ -199,7 +199,7 @@ class PqAppState( topLevelNavOptions, ) - TopLevelDestination.PHOTO_LIBRARY -> navController.navigateToPhotoLibrary( + TopLevelDestination.PHOTO -> navController.navigateToPhotoSearch( topLevelNavOptions, ) diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index ec1279b..27cda33 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -2,7 +2,7 @@ PicQuest ⚠️ 您沒有網路連線 - 照片庫 + 照片 首頁 聯絡我 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 503bf20..d34aeec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ PicQuest ⚠️ You aren’t connected to the internet - Photo Library + Photo Home Contact Me diff --git a/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/component/Navigation.kt b/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/component/Navigation.kt index fe4cf33..34cde89 100644 --- a/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/component/Navigation.kt +++ b/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/component/Navigation.kt @@ -335,14 +335,14 @@ object PqNavigationDefaults { fun navigationIndicatorColor() = MaterialTheme.colorScheme.primaryContainer } -internal val previewItems = listOf("Schedule", "Home", "Contact Me") +internal val previewItems = listOf("Home", "Photo", "Contact Me") internal val previewIcons = listOf( - PqIcons.ScheduleBorder, PqIcons.HomeBorder, + PqIcons.PhotoLibraryBorder, PqIcons.ContactMeBorder, ) internal val previewSelectedIcons = listOf( - PqIcons.Schedule, PqIcons.Home, + PqIcons.PhotoLibrary, PqIcons.ContactMe, ) diff --git a/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/icon/PqIcons.kt b/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/icon/PqIcons.kt index 3ef3b6f..1f4b5c5 100644 --- a/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/icon/PqIcons.kt +++ b/core/designsystem/src/main/java/com/wei/picquest/core/designsystem/icon/PqIcons.kt @@ -1,7 +1,6 @@ package com.wei.picquest.core.designsystem.icon import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.CalendarMonth import androidx.compose.material.icons.outlined.Home import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.PhotoLibrary @@ -12,7 +11,6 @@ import androidx.compose.material.icons.rounded.ArrowBack import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material.icons.rounded.ArrowForward import androidx.compose.material.icons.rounded.ArrowForwardIos -import androidx.compose.material.icons.rounded.CalendarMonth import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.GridView import androidx.compose.material.icons.rounded.Home @@ -44,8 +42,6 @@ object PqIcons { val InfoBorder = Icons.Outlined.Info val Home = Icons.Rounded.Home val HomeBorder = Icons.Outlined.Home - val Schedule = Icons.Rounded.CalendarMonth - val ScheduleBorder = Icons.Outlined.CalendarMonth val ContactMe = Icons.Rounded.SupportAgent val ContactMeBorder = Icons.Outlined.SupportAgent val PhotoLibrary = Icons.Rounded.PhotoLibrary diff --git a/feature/photolibrary/.gitignore b/feature/photo/.gitignore similarity index 100% rename from feature/photolibrary/.gitignore rename to feature/photo/.gitignore diff --git a/feature/photolibrary/build.gradle.kts b/feature/photo/build.gradle.kts similarity index 75% rename from feature/photolibrary/build.gradle.kts rename to feature/photo/build.gradle.kts index 85b8308..59a13a9 100644 --- a/feature/photolibrary/build.gradle.kts +++ b/feature/photo/build.gradle.kts @@ -5,7 +5,7 @@ plugins { } android { - namespace = "com.wei.picquest.feature.photolibrary" + namespace = "com.wei.picquest.feature.photo" } dependencies { diff --git a/feature/photolibrary/src/main/AndroidManifest.xml b/feature/photo/src/main/AndroidManifest.xml similarity index 100% rename from feature/photolibrary/src/main/AndroidManifest.xml rename to feature/photo/src/main/AndroidManifest.xml diff --git a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryScreen.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryScreen.kt similarity index 89% rename from feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryScreen.kt rename to feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryScreen.kt index 3d95f13..36060c4 100644 --- a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryScreen.kt +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryScreen.kt @@ -1,4 +1,4 @@ -package com.wei.picquest.feature.photolibrary.photolibrary +package com.wei.picquest.feature.photo.photolibrary import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -54,13 +54,12 @@ import coil.compose.AsyncImagePainter import coil.compose.SubcomposeAsyncImage import coil.compose.SubcomposeAsyncImageContent import com.wei.picquest.core.data.model.ImageDetail -import com.wei.picquest.core.designsystem.component.FunctionalityNotAvailablePopup import com.wei.picquest.core.designsystem.icon.PqIcons import com.wei.picquest.core.designsystem.theme.SPACING_LARGE import com.wei.picquest.core.designsystem.theme.SPACING_MEDIUM import com.wei.picquest.core.designsystem.theme.SPACING_SMALL -import com.wei.picquest.feature.photolibrary.R -import com.wei.picquest.feature.photolibrary.photolibrary.component.LayoutSwitchWarningDialog +import com.wei.picquest.feature.photo.R +import com.wei.picquest.feature.photo.photolibrary.component.LayoutSwitchWarningDialog /** * @@ -109,6 +108,7 @@ internal fun PhotoLibraryRoute( TopBarActions( layoutType = uiStates.layoutType, + onBackClick = navController::popBackStack, onSwitchLayoutClick = { viewModel.dispatch(PhotoLibraryViewAction.SwitchLayoutType) }, @@ -120,12 +120,13 @@ internal fun PhotoLibraryRoute( @Composable fun TopBarActions( layoutType: LayoutType, + onBackClick: () -> Unit, onSwitchLayoutClick: () -> Unit, ) { Column { Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) Row(modifier = Modifier.padding(SPACING_MEDIUM.dp)) { - BackButton() + BackButton(onBackClick = onBackClick) Spacer(modifier = Modifier.weight(1f)) SwitchLayoutButton( layoutType = layoutType, @@ -136,22 +137,11 @@ fun TopBarActions( } @Composable -fun BackButton() { - val showPopup = remember { mutableStateOf(false) } - - if (showPopup.value) { - FunctionalityNotAvailablePopup( - onDismiss = { - showPopup.value = false - }, - ) - } - +fun BackButton( + onBackClick: () -> Unit, +) { IconButton( - onClick = { - /* TODO: Implement back button action */ - showPopup.value = true - }, + onClick = { onBackClick() }, modifier = Modifier .clip(CircleShape) .background(MaterialTheme.colorScheme.surfaceVariant) @@ -208,12 +198,6 @@ fun PhotoLibraryListScreen( Box(modifier = Modifier.fillMaxSize()) { Column { LazyColumn(modifier = Modifier.weight(1f)) { - if (withTopSpacer) { - item { - Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) - } - } - items(lazyPagingItems.itemCount) { index -> lazyPagingItems[index]?.let { ImageDetailItem( @@ -222,15 +206,11 @@ fun PhotoLibraryListScreen( ) } } - - if (withBottomSpacer) { - item { - Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) - } - } } - PagingStateHandling(lazyPagingItems) + if (withBottomSpacer) { + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) + } } } } @@ -254,12 +234,6 @@ fun PhotoLibraryGridScreen( verticalItemSpacing = 0.dp, flingBehavior = ScrollableDefaults.flingBehavior(), ) { - if (withTopSpacer) { - item { - Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) - } - } - items(lazyPagingItems.itemCount) { index -> lazyPagingItems[index]?.let { ImageDetailItem( @@ -268,15 +242,12 @@ fun PhotoLibraryGridScreen( ) } } - - if (withBottomSpacer) { - item { - Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) - } - } } PagingStateHandling(lazyPagingItems) + if (withBottomSpacer) { + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) + } } } } diff --git a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewModel.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewModel.kt similarity index 80% rename from feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewModel.kt rename to feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewModel.kt index 7dee194..b20d491 100644 --- a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewModel.kt +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewModel.kt @@ -1,11 +1,13 @@ -package com.wei.picquest.feature.photolibrary.photolibrary +package com.wei.picquest.feature.photo.photolibrary +import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import androidx.paging.PagingData import androidx.paging.cachedIn import com.wei.picquest.core.base.BaseViewModel import com.wei.picquest.core.data.model.ImageDetail import com.wei.picquest.core.data.repository.SearchImagesRepository +import com.wei.picquest.feature.photo.photolibrary.navigation.PhotoLibraryArgs import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.distinctUntilChanged @@ -14,19 +16,23 @@ import javax.inject.Inject @HiltViewModel class PhotoLibraryViewModel @Inject constructor( + savedStateHandle: SavedStateHandle, private val searchImagesRepository: SearchImagesRepository, ) : BaseViewModel< PhotoLibraryViewAction, PhotoLibraryViewState, >(PhotoLibraryViewState()) { + private val photoLibraryArgs: PhotoLibraryArgs = PhotoLibraryArgs(savedStateHandle) + + val photoSearchKeyword = photoLibraryArgs.photoSearchKeyword + private val _imagesState: MutableStateFlow> = MutableStateFlow(value = PagingData.empty()) val imagesState: MutableStateFlow> get() = _imagesState init { - // TODO Wei - searchImages("") + searchImages(photoSearchKeyword) } private fun searchImages(query: String) { @@ -50,7 +56,6 @@ class PhotoLibraryViewModel @Inject constructor( override fun dispatch(action: PhotoLibraryViewAction) { when (action) { - is PhotoLibraryViewAction.SearchImages -> searchImages(action.query) is PhotoLibraryViewAction.SwitchLayoutType -> switchLayoutType() } } diff --git a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewState.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewState.kt similarity index 68% rename from feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewState.kt rename to feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewState.kt index 177d4cf..c84ca84 100644 --- a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/PhotoLibraryViewState.kt +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/PhotoLibraryViewState.kt @@ -1,4 +1,4 @@ -package com.wei.picquest.feature.photolibrary.photolibrary +package com.wei.picquest.feature.photo.photolibrary import com.wei.picquest.core.base.Action import com.wei.picquest.core.base.State @@ -8,9 +8,6 @@ enum class LayoutType { } sealed class PhotoLibraryViewAction : Action { - data class SearchImages( - val query: String, - ) : PhotoLibraryViewAction() object SwitchLayoutType : PhotoLibraryViewAction() } diff --git a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/component/LayoutSwitchWarningDialog.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/component/LayoutSwitchWarningDialog.kt similarity index 91% rename from feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/component/LayoutSwitchWarningDialog.kt rename to feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/component/LayoutSwitchWarningDialog.kt index 09b3527..f4713a9 100644 --- a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/component/LayoutSwitchWarningDialog.kt +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/component/LayoutSwitchWarningDialog.kt @@ -1,4 +1,4 @@ -package com.wei.picquest.feature.photolibrary.photolibrary.component +package com.wei.picquest.feature.photo.photolibrary.component import androidx.compose.material3.AlertDialog import androidx.compose.material3.MaterialTheme @@ -9,7 +9,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics -import com.wei.picquest.feature.photolibrary.R +import com.wei.picquest.feature.photo.R @Composable fun LayoutSwitchWarningDialog(onDismiss: () -> Unit) { diff --git a/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/navigation/PhotoLibraryNavigation.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/navigation/PhotoLibraryNavigation.kt new file mode 100644 index 0000000..36bd8ad --- /dev/null +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photolibrary/navigation/PhotoLibraryNavigation.kt @@ -0,0 +1,50 @@ +package com.wei.picquest.feature.photo.photolibrary.navigation + +import androidx.annotation.VisibleForTesting +import androidx.lifecycle.SavedStateHandle +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavType +import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import com.wei.picquest.feature.photo.photolibrary.PhotoLibraryRoute +import com.wei.picquest.feature.photo.photosearch.navigation.photoSearchRoute +import java.net.URLDecoder +import java.net.URLEncoder + +private val URL_CHARACTER_ENCODING = Charsets.UTF_8.name() + +@VisibleForTesting +internal const val photoSearchKeywordArg = "photoSearchKeyword" + +internal class PhotoLibraryArgs(val photoSearchKeyword: String) { + constructor(savedStateHandle: SavedStateHandle) : + this( + URLDecoder.decode( + checkNotNull(savedStateHandle[photoSearchKeywordArg]), + URL_CHARACTER_ENCODING, + ), + ) +} + +fun NavController.navigateToPhotoLibrary(photoSearchKeyword: String) { + val encodedKey = URLEncoder.encode(photoSearchKeyword, URL_CHARACTER_ENCODING) + this.navigate("$photoSearchRoute/$encodedKey") { + launchSingleTop = true + } +} + +fun NavGraphBuilder.photoLibraryGraph( + navController: NavController, +) { + composable( + route = "$photoSearchRoute/{$photoSearchKeywordArg}", + arguments = listOf( + navArgument(photoSearchKeywordArg) { type = NavType.StringType }, + ), + ) { + PhotoLibraryRoute( + navController = navController, + ) + } +} diff --git a/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchScreen.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchScreen.kt new file mode 100644 index 0000000..24e3dbb --- /dev/null +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchScreen.kt @@ -0,0 +1,119 @@ +package com.wei.picquest.feature.photo.photosearch + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.windowInsetsBottomHeight +import androidx.compose.foundation.layout.windowInsetsTopHeight +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.navigation.NavController +import com.wei.picquest.core.designsystem.component.FunctionalityNotAvailablePopup +import com.wei.picquest.core.designsystem.component.ThemePreviews +import com.wei.picquest.core.designsystem.theme.PqTheme + +/** + * + * UI 事件決策樹 + * 下圖顯示了一個決策樹,用於查找處理特定事件用例的最佳方法。 + * + * ┌───────┐ + * │ Start │ + * └───┬───┘ + * ↓ + * ┌───────────────────────────────────┐ + * │ Where is event originated? │ + * └──────┬─────────────────────┬──────┘ + * ↓ ↓ + * UI ViewModel + * │ │ + * ┌─────────────────────────┐ ┌───────────────┐ + * │ When the event requires │ │ Update the UI │ + * │ ... │ │ State │ + * └─┬─────────────────────┬─┘ └───────────────┘ + * ↓ ↓ + * Business logic UI behavior logic + * │ │ + * ┌─────────────────────────────────┐ ┌──────────────────────────────────────┐ + * │ Delegate the business logic to │ │ Modify the UI element state in the │ + * │ the ViewModel │ │ UI directly │ + * └─────────────────────────────────┘ └──────────────────────────────────────┘ + * + * + */ +@Composable +internal fun PhotoSearchRoute( + onSearchClick: (String) -> Unit, + navController: NavController, +) { + PhotoSearchScreen(onSearchClick = onSearchClick) +} + +@Composable +internal fun PhotoSearchScreen( + onSearchClick: (String) -> Unit, + withTopSpacer: Boolean = true, + withBottomSpacer: Boolean = true, +) { + val showPopup = remember { mutableStateOf(false) } + + if (showPopup.value) { + FunctionalityNotAvailablePopup( + onDismiss = { + showPopup.value = false + }, + ) + } + + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background, + ) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + ) { + if (withTopSpacer) { + Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) + } + + Column { + Spacer(modifier = Modifier.weight(1f)) + Text( + text = "Search Screen not available \uD83D\uDE48", + color = MaterialTheme.colorScheme.error, + style = MaterialTheme.typography.headlineMedium, + modifier = Modifier + .semantics { contentDescription = "" }, + ) + // TODO Wei + Button(onClick = { onSearchClick("kitten") }) { + Text(text = "Search [kitten] keyword") + } + Spacer(modifier = Modifier.weight(1f)) + } + + if (withBottomSpacer) { + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) + } + } + } +} + +@ThemePreviews +@Composable +fun SearchPhotoScreenPreview() { + PqTheme { + PhotoSearchScreen(onSearchClick = {}) + } +} diff --git a/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewModel.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewModel.kt new file mode 100644 index 0000000..210e1af --- /dev/null +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewModel.kt @@ -0,0 +1,18 @@ +package com.wei.picquest.feature.photo.photosearch + +import com.wei.picquest.core.base.BaseViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class PhotoSearchViewModel @Inject constructor() : BaseViewModel< + PhotoSearchViewAction, + PhotoSearchViewState, + >(PhotoSearchViewState) { + + override fun dispatch(action: PhotoSearchViewAction) { + when (action) { + is PhotoSearchViewAction.SearchPhotos -> TODO() + } + } +} diff --git a/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewState.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewState.kt new file mode 100644 index 0000000..aa6bdc3 --- /dev/null +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/PhotoSearchViewState.kt @@ -0,0 +1,12 @@ +package com.wei.picquest.feature.photo.photosearch + +import com.wei.picquest.core.base.Action +import com.wei.picquest.core.base.State + +sealed class PhotoSearchViewAction : Action { + data class SearchPhotos( + val query: String, + ) : PhotoSearchViewAction() +} + +object PhotoSearchViewState : State diff --git a/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/navigation/PhotoSearchNavigation.kt b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/navigation/PhotoSearchNavigation.kt new file mode 100644 index 0000000..04734df --- /dev/null +++ b/feature/photo/src/main/java/com/wei/picquest/feature/photo/photosearch/navigation/PhotoSearchNavigation.kt @@ -0,0 +1,27 @@ +package com.wei.picquest.feature.photo.photosearch.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import com.wei.picquest.feature.photo.photosearch.PhotoSearchRoute + +const val photoSearchRoute = "photo_search_route" + +fun NavController.navigateToPhotoSearch(navOptions: NavOptions? = null) { + this.navigate(photoSearchRoute, navOptions) +} + +fun NavGraphBuilder.photoSearchGraph( + navController: NavController, + onSearchClick: (String) -> Unit, + nestedGraphs: NavGraphBuilder.() -> Unit, +) { + composable(route = photoSearchRoute) { + PhotoSearchRoute( + onSearchClick = onSearchClick, + navController = navController, + ) + } + nestedGraphs() +} diff --git a/feature/photolibrary/src/main/res/drawable/placeholder_image.png b/feature/photo/src/main/res/drawable/placeholder_image.png similarity index 100% rename from feature/photolibrary/src/main/res/drawable/placeholder_image.png rename to feature/photo/src/main/res/drawable/placeholder_image.png diff --git a/feature/photolibrary/src/main/res/values-zh-rTW/strings.xml b/feature/photo/src/main/res/values-zh-rTW/strings.xml similarity index 100% rename from feature/photolibrary/src/main/res/values-zh-rTW/strings.xml rename to feature/photo/src/main/res/values-zh-rTW/strings.xml diff --git a/feature/photolibrary/src/main/res/values/strings.xml b/feature/photo/src/main/res/values/strings.xml similarity index 100% rename from feature/photolibrary/src/main/res/values/strings.xml rename to feature/photo/src/main/res/values/strings.xml diff --git a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/navigation/PhotoLibraryNavigation.kt b/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/navigation/PhotoLibraryNavigation.kt deleted file mode 100644 index 910d257..0000000 --- a/feature/photolibrary/src/main/java/com/wei/picquest/feature/photolibrary/photolibrary/navigation/PhotoLibraryNavigation.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.wei.picquest.feature.photolibrary.photolibrary.navigation - -import androidx.navigation.NavController -import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavOptions -import androidx.navigation.compose.composable -import com.wei.picquest.feature.photolibrary.photolibrary.PhotoLibraryRoute - -const val photoLibraryRoute = "photo_library_route" - -fun NavController.navigateToPhotoLibrary(navOptions: NavOptions? = null) { - this.navigate(photoLibraryRoute, navOptions) -} - -fun NavGraphBuilder.photoLibraryGraph( - navController: NavController, -) { - composable(route = photoLibraryRoute) { - PhotoLibraryRoute( - navController = navController, - ) - } -} diff --git a/settings.gradle.kts b/settings.gradle.kts index d130eb7..621bb1e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -29,4 +29,4 @@ include(":core:network") include(":ui-test-hilt-manifest") include(":feature:home") -include(":feature:photolibrary") +include(":feature:photo")