From 71b61826c0356e975710d4a04d033a45d4b02e89 Mon Sep 17 00:00:00 2001 From: WeiHe Date: Sun, 3 Dec 2023 02:18:40 +0800 Subject: [PATCH] feat: Implement functionality of the contactme module --- app/build.gradle.kts | 5 +- .../com/wei/picquest/navigation/PqNavHost.kt | 8 + .../java/com/wei/picquest/ui/PqAppState.kt | 9 +- feature/contactme/.gitignore | 1 + feature/contactme/build.gradle.kts | 12 + .../contactme/ContactMeScreenRobot.kt | 206 ++++++++ .../contactme/ContactMeScreenTest.kt | 56 +++ .../contactme/src/main/AndroidManifest.xml | 4 + .../contactme/contactme/ContactMeScreen.kt | 457 ++++++++++++++++++ .../contactme/contactme/ContactMeViewModel.kt | 47 ++ .../contactme/contactme/ContactMeViewState.kt | 18 + .../navigation/ContactMeNavigation.kt | 33 ++ .../contactme/ui/DecorativeBackgroundText.kt | 54 +++ .../contactme/contactme/ui/ProfileProperty.kt | 42 ++ .../contactme/utilities/Constants.kt | 12 + .../src/main/res/drawable/he_wei.jpg | Bin 0 -> 63887 bytes .../src/main/res/values-zh-rTW/strings.xml | 8 + .../contactme/src/main/res/values/strings.xml | 8 + feature/contactme/utilities/Constants.kt | 12 + settings.gradle.kts | 1 + 20 files changed, 987 insertions(+), 6 deletions(-) create mode 100644 feature/contactme/.gitignore create mode 100644 feature/contactme/build.gradle.kts create mode 100644 feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenRobot.kt create mode 100644 feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenTest.kt create mode 100644 feature/contactme/src/main/AndroidManifest.xml create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreen.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewModel.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewState.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/navigation/ContactMeNavigation.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/DecorativeBackgroundText.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/ProfileProperty.kt create mode 100644 feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/utilities/Constants.kt create mode 100644 feature/contactme/src/main/res/drawable/he_wei.jpg create mode 100644 feature/contactme/src/main/res/values-zh-rTW/strings.xml create mode 100644 feature/contactme/src/main/res/values/strings.xml create mode 100644 feature/contactme/utilities/Constants.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a542a30..6e42fc6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -68,14 +68,13 @@ android { dependencies { implementation(project(":feature:home")) implementation(project(":feature:photo")) - - // TODO Wei -// implementation(project(":feature:contactme")) + implementation(project(":feature:contactme")) implementation(project(":core:designsystem")) implementation(project(":core:common")) implementation(project(":core:data")) implementation(project(":core:model")) + // TODO Wei // implementation(project(":core:datastore")) androidTestImplementation(project(":core:designsystem")) 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 78790d4..d9dd5de 100644 --- a/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt +++ b/app/src/main/java/com/wei/picquest/navigation/PqNavHost.kt @@ -5,6 +5,7 @@ import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost import androidx.window.layout.DisplayFeature import com.wei.picquest.core.designsystem.ui.DeviceOrientation +import com.wei.picquest.feature.contactme.contactme.navigation.contactMeGraph import com.wei.picquest.feature.home.home.navigation.homeGraph import com.wei.picquest.feature.home.home.navigation.homeRoute import com.wei.picquest.feature.photo.photolibrary.navigation.photoLibraryGraph @@ -44,5 +45,12 @@ fun PqNavHost( photoLibraryGraph(navController = navController) }, ) + contactMeGraph( + navController = navController, + contentType = contentType, + displayFeatures = displayFeatures, + navigationType = navigationType, + nestedGraphs = { }, + ) } } 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 5eed23d..7928336 100644 --- a/app/src/main/java/com/wei/picquest/ui/PqAppState.kt +++ b/app/src/main/java/com/wei/picquest/ui/PqAppState.kt @@ -25,6 +25,8 @@ import com.wei.picquest.core.designsystem.ui.PqNavigationType import com.wei.picquest.core.designsystem.ui.currentDeviceOrientation import com.wei.picquest.core.designsystem.ui.isBookPosture import com.wei.picquest.core.designsystem.ui.isSeparating +import com.wei.picquest.feature.contactme.contactme.navigation.contactMeRoute +import com.wei.picquest.feature.contactme.contactme.navigation.navigateToContactMe import com.wei.picquest.feature.home.home.navigation.homeRoute import com.wei.picquest.feature.home.home.navigation.navigateToHome import com.wei.picquest.feature.photo.photosearch.navigation.navigateToPhotoSearch @@ -152,6 +154,7 @@ class PqAppState( @Composable get() = when (currentDestination?.route) { homeRoute -> TopLevelDestination.HOME photoSearchRoute -> TopLevelDestination.PHOTO + contactMeRoute -> TopLevelDestination.CONTACT_ME else -> null } @@ -203,9 +206,9 @@ class PqAppState( topLevelNavOptions, ) -// TopLevelDestination.CONTACT_ME -> navController.navigateToContactMe( -// topLevelNavOptions, -// ) + TopLevelDestination.CONTACT_ME -> navController.navigateToContactMe( + topLevelNavOptions, + ) else -> showFunctionalityNotAvailablePopup.value = true } diff --git a/feature/contactme/.gitignore b/feature/contactme/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/feature/contactme/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/contactme/build.gradle.kts b/feature/contactme/build.gradle.kts new file mode 100644 index 0000000..bcf3613 --- /dev/null +++ b/feature/contactme/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + alias(libs.plugins.pq.android.feature) + alias(libs.plugins.pq.android.library.compose) + alias(libs.plugins.pq.android.hilt) +} + +android { + namespace = "com.wei.picquest.feature.contactme" +} + +dependencies { +} \ No newline at end of file diff --git a/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenRobot.kt b/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenRobot.kt new file mode 100644 index 0000000..1a23cab --- /dev/null +++ b/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenRobot.kt @@ -0,0 +1,206 @@ +package com.wei.picquest.feature.contactme.contactme + +import androidx.activity.ComponentActivity +import androidx.annotation.StringRes +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.AndroidComposeTestRule +import androidx.compose.ui.test.onNodeWithContentDescription +import androidx.compose.ui.test.performClick +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.window.layout.DisplayFeature +import com.google.common.truth.Truth +import com.wei.picquest.core.designsystem.theme.PqTheme +import com.wei.picquest.core.designsystem.ui.PqContentType +import com.wei.picquest.feature.contactme.R +import com.wei.picquest.feature.contactme.contactme.utilities.EMAIL +import com.wei.picquest.feature.contactme.contactme.utilities.LINKEDIN_URL +import com.wei.picquest.feature.contactme.contactme.utilities.NAME_ENG +import com.wei.picquest.feature.contactme.contactme.utilities.NAME_TW +import com.wei.picquest.feature.contactme.contactme.utilities.PHONE +import com.wei.picquest.feature.contactme.contactme.utilities.POSITION +import com.wei.picquest.feature.contactme.contactme.utilities.TIME_ZONE +import kotlin.properties.ReadOnlyProperty + +/** + * Screen Robot for [ContactMeScreenTest]. + * + * 遵循此模型,找到測試使用者介面元素、檢查其屬性、和透過測試規則執行動作: + * composeTestRule{.finder}{.assertion}{.action} + * + * Testing cheatsheet: + * https://developer.android.com/jetpack/compose/testing-cheatsheet + */ +internal fun contactMeScreenRobot( + composeTestRule: AndroidComposeTestRule, ComponentActivity>, + func: ContactMeScreenRobot.() -> Unit, +) = ContactMeScreenRobot(composeTestRule).apply(func) + +internal open class ContactMeScreenRobot( + private val composeTestRule: AndroidComposeTestRule, ComponentActivity>, +) { + private fun AndroidComposeTestRule<*, *>.stringResource(@StringRes resId: Int) = + ReadOnlyProperty { _, _ -> activity.getString(resId) } + + private val profilePictureDescription by composeTestRule.stringResource(R.string.profile_picture) + private val linkedinString by composeTestRule.stringResource(R.string.linkedin) + private val emailString by composeTestRule.stringResource(R.string.email) + private val timezoneString by composeTestRule.stringResource(R.string.timezone) + private val callDescription by composeTestRule.stringResource(R.string.call) + + private val profilePicture by lazy { + composeTestRule.onNodeWithContentDescription( + profilePictureDescription.format(testUiState.nameEng), + useUnmergedTree = true, + ) + } + private val name by lazy { + composeTestRule.onNodeWithContentDescription( + testUiState.nameEng, + useUnmergedTree = true, + ) + } + private val position by lazy { + composeTestRule.onNodeWithContentDescription( + testUiState.position, + useUnmergedTree = true, + ) + } + private val linkedin by lazy { + composeTestRule.onNodeWithContentDescription( + linkedinString, + useUnmergedTree = true, + ) + } + private val linkedinValue by lazy { + composeTestRule.onNodeWithContentDescription( + testUiState.linkedinUrl, + useUnmergedTree = true, + ) + } + private val email by lazy { + composeTestRule.onNodeWithContentDescription( + emailString, + useUnmergedTree = true, + ) + } + private val emailValue by lazy { + composeTestRule.onNodeWithContentDescription( + testUiState.email, + useUnmergedTree = true, + ) + } + private val timeZone by lazy { + composeTestRule.onNodeWithContentDescription( + timezoneString, + useUnmergedTree = true, + ) + } + private val timeZoneValue by lazy { + composeTestRule.onNodeWithContentDescription( + testUiState.timeZone, + useUnmergedTree = true, + ) + } + private val call by lazy { + composeTestRule.onNodeWithContentDescription( + callDescription.format(testUiState.nameEng), + useUnmergedTree = true, + ) + } + + private var callClicked: Boolean = false + + fun setContactMeScreenContent( + contentType: PqContentType, + displayFeature: List, + ) { + composeTestRule.setContent { + PqTheme { + ContactMeScreen( + uiStates = testUiState, + contentType = contentType, + displayFeatures = displayFeature, + onPhoneClick = { callClicked = true }, + ) + } + } + } + + fun verifyProfilePictureDisplayed() { + profilePicture.assertExists().assertIsDisplayed() + } + + fun verifyNameDisplayed() { + name.assertExists().assertIsDisplayed() + } + + fun verifyPositionDisplayed() { + position.assertExists().assertIsDisplayed() + } + + fun verifyCallDisplayed() { + call.assertExists().assertIsDisplayed() + } + + fun verifyLinkedinExists() { + linkedin.assertExists() + } + + fun verifyLinkedinValueExists() { + linkedinValue.assertExists() + } + + fun verifyEmailExists() { + email.assertExists() + } + + fun verifyEmailValueExists() { + emailValue.assertExists() + } + + fun verifyTimeZoneExists() { + timeZone.assertExists() + } + + fun verifyTimeZoneValueExists() { + timeZoneValue.assertExists() + } + + infix fun call(func: ContactMeScreenCallRobot.() -> Unit): ContactMeScreenCallRobot { + call.assertExists().performClick() + return contactMeScreenCallRobot(composeTestRule) { + setIsCallClicked(callClicked) + func() + } + } +} + +internal fun contactMeScreenCallRobot( + composeTestRule: AndroidComposeTestRule, ComponentActivity>, + func: ContactMeScreenCallRobot.() -> Unit, +) = ContactMeScreenCallRobot(composeTestRule).apply(func) + +internal open class ContactMeScreenCallRobot( + private val composeTestRule: AndroidComposeTestRule, ComponentActivity>, +) { + + private var isCallClicked: Boolean = false + + fun setIsCallClicked(backClicked: Boolean) { + isCallClicked = backClicked + } + + fun isCall() { + Truth.assertThat(isCallClicked).isTrue() + } +} + +val testUiState = ContactMeViewState( + nameTw = NAME_TW, + nameEng = NAME_ENG, + position = POSITION, + phone = PHONE, + linkedinUrl = LINKEDIN_URL, + email = EMAIL, + timeZone = TIME_ZONE, +) diff --git a/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenTest.kt b/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenTest.kt new file mode 100644 index 0000000..e283d82 --- /dev/null +++ b/feature/contactme/src/androidTest/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreenTest.kt @@ -0,0 +1,56 @@ +package com.wei.picquest.feature.contactme.contactme + +import androidx.activity.ComponentActivity +import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.window.layout.DisplayFeature +import com.wei.picquest.core.designsystem.ui.PqContentType +import org.junit.Rule +import org.junit.Test + +/** + * UI tests for [ContactMeScreen] composable. + */ +class ContactMeScreenTest { + + /** + * 通常我們使用 createComposeRule(),作為 composeTestRule + * + * 但若測試案例需查找資源檔 e.g. R.string.welcome。 + * 使用 createAndroidComposeRule(),作為 composeTestRule + */ + @get:Rule + val composeTestRule = createAndroidComposeRule() + + @Test + fun checkElementsVisibility_afterOpeningTheScreen() { + contactMeScreenRobot(composeTestRule) { + setContactMeScreenContent( + contentType = PqContentType.SINGLE_PANE, + displayFeature = emptyList(), + ) + + verifyProfilePictureDisplayed() + verifyNameDisplayed() + verifyPositionDisplayed() + verifyCallDisplayed() + verifyLinkedinExists() + verifyLinkedinValueExists() + verifyEmailExists() + verifyEmailValueExists() + verifyTimeZoneExists() + verifyTimeZoneValueExists() + } + } + + @Test + fun checkCallButtonAction_afterPress() { + contactMeScreenRobot(composeTestRule) { + setContactMeScreenContent( + contentType = PqContentType.SINGLE_PANE, + displayFeature = emptyList(), + ) + } call { + isCall() + } + } +} diff --git a/feature/contactme/src/main/AndroidManifest.xml b/feature/contactme/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a5918e6 --- /dev/null +++ b/feature/contactme/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreen.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreen.kt new file mode 100644 index 0000000..d871584 --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeScreen.kt @@ -0,0 +1,457 @@ +package com.wei.picquest.feature.contactme.contactme + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.windowInsetsBottomHeight +import androidx.compose.foundation.layout.windowInsetsTopHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavController +import androidx.window.layout.DisplayFeature +import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy +import com.google.accompanist.adaptive.TwoPane +import com.wei.picquest.core.designsystem.component.FunctionalityNotAvailablePopup +import com.wei.picquest.core.designsystem.component.baselineHeight +import com.wei.picquest.core.designsystem.component.coilImagePainter +import com.wei.picquest.core.designsystem.icon.PqIcons +import com.wei.picquest.core.designsystem.theme.PqTheme +import com.wei.picquest.core.designsystem.theme.SPACING_EXTRA_LARGE +import com.wei.picquest.core.designsystem.theme.SPACING_LARGE +import com.wei.picquest.core.designsystem.theme.SPACING_SMALL +import com.wei.picquest.core.designsystem.ui.DeviceLandscapePreviews +import com.wei.picquest.core.designsystem.ui.DevicePortraitPreviews +import com.wei.picquest.core.designsystem.ui.PqContentType +import com.wei.picquest.core.designsystem.ui.PqNavigationType +import com.wei.picquest.feature.contactme.R +import com.wei.picquest.feature.contactme.contactme.ui.DecorativeBackgroundText +import com.wei.picquest.feature.contactme.contactme.ui.ProfileProperty +import com.wei.picquest.feature.contactme.contactme.ui.decorativeTextStyle +import com.wei.picquest.feature.contactme.contactme.utilities.EMAIL +import com.wei.picquest.feature.contactme.contactme.utilities.LINKEDIN_URL +import com.wei.picquest.feature.contactme.contactme.utilities.NAME_ENG +import com.wei.picquest.feature.contactme.contactme.utilities.PHONE +import com.wei.picquest.feature.contactme.contactme.utilities.POSITION +import com.wei.picquest.feature.contactme.contactme.utilities.TIME_ZONE + +/** + * + * 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 ContactMeRoute( + navController: NavController, + contentType: PqContentType, + displayFeatures: List, + navigationType: PqNavigationType, + viewModel: ContactMeViewModel = hiltViewModel(), +) { + val uiStates: ContactMeViewState by viewModel.states.collectAsStateWithLifecycle() + + ContactMeScreen( + uiStates = uiStates, + contentType = contentType, + displayFeatures = displayFeatures, + navigationType = navigationType, + onPhoneClick = { viewModel.dispatch(ContactMeViewAction.Call) }, + ) +} + +@Composable +internal fun ContactMeScreen( + uiStates: ContactMeViewState, + contentType: PqContentType, + displayFeatures: List, + navigationType: PqNavigationType = PqNavigationType.PERMANENT_NAVIGATION_DRAWER, + isPreview: Boolean = false, + onPhoneClick: () -> Unit, +) { + Surface( + modifier = Modifier + .fillMaxSize(), + ) { + if (contentType == PqContentType.DUAL_PANE) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + DecorativeBackgroundText( + text = uiStates.nameEng, + repetitions = 3, + rotationZ = -25f, + scale = 2.5f, + textStyle = decorativeTextStyle(MaterialTheme.colorScheme.error), + ) + TwoPane( + first = { + ContactMeTwoPaneFirstContent( + uiStates = uiStates, + isPreview = isPreview, + ) + }, + second = { + ContactMeTwoPaneSecondContent( + uiStates = uiStates, + navigationType = navigationType, + onPhoneClick = onPhoneClick, + ) + }, + strategy = HorizontalTwoPaneStrategy(splitFraction = 0.5f, gapWidth = SPACING_LARGE.dp), + displayFeatures = displayFeatures, + ) + } + } else { + Box( + modifier = Modifier + .fillMaxSize() + .background(color = MaterialTheme.colorScheme.background), + contentAlignment = Alignment.Center, + ) { + DecorativeBackgroundText( + text = uiStates.nameEng, + repetitions = 3, + rotationZ = -25f, + scale = 2.5f, + textStyle = decorativeTextStyle(MaterialTheme.colorScheme.primary), + ) + ContactMeSinglePaneContent( + uiStates = uiStates, + onPhoneClick = onPhoneClick, + isPreview = isPreview, + ) + } + } + } +} + +@Composable +internal fun ContactMeTwoPaneFirstContent( + uiStates: ContactMeViewState, + isPreview: Boolean, +) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + val modifier = Modifier + .clip(CircleShape) + .size(200.dp) + .border(2.dp, MaterialTheme.colorScheme.onSurface, CircleShape) + + DisplayHeadShot( + modifier = modifier, + name = uiStates.nameEng, + isPreview = isPreview, + ) + } +} + +@Composable +internal fun ContactMeTwoPaneSecondContent( + uiStates: ContactMeViewState, + navigationType: PqNavigationType, + onPhoneClick: () -> Unit, + withTopSpacer: Boolean = true, + withBottomSpacer: Boolean = true, +) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + LazyColumn( + modifier = Modifier.fillMaxWidth(), + ) { + if (withTopSpacer) { + item { + Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) + Spacer(modifier = Modifier.height(SPACING_LARGE.dp)) + } + } + item { + ContactMeCard( + uiStates = uiStates, + onPhoneClick = onPhoneClick, + ) + } + if (withBottomSpacer) { + item { + Spacer(modifier = Modifier.height(SPACING_LARGE.dp)) + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) + } + } + } + } +} + +@Composable +internal fun ContactMeSinglePaneContent( + uiStates: ContactMeViewState, + onPhoneClick: () -> Unit, + isPreview: Boolean, + withTopSpacer: Boolean = true, + withBottomSpacer: Boolean = true, +) { + LazyColumn( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + if (withTopSpacer) { + item { + Spacer(Modifier.windowInsetsTopHeight(WindowInsets.safeDrawing)) + Spacer(modifier = Modifier.height(SPACING_LARGE.dp)) + } + } + item { + val modifier = Modifier + .clip(CircleShape) + .size(150.dp) + .border(2.dp, MaterialTheme.colorScheme.onBackground, CircleShape) + + DisplayHeadShot( + modifier = modifier, + name = uiStates.nameEng, + isPreview = isPreview, + ) + } + item { + Spacer(modifier = Modifier.height(SPACING_SMALL.dp)) + ContactMeCard( + uiStates = uiStates, + onPhoneClick = onPhoneClick, + ) + } + if (withBottomSpacer) { + item { + Spacer(modifier = Modifier.height(SPACING_LARGE.dp)) + Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.safeDrawing)) + } + } + } +} + +@Composable +internal fun DisplayHeadShot( + modifier: Modifier = Modifier, + name: String, + isPreview: Boolean, +) { + val resId = R.drawable.he_wei + val painter = coilImagePainter(resId, isPreview) + + val profilePictureDescription = stringResource(R.string.profile_picture).format(name) + Image( + painter = painter, + contentDescription = profilePictureDescription, + modifier = modifier + .clip(CircleShape) + .size(300.dp) + .border(2.dp, MaterialTheme.colorScheme.onBackground, CircleShape), + ) +} + +@Composable +fun ContactMeCard( + uiStates: ContactMeViewState, + modifier: Modifier = Modifier, + onPhoneClick: () -> Unit, +) { + Card( + modifier = modifier + .padding(horizontal = SPACING_EXTRA_LARGE.dp) + .clip(CardDefaults.shape), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + ) { + Column( + modifier = Modifier + .padding(SPACING_LARGE.dp) + .fillMaxWidth(), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + NameAndPosition( + uiStates = uiStates, + modifier = Modifier.weight(1f), + ) + PhoneButton( + uiStates.nameEng, + onPhoneClick = onPhoneClick, + ) + } + ProfileProperty( + label = stringResource(id = R.string.linkedin), + value = uiStates.linkedinUrl, + isLink = true, + ) + ProfileProperty( + label = stringResource(id = R.string.email), + value = uiStates.email, + isLink = true, + ) + ProfileProperty( + label = stringResource(id = R.string.timezone), + value = uiStates.timeZone, + isLink = false, + ) + } + } +} + +@Composable +private fun NameAndPosition( + uiStates: ContactMeViewState, + modifier: Modifier, +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.Center, + ) { + val name = uiStates.nameEng + Text( + text = name, + style = MaterialTheme.typography.headlineSmall, + modifier = Modifier + .baselineHeight(32.dp) + .semantics { contentDescription = name }, + ) + val position = uiStates.position + Text( + text = position, + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier + .padding(bottom = 20.dp) + .baselineHeight(SPACING_EXTRA_LARGE.dp) + .semantics { contentDescription = position }, + ) + } +} + +@Composable +private fun PhoneButton( + name: String, + onPhoneClick: () -> Unit, +) { + val showPopup = remember { mutableStateOf(false) } + + if (showPopup.value) { + FunctionalityNotAvailablePopup(onDismiss = { + showPopup.value = false + }) + } + + val phoneDescription = stringResource(id = R.string.call).format(name) + IconButton( + onClick = { + showPopup.value = true + onPhoneClick() + }, + modifier = Modifier + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surface) + .semantics { contentDescription = phoneDescription }, + ) { + Icon( + imageVector = PqIcons.Phone, + contentDescription = null, + tint = MaterialTheme.colorScheme.outline, + ) + } +} + +@DeviceLandscapePreviews() +@Composable +fun ContactMeScreenDualPanePreview() { + PqTheme { + ContactMeScreen( + uiStates = previewUIState, + contentType = PqContentType.DUAL_PANE, + displayFeatures = emptyList(), + onPhoneClick = { }, + ) + } +} + +@DevicePortraitPreviews() +@Composable +fun ContactMeScreenSinglePanePreview() { + PqTheme { + ContactMeScreen( + uiStates = previewUIState, + contentType = PqContentType.SINGLE_PANE, + displayFeatures = emptyList(), + isPreview = true, + onPhoneClick = { }, + ) + } +} + +internal val previewUIState = ContactMeViewState( + nameEng = NAME_ENG, + position = POSITION, + phone = PHONE, + linkedinUrl = LINKEDIN_URL, + email = EMAIL, + timeZone = TIME_ZONE, +) diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewModel.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewModel.kt new file mode 100644 index 0000000..92e6b0e --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewModel.kt @@ -0,0 +1,47 @@ +package com.wei.picquest.feature.contactme.contactme + +import com.wei.picquest.core.base.BaseViewModel +import com.wei.picquest.feature.contactme.contactme.utilities.EMAIL +import com.wei.picquest.feature.contactme.contactme.utilities.LINKEDIN_URL +import com.wei.picquest.feature.contactme.contactme.utilities.NAME_ENG +import com.wei.picquest.feature.contactme.contactme.utilities.NAME_TW +import com.wei.picquest.feature.contactme.contactme.utilities.PHONE +import com.wei.picquest.feature.contactme.contactme.utilities.POSITION +import com.wei.picquest.feature.contactme.contactme.utilities.TIME_ZONE +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class ContactMeViewModel @Inject constructor() : BaseViewModel< + ContactMeViewAction, + ContactMeViewState, + >(ContactMeViewState()) { + + init { + getProfile() + } + + private fun getProfile() { + updateState { + copy( + nameTw = NAME_TW, + nameEng = NAME_ENG, + position = POSITION, + phone = PHONE, + linkedinUrl = LINKEDIN_URL, + email = EMAIL, + timeZone = TIME_ZONE, + ) + } + } + + private fun callPhone() { + // TODO + } + + override fun dispatch(action: ContactMeViewAction) { + when (action) { + is ContactMeViewAction.Call -> callPhone() + } + } +} diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewState.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewState.kt new file mode 100644 index 0000000..5a6fc8a --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ContactMeViewState.kt @@ -0,0 +1,18 @@ +package com.wei.picquest.feature.contactme.contactme + +import com.wei.picquest.core.base.Action +import com.wei.picquest.core.base.State + +sealed class ContactMeViewAction : Action { + object Call : ContactMeViewAction() +} + +data class ContactMeViewState( + val nameTw: String = "N/A", + val nameEng: String = "N/A", + val position: String = "N/A", + val phone: String = "N/A", + val linkedinUrl: String = "N/A", + val email: String = "N/A", + val timeZone: String = "N/A", +) : State diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/navigation/ContactMeNavigation.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/navigation/ContactMeNavigation.kt new file mode 100644 index 0000000..276d34e --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/navigation/ContactMeNavigation.kt @@ -0,0 +1,33 @@ +package com.wei.picquest.feature.contactme.contactme.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.NavOptions +import androidx.navigation.compose.composable +import androidx.window.layout.DisplayFeature +import com.wei.picquest.core.designsystem.ui.PqContentType +import com.wei.picquest.core.designsystem.ui.PqNavigationType +import com.wei.picquest.feature.contactme.contactme.ContactMeRoute + +const val contactMeRoute = "contact_me_route" + +fun NavController.navigateToContactMe(navOptions: NavOptions? = null) { + this.navigate(contactMeRoute, navOptions) +} + +fun NavGraphBuilder.contactMeGraph( + navController: NavController, + contentType: PqContentType, + displayFeatures: List, + navigationType: PqNavigationType, + nestedGraphs: NavGraphBuilder.() -> Unit, +) { + composable(route = contactMeRoute) { + ContactMeRoute( + navController = navController, + contentType = contentType, + displayFeatures = displayFeatures, + navigationType = navigationType, + ) + } +} diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/DecorativeBackgroundText.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/DecorativeBackgroundText.kt new file mode 100644 index 0000000..107d8a6 --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/DecorativeBackgroundText.kt @@ -0,0 +1,54 @@ +package com.wei.picquest.feature.contactme.contactme.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign + +@Composable +internal fun DecorativeBackgroundText( + text: String, + repetitions: Int, + rotationZ: Float = 0f, + scale: Float = 1f, + textStyle: TextStyle = TextStyle( + fontSize = MaterialTheme.typography.displayLarge.fontSize, + color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f), + textAlign = TextAlign.Center, + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + ), +) { + Column( + modifier = Modifier + .graphicsLayer(rotationZ = rotationZ) + .scale(scale), + ) { + repeat(repetitions) { + Text( + text = text, + style = textStyle, + modifier = Modifier.semantics { contentDescription = "" }, + ) + } + } +} + +@Composable +fun decorativeTextStyle(color: Color) = TextStyle( + fontSize = MaterialTheme.typography.displayLarge.fontSize, + color = color.copy(alpha = 0.8f), + textAlign = TextAlign.Center, + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, +) diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/ProfileProperty.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/ProfileProperty.kt new file mode 100644 index 0000000..fed6f8c --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/ui/ProfileProperty.kt @@ -0,0 +1,42 @@ +package com.wei.picquest.feature.contactme.contactme.ui + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Divider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import com.wei.picquest.core.designsystem.component.baselineHeight +import com.wei.picquest.core.designsystem.theme.SPACING_EXTRA_LARGE +import com.wei.picquest.core.designsystem.theme.SPACING_MEDIUM + +@Composable +fun ProfileProperty(label: String, value: String, isLink: Boolean = false) { + Column(modifier = Modifier.padding(vertical = SPACING_MEDIUM.dp)) { + Divider(color = MaterialTheme.colorScheme.outline) + Text( + text = label, + modifier = Modifier + .baselineHeight(SPACING_EXTRA_LARGE.dp) + .semantics { contentDescription = label }, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + val style = if (isLink) { + MaterialTheme.typography.bodyLarge.copy(color = MaterialTheme.colorScheme.primary) + } else { + MaterialTheme.typography.bodyLarge + } + Text( + text = value, + modifier = Modifier + .baselineHeight(SPACING_EXTRA_LARGE.dp) + .semantics { contentDescription = value }, + style = style, + ) + } +} diff --git a/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/utilities/Constants.kt b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/utilities/Constants.kt new file mode 100644 index 0000000..e113b00 --- /dev/null +++ b/feature/contactme/src/main/java/com/wei/picquest/feature/contactme/contactme/utilities/Constants.kt @@ -0,0 +1,12 @@ +package com.wei.picquest.feature.contactme.contactme.utilities + +/** + * Constants used throughout the feature:contactme. + */ +const val NAME_TW = "HE, XUAN-WEI" +const val NAME_ENG = "HE, XUAN-WEI" +const val POSITION = "Android Developer" +const val PHONE = "+886-900-123-456" +const val LINKEDIN_URL = "in/he-xuen-wei" +const val EMAIL = "azrael8576love2008@gmail.com" +const val TIME_ZONE = "Asia/Taipei GMT +08:00" diff --git a/feature/contactme/src/main/res/drawable/he_wei.jpg b/feature/contactme/src/main/res/drawable/he_wei.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5f280cf6ef1f9e92ddfd300953ef8db3b05aa5e4 GIT binary patch literal 63887 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 + + %s 的大頭貼 + LinkedIn + Email + 時區 + 撥打給 %s + \ No newline at end of file diff --git a/feature/contactme/src/main/res/values/strings.xml b/feature/contactme/src/main/res/values/strings.xml new file mode 100644 index 0000000..b426f46 --- /dev/null +++ b/feature/contactme/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + + %s\'s profile picture + LinkedIn + Email + Timezone + Call %s + \ No newline at end of file diff --git a/feature/contactme/utilities/Constants.kt b/feature/contactme/utilities/Constants.kt new file mode 100644 index 0000000..7a5580d --- /dev/null +++ b/feature/contactme/utilities/Constants.kt @@ -0,0 +1,12 @@ +package com.wei.amazingtalker.feature.contactme.utilities + +/** + * Constants used throughout the feature:contactme. + */ +const val NAME_TW = "HE, XUAN-WEI" +const val NAME_ENG = "HE, XUAN-WEI" +const val POSITION = "Android Developer" +const val PHONE = "+886-900-123-456" +const val LINKEDIN_URL = "in/he-xuen-wei" +const val EMAIL = "azrael8576love2008@gmail.com" +const val TIME_ZONE = "Asia/Taipei GMT +08:00" diff --git a/settings.gradle.kts b/settings.gradle.kts index 621bb1e..d475a70 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,3 +30,4 @@ include(":ui-test-hilt-manifest") include(":feature:home") include(":feature:photo") +include(":feature:contactme")