From 9da6c2410088d4c3a3bd32e843d6b6e9bb14e236 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 18:03:55 +0000 Subject: [PATCH 01/64] chore(deps): update dependency com.google.firebase.appdistribution to v5 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0a8c342..44c9be8f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ gmsPlugin = "4.4.1" firebaseBom = "32.8.1" firebaseCrashlyticsPlugin = "2.9.9" firebasePerfPlugin = "1.4.2" -firebaseAppdistributionPlugin = "4.2.0" +firebaseAppdistributionPlugin = "5.0.0" hilt = "2.51.1" junit4 = "4.13.2" kotlin = "1.9.23" From 0cf65fe4772244d9284a7f371491e82460c0477f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 22:45:25 +0000 Subject: [PATCH 02/64] fix(deps): update dependency com.google.firebase:firebase-bom to v33 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0a8c342..e6aa6e93 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ coroutines = "1.8.0" coroutineTest = "1.8.0" dokka = "1.9.20" gmsPlugin = "4.4.1" -firebaseBom = "32.8.1" +firebaseBom = "33.0.0" firebaseCrashlyticsPlugin = "2.9.9" firebasePerfPlugin = "1.4.2" firebaseAppdistributionPlugin = "4.2.0" From 057393a0f1f4631007438b9e0a6ae1ec28ecf6c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 08:20:25 +0000 Subject: [PATCH 03/64] chore(deps): update roborazzi to v1.14.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0a8c342..724e0932 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,7 +43,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.10" -roborazzi = "1.13.0" +roborazzi = "1.14.0" showkase = "1.0.2" # ** I'm using it, so no deletions allowed. ** From 148881886db822a4b89c9d5df9e0633adca3bfc4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 07:04:42 +0000 Subject: [PATCH 04/64] chore(deps): update kotlin monorepo to v1.9.24 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c3178de..28ecb3c9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ firebasePerfPlugin = "1.4.2" firebaseAppdistributionPlugin = "5.0.0" hilt = "2.51.1" junit4 = "4.13.2" -kotlin = "1.9.23" +kotlin = "1.9.24" kotlinxSerializationJson = "1.6.3" kotlinxDatetime = "0.5.0" ksp = "1.9.23-1.0.20" From 69f1e853bd74c0dce8df19c2ba547609938ceaed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 07:04:48 +0000 Subject: [PATCH 05/64] chore(deps): update roborazzi to v1.15.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c3178de..98b3f238 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,7 +43,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.10" -roborazzi = "1.14.0" +roborazzi = "1.15.0" showkase = "1.0.2" # ** I'm using it, so no deletions allowed. ** From e5c08b9d1964f781e060ff9a6c5a28e62b40e509 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 11:29:42 +0000 Subject: [PATCH 06/64] fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-coroutines-android to v1.8.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c3178de..c2c55d60 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ androidxNavigation = "2.8.0-alpha08" androidxTestCore = "1.5.0" appUpdate = "2.1.0" coil = "2.6.0" -coroutines = "1.8.0" +coroutines = "1.8.1" coroutineTest = "1.8.0" dokka = "1.9.20" gmsPlugin = "4.4.1" From 99f9bf7b15adb8ef633046a63ffe586f77d627aa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 11:29:46 +0000 Subject: [PATCH 07/64] fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-coroutines-test to v1.8.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c3178de..5dca0a6f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ androidxTestCore = "1.5.0" appUpdate = "2.1.0" coil = "2.6.0" coroutines = "1.8.0" -coroutineTest = "1.8.0" +coroutineTest = "1.8.1" dokka = "1.9.20" gmsPlugin = "4.4.1" firebaseBom = "33.0.0" From cf1027b88237ce9c63ed0c60eef531879beeabe5 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 11 May 2024 19:58:46 +0900 Subject: [PATCH 08/64] feaute: change library to AboutLibraries for licenses --- README.md | 2 +- app/build.gradle.kts | 5 +- .../view/navigation/Navigation.kt | 8 ++ build.gradle.kts | 2 +- .../core/ui/navigation/Nav.kt | 3 + .../core/ui/parts/card/TitleCard.kt | 8 +- feature/info/build.gradle.kts | 2 +- .../feature/info/InfoScreen.kt | 24 +++--- .../feature/info/licence/LicenseScreen.kt | 75 +++++++++++++++++++ .../feature/info/licence/LicenseViewModel.kt | 10 +++ gradle/libs.versions.toml | 11 ++- 11 files changed, 123 insertions(+), 27 deletions(-) create mode 100644 feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt create mode 100644 feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt diff --git a/README.md b/README.md index ceffde24..6baf59db 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ https://github.com/kosenda/hiragana-converter/blob/develop/REFERENCE.md ## Typical libraries used |Name|Brief description| |:--|:--| +|AboutLibraries|OSS Licenses| |Analytics|Firebase analytics| |App Update|In App Update| |App Review|In App Review| @@ -47,7 +48,6 @@ https://github.com/kosenda/hiragana-converter/blob/develop/REFERENCE.md |Ktlint|Formatter| |Material3|Design| |Mockk|Unit test mock| -|OSS licenses plugin|OSS Licenses| |Preferences DataStore|Permanent data| |Renovate|Automated project dependency updates| |Retrofit2|Library for API communications| diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9041cf83..04fe4052 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,7 +6,6 @@ plugins { id("hiraganaconverter.android.application") id("hiraganaconverter.android.application.jacoco") id("hiraganaconverter.android.hilt") - alias(libs.plugins.oss.licenses) alias(libs.plugins.kotlin.serialization) alias(libs.plugins.secrets) alias(libs.plugins.dokka) @@ -15,6 +14,7 @@ plugins { alias(libs.plugins.firebase.crashlytics) alias(libs.plugins.firebase.perf) alias(libs.plugins.firebase.appdistribution) + alias(libs.plugins.aboutLibraries) } android { @@ -121,9 +121,6 @@ dependencies { // Timber implementation(libs.timber) - // OSS Licenses - implementation(libs.play.oss.licenses) - // Splash Screen implementation(libs.androidx.core.splashscreen) diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt index dbae67b0..6585b072 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt +++ b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt @@ -33,6 +33,7 @@ import ksnd.hiraganaconverter.core.ui.navigation.Nav import ksnd.hiraganaconverter.feature.converter.ConverterScreen import ksnd.hiraganaconverter.feature.history.ConvertHistoryScreen import ksnd.hiraganaconverter.feature.info.InfoScreen +import ksnd.hiraganaconverter.feature.info.licence.LicenseScreen import ksnd.hiraganaconverter.feature.setting.SettingScreen import ksnd.hiraganaconverter.view.TopBar @@ -99,6 +100,13 @@ fun Navigation( InfoScreen( viewModel = hiltViewModel(), onBackPressed = ::navigateUp, + onClickLicense = { transitionScreen(Nav.License) }, + ) + } + slideHorizontallyComposable { + LicenseScreen( + viewModel = hiltViewModel(), + onBackPressed = ::navigateUp, ) } } diff --git a/build.gradle.kts b/build.gradle.kts index 3d54e5da..18f83029 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,6 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.hilt) apply false - alias(libs.plugins.oss.licenses) apply false alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.secrets) apply false alias(libs.plugins.dokka) apply false @@ -17,6 +16,7 @@ plugins { alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.firebase.perf) apply false alias(libs.plugins.firebase.appdistribution) apply false + alias(libs.plugins.aboutLibraries) apply false } tasks.create("jacocoTestReport") { diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt index a922063f..bff13fa5 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt @@ -14,4 +14,7 @@ sealed class Nav { @Serializable data object Info : Nav() + + @Serializable + data object License : Nav() } diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/TitleCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/TitleCard.kt index 513232f8..c5302f7c 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/TitleCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/TitleCard.kt @@ -27,9 +27,13 @@ import ksnd.hiraganaconverter.core.ui.theme.contentBrush import ksnd.hiraganaconverter.core.ui.theme.primaryBrush @Composable -fun TitleCard(text: String, painter: Painter) { +fun TitleCard( + text: String, + painter: Painter, + modifier: Modifier = Modifier, +) { Card( - modifier = Modifier.padding(top = 28.dp, bottom = 4.dp), + modifier = modifier.padding(top = 28.dp, bottom = 4.dp), colors = CardDefaults.cardColors( containerColor = Color.Transparent, ), diff --git a/feature/info/build.gradle.kts b/feature/info/build.gradle.kts index ae51381e..8ab9baf3 100644 --- a/feature/info/build.gradle.kts +++ b/feature/info/build.gradle.kts @@ -25,5 +25,5 @@ dependencies { implementation(project(":core:model")) implementation(libs.androidx.hilt.navigation.compose) implementation(libs.accompanist.webView) - implementation(libs.play.oss.licenses) + implementation(libs.aboutLibraries) } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt index d7f0d2d0..63a0ebff 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt @@ -1,6 +1,5 @@ package ksnd.hiraganaconverter.feature.info -import android.content.Intent import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -52,8 +51,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat -import com.google.android.gms.oss.licenses.OssLicensesMenuActivity import kotlinx.coroutines.launch import ksnd.hiraganaconverter.core.analytics.LocalAnalytics import ksnd.hiraganaconverter.core.analytics.Screen @@ -74,6 +71,7 @@ import ksnd.hiraganaconverter.core.ui.theme.urlColor fun InfoScreen( viewModel: InfoViewModel, onBackPressed: () -> Unit, + onClickLicense: () -> Unit, ) { val analytics = LocalAnalytics.current @@ -81,7 +79,11 @@ fun InfoScreen( analytics.logScreen(Screen.INFO) } - InfoScreenContent(versionName = viewModel.versionName, onBackPressed = onBackPressed) + InfoScreenContent( + versionName = viewModel.versionName, + onBackPressed = onBackPressed, + onClickLicense = onClickLicense, + ) } @OptIn(ExperimentalMaterial3Api::class) @@ -89,6 +91,7 @@ fun InfoScreen( private fun InfoScreenContent( versionName: String, onBackPressed: () -> Unit, + onClickLicense: () -> Unit, ) { val urlHandler = LocalUriHandler.current val context = LocalContext.current @@ -132,7 +135,7 @@ private fun InfoScreenContent( AppInfoContent(versionName = versionName, onURLClick = { isShowMovesToAppSiteDialog = true }) DeveloperInfoContent() APIInfoContent(onURLClick = { isShowMovesToApiSiteDialog = true }) - LicensesContent() + LicensesContent(onClickLicense = onClickLicense) PrivacyPolicyContent() Spacer(modifier = Modifier.height(48.dp)) } @@ -316,20 +319,16 @@ private fun APIInfoContent(onURLClick: () -> Unit) { } @Composable -private fun LicensesContent() { - val context = LocalContext.current +private fun LicensesContent(onClickLicense: () -> Unit) { val buttonText = stringResource(id = R.string.oss_licenses) + TitleCard( text = stringResource(id = R.string.licenses_title), painter = painterResource(id = R.drawable.ic_outline_info_24), ) TransitionButton( text = buttonText, - onClick = { - val intent = Intent(context, OssLicensesMenuActivity::class.java) - intent.putExtra("title", buttonText) - ContextCompat.startActivity(context, intent, null) - }, + onClick = onClickLicense, ) } @@ -379,6 +378,7 @@ fun PreviewInfoScreenContent() { InfoScreenContent( versionName = "1.0.0", onBackPressed = {}, + onClickLicense = {}, ) } } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt new file mode 100644 index 00000000..9215fdf5 --- /dev/null +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -0,0 +1,75 @@ +package ksnd.hiraganaconverter.feature.info.licence + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.displayCutoutPadding +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer +import kotlinx.coroutines.launch +import ksnd.hiraganaconverter.core.resource.R +import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable +import ksnd.hiraganaconverter.core.ui.parts.BackTopBar +import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard + +@Composable +fun LicenseScreen(viewModel: LicenseViewModel, onBackPressed: () -> Unit) { + LicenseContent(onBackPressed = onBackPressed) +} + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) +@Composable +fun LicenseContent( + onBackPressed: () -> Unit, +) { + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) + val coroutineScope = rememberCoroutineScope() + val lazyListState = rememberLazyListState() + + Scaffold( + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) + .background(MaterialTheme.colorScheme.surface) + .displayCutoutPadding(), + topBar = { + BackTopBar( + scrollBehavior = scrollBehavior, + modifier = Modifier.noRippleClickable { + coroutineScope.launch { + lazyListState.animateScrollToItem(0) + } + }, + onBackPressed = onBackPressed, + ) + }, + ) { innerPadding -> + LibrariesContainer( + modifier = Modifier + .padding(innerPadding) + .fillMaxSize(), + lazyListState = lazyListState, + header = { + item { + TitleCard( + text = stringResource(id = R.string.licenses_title), + painter = painterResource(id = R.drawable.ic_outline_info_24), + modifier = Modifier.padding(start = 16.dp), + ) + } + } + ) + } +} diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt new file mode 100644 index 00000000..4a448c71 --- /dev/null +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt @@ -0,0 +1,10 @@ +package ksnd.hiraganaconverter.feature.info.licence + +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class LicenseViewModel @Inject constructor() : ViewModel() { + +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 013e7b54..43242dda 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,8 +31,6 @@ ktlint = "1.2.1" lazyColumnScrollbar = "1.9.0" lottie = "6.4.0" okhttp3 = "4.12.0" -ossLicenses = "17.0.1" -ossLicensesPlugin = "0.10.6" playReview = "2.0.1" retrofit = "2.11.0" retrofitSerialization = "1.0.0" @@ -45,6 +43,7 @@ turbine = "1.1.0" mockk = "1.13.10" roborazzi = "1.15.0" showkase = "1.0.2" +aboutLibraries = "11.1.4" # ** I'm using it, so no deletions allowed. ** androidxComposeCompiler = "1.5.11" @@ -88,9 +87,6 @@ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx- # Lottie lottie = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" } -# Play Services -play-oss-licenses = { group = "com.google.android.gms", name = "play-services-oss-licenses", version.ref = "ossLicenses" } - # Ktlint ktlint = { group = "com.pinterest.ktlint", name = "ktlint-cli", version.ref = "ktlint" } @@ -158,13 +154,15 @@ showkase = { group = "com.airbnb.android", name = "showkase", version.ref = "sho showkase-annotation = { group = "com.airbnb.android", name = "showkase-annotation", version.ref = "showkase" } showkase-processor = { group = "com.airbnb.android", name = "showkase-processor", version.ref = "showkase" } +# AboutLibraries +aboutLibraries = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibraries" } + [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -oss-licenses = { id = "com.google.android.gms.oss-licenses-plugin", version.ref = "ossLicensesPlugin" } secrets = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version.ref = "secrets" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" } @@ -173,3 +171,4 @@ firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = " firebase-appdistribution = { id = "com.google.firebase.appdistribution", version.ref = "firebaseAppdistributionPlugin" } firebase-perf = { id = "com.google.firebase.firebase-perf", version.ref = "firebasePerfPlugin" } androidLibrary = { id = "com.android.library", version.ref = "androidGradlePlugin" } +aboutLibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibraries" } From b1d9817b3799d8a0dc8f057669b52684746e1032 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 12 May 2024 14:08:35 +0900 Subject: [PATCH 09/64] feature: custom desing --- app/build.gradle.kts | 3 + .../view/navigation/Navigation.kt | 24 ++- .../res/drawable/baseline_open_in_new_24.xml | 5 + core/ui/build.gradle.kts | 3 + .../core/ui/navigation/Nav.kt | 6 + .../feature/info/licence/LicenseScreen.kt | 178 ++++++++++++++++-- .../feature/info/licence/LicenseViewModel.kt | 28 ++- .../info/licensedetail/LicenseDetailScreen.kt | 103 ++++++++++ 8 files changed, 324 insertions(+), 26 deletions(-) create mode 100644 core/resource/src/main/res/drawable/baseline_open_in_new_24.xml create mode 100644 feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 04fe4052..4fad6067 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -143,6 +143,9 @@ dependencies { // kotlinx serialization implementation(libs.kotlinx.serialization.json) + + // AboutLibraries + implementation(libs.aboutLibraries) } tasks.withType().configureEach { diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt index 6585b072..946a0d2a 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt +++ b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt @@ -29,11 +29,13 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import androidx.navigation.toRoute import ksnd.hiraganaconverter.core.ui.navigation.Nav import ksnd.hiraganaconverter.feature.converter.ConverterScreen import ksnd.hiraganaconverter.feature.history.ConvertHistoryScreen import ksnd.hiraganaconverter.feature.info.InfoScreen import ksnd.hiraganaconverter.feature.info.licence.LicenseScreen +import ksnd.hiraganaconverter.feature.info.licensedetail.LicenseDetailScreen import ksnd.hiraganaconverter.feature.setting.SettingScreen import ksnd.hiraganaconverter.view.TopBar @@ -58,10 +60,14 @@ fun Navigation( } } - fun transitionScreen(nav: Nav) { + fun navigateScreen(nav: Nav) { navController.navigate(nav) { launchSingleTop = true } } + fun navigateLicenseDetail(libraryName: String, licenseContent: String) { + navController.navigate(Nav.LicenseDetail(libraryName, licenseContent)) + } + NavHost( navController = navController, startDestination = Nav.Converter(receivedText = receivedText?.toString() ?: ""), @@ -77,9 +83,9 @@ fun Navigation( TopBar( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, scrollBehavior = scrollBehavior, - transitionHistory = { transitionScreen(Nav.History) }, - transitionSetting = { transitionScreen(Nav.Setting) }, - transitionInfo = { transitionScreen(Nav.Info) }, + transitionHistory = { navigateScreen(Nav.History) }, + transitionSetting = { navigateScreen(Nav.Setting) }, + transitionInfo = { navigateScreen(Nav.Info) }, ) }, ) @@ -100,12 +106,20 @@ fun Navigation( InfoScreen( viewModel = hiltViewModel(), onBackPressed = ::navigateUp, - onClickLicense = { transitionScreen(Nav.License) }, + onClickLicense = { navigateScreen(Nav.License) }, ) } slideHorizontallyComposable { LicenseScreen( viewModel = hiltViewModel(), + navigateLicenseDetail = ::navigateLicenseDetail, + onBackPressed = ::navigateUp, + ) + } + slideHorizontallyComposable { + LicenseDetailScreen( + libraryName = it.toRoute().libraryName, + licenseContent = it.toRoute().licenseContent, onBackPressed = ::navigateUp, ) } diff --git a/core/resource/src/main/res/drawable/baseline_open_in_new_24.xml b/core/resource/src/main/res/drawable/baseline_open_in_new_24.xml new file mode 100644 index 00000000..99987474 --- /dev/null +++ b/core/resource/src/main/res/drawable/baseline_open_in_new_24.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/core/ui/build.gradle.kts b/core/ui/build.gradle.kts index ac389d1e..e7bb072c 100644 --- a/core/ui/build.gradle.kts +++ b/core/ui/build.gradle.kts @@ -30,4 +30,7 @@ dependencies { // kotlinx serialization implementation(libs.kotlinx.serialization.json) + + // AboutLibraries + implementation(libs.aboutLibraries) } diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt index bff13fa5..7f03148a 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/navigation/Nav.kt @@ -17,4 +17,10 @@ sealed class Nav { @Serializable data object License : Nav() + + @Serializable + data class LicenseDetail( + val libraryName: String, + val licenseContent: String, + ) : Nav() } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 9215fdf5..40b2e2d2 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -1,38 +1,75 @@ package ksnd.hiraganaconverter.feature.info.licence -import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.displayCutoutPadding -import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Badge +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.mikepenz.aboutlibraries.Libs +import com.mikepenz.aboutlibraries.entity.Library +import com.mikepenz.aboutlibraries.ui.compose.m3.util.author +import com.mikepenz.aboutlibraries.ui.compose.m3.util.htmlReadyLicenseContent import kotlinx.coroutines.launch import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable import ksnd.hiraganaconverter.core.ui.parts.BackTopBar -import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.rememberButtonScaleState @Composable -fun LicenseScreen(viewModel: LicenseViewModel, onBackPressed: () -> Unit) { - LicenseContent(onBackPressed = onBackPressed) +fun LicenseScreen( + viewModel: LicenseViewModel, + navigateLicenseDetail: (libraryName: String, licenseContent: String) -> Unit, + onBackPressed: () -> Unit, +) { + val libs by viewModel.libs.collectAsStateWithLifecycle() + + LicenseContent( + libs = libs, + navigateLicenseDetail = navigateLicenseDetail, + onBackPressed = onBackPressed + ) } -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun LicenseContent( + libs: Libs?, + navigateLicenseDetail: (libraryName: String, licenseContent: String) -> Unit, onBackPressed: () -> Unit, ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) @@ -53,23 +90,126 @@ fun LicenseContent( } }, onBackPressed = onBackPressed, + title = { + Text( + text = stringResource(id = R.string.licenses_title), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary, + ) + }, ) }, ) { innerPadding -> - LibrariesContainer( - modifier = Modifier - .padding(innerPadding) - .fillMaxSize(), - lazyListState = lazyListState, - header = { - item { - TitleCard( - text = stringResource(id = R.string.licenses_title), - painter = painterResource(id = R.drawable.ic_outline_info_24), - modifier = Modifier.padding(start = 16.dp), + LazyColumn( + modifier = Modifier.padding( + paddingValues = PaddingValues( + start = innerPadding.calculateStartPadding(LocalLayoutDirection.current), + top = innerPadding.calculateTopPadding(), + end = innerPadding.calculateEndPadding(LocalLayoutDirection.current), + ), + ), + verticalArrangement = Arrangement.spacedBy(8.dp), + state = lazyListState, + contentPadding = PaddingValues(horizontal = 16.dp), + ) { + items( + items = libs?.libraries ?: emptyList(), + key = { it.uniqueId } + ) { library -> + LibraryItem( + library = library, + navigateLicenseDetail = navigateLicenseDetail, + ) + } + item { + Spacer( + modifier = Modifier + .navigationBarsPadding() + .height(48.dp), + ) + } + } + } +} + +@Composable +fun LibraryItem( + library: Library, + navigateLicenseDetail: (libraryName: String, licenseContent: String) -> Unit, +) { + val urlHandler = LocalUriHandler.current + val buttonScaleState = rememberButtonScaleState() + val isNotExistLicenseContent = library.licenses.firstOrNull()?.htmlReadyLicenseContent.isNullOrBlank() + + Card( + modifier = Modifier + .scale(scale = buttonScaleState.animationScale.value) + .noRippleClickable( + interactionSource = buttonScaleState.interactionSource, + onClick = { + if (isNotExistLicenseContent) { + library.licenses.first().url?.let { + urlHandler.openUri(it) + } + } else { + navigateLicenseDetail(library.name, library.licenses.first().htmlReadyLicenseContent!!) + } + }, + ), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant), + ) { + Row( + modifier = Modifier.padding(all = 8.dp), + ) { + Column( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + Text( + text = library.name, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary, + fontWeight = FontWeight.SemiBold, + ) + + if (library.author.isNotBlank()) { + Text( + text = library.author, + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.tertiary, ) } + + library.artifactVersion?.let { version -> + Text( + text = "version: %s".format(version), + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.secondary, + ) + } + + library.licenses.forEach { license -> + Badge( + contentColor = MaterialTheme.colorScheme.onPrimary, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Text( + text = license.name, + modifier = Modifier.padding(horizontal = 4.dp), + style = MaterialTheme.typography.labelMedium, + ) + } + } + } + + if (isNotExistLicenseContent) { + Image( + modifier = Modifier.size(28.dp), + painter = painterResource(id = R.drawable.baseline_open_in_new_24), + contentDescription = "open license", + colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.primary), + ) } - ) + } } } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt index 4a448c71..7e06418b 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseViewModel.kt @@ -1,10 +1,34 @@ package ksnd.hiraganaconverter.feature.info.licence +import android.content.Context import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.mikepenz.aboutlibraries.Libs +import com.mikepenz.aboutlibraries.util.withContext import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch +import ksnd.hiraganaconverter.core.resource.di.IODispatcher import javax.inject.Inject @HiltViewModel -class LicenseViewModel @Inject constructor() : ViewModel() { +class LicenseViewModel @Inject constructor( + @ApplicationContext private val context: Context, + @IODispatcher private val ioDispatcher: CoroutineDispatcher, +) : ViewModel() { + private val _libs = MutableStateFlow(null) + val libs: StateFlow = _libs -} \ No newline at end of file + init { + getLicenses() + } + + private fun getLicenses() { + viewModelScope.launch(ioDispatcher) { + _libs.value = Libs.Builder().withContext(context).build() + } + } +} diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt new file mode 100644 index 00000000..b12b3df4 --- /dev/null +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt @@ -0,0 +1,103 @@ +package ksnd.hiraganaconverter.feature.info.licensedetail + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.displayCutoutPadding +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.rememberTopAppBarState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.mikepenz.aboutlibraries.ui.compose.m3.HtmlText +import kotlinx.coroutines.launch +import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable +import ksnd.hiraganaconverter.core.ui.parts.BackTopBar + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LicenseDetailScreen( + libraryName: String, + licenseContent: String, + onBackPressed: () -> Unit +) { + val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) + val coroutineScope = rememberCoroutineScope() + val scrollState = rememberScrollState() + + Scaffold( + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) + .background(MaterialTheme.colorScheme.surface) + .displayCutoutPadding(), + topBar = { + BackTopBar( + scrollBehavior = scrollBehavior, + modifier = Modifier.noRippleClickable { + coroutineScope.launch { + scrollState.animateScrollTo(0) + } + }, + onBackPressed = onBackPressed, + title = { + Text( + text = libraryName, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + }, + ) + }, + ) { innerPadding -> + Column( + modifier = Modifier + .padding( + paddingValues = PaddingValues( + start = innerPadding.calculateStartPadding(LocalLayoutDirection.current), + top = innerPadding.calculateTopPadding(), + end = innerPadding.calculateEndPadding(LocalLayoutDirection.current), + ), + ) + .verticalScroll(scrollState) + .padding(horizontal = 16.dp), + ) { + Text( + text = libraryName, + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.primary, + fontWeight = FontWeight.SemiBold, + ) + + HtmlText( + html = licenseContent, + modifier = Modifier.padding(top = 8.dp), + color = MaterialTheme.colorScheme.secondary, + ) + + Spacer( + modifier = Modifier + .navigationBarsPadding() + .height(48.dp), + ) + } + } +} From 4975984cb57842729b07563d799685c87b368d5d Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 12 May 2024 17:07:35 +0900 Subject: [PATCH 10/64] feature: add previews --- .../view/navigation/Navigation.kt | 2 +- .../feature/info/licence/LicenseScreen.kt | 19 ++++++++- .../licensedetail/LicenseDetailScreen.kt | 19 ++++++++- .../feature/info/licence/mock/MockLibs.kt | 42 +++++++++++++++++++ 4 files changed, 77 insertions(+), 5 deletions(-) rename feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/{ => licence}/licensedetail/LicenseDetailScreen.kt (87%) create mode 100644 feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt index 946a0d2a..571f83f8 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt +++ b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt @@ -35,7 +35,7 @@ import ksnd.hiraganaconverter.feature.converter.ConverterScreen import ksnd.hiraganaconverter.feature.history.ConvertHistoryScreen import ksnd.hiraganaconverter.feature.info.InfoScreen import ksnd.hiraganaconverter.feature.info.licence.LicenseScreen -import ksnd.hiraganaconverter.feature.info.licensedetail.LicenseDetailScreen +import ksnd.hiraganaconverter.feature.info.licence.licensedetail.LicenseDetailScreen import ksnd.hiraganaconverter.feature.setting.SettingScreen import ksnd.hiraganaconverter.view.TopBar diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 40b2e2d2..3e5f414f 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -48,7 +48,10 @@ import kotlinx.coroutines.launch import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable import ksnd.hiraganaconverter.core.ui.parts.BackTopBar +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.rememberButtonScaleState +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme +import ksnd.hiraganaconverter.feature.info.licence.mock.MockLibs @Composable fun LicenseScreen( @@ -61,7 +64,7 @@ fun LicenseScreen( LicenseContent( libs = libs, navigateLicenseDetail = navigateLicenseDetail, - onBackPressed = onBackPressed + onBackPressed = onBackPressed, ) } @@ -114,7 +117,7 @@ fun LicenseContent( ) { items( items = libs?.libraries ?: emptyList(), - key = { it.uniqueId } + key = { it.uniqueId }, ) { library -> LibraryItem( library = library, @@ -213,3 +216,15 @@ fun LibraryItem( } } } + +@UiModePreview +@Composable +fun PreviewLicenseContent() { + HiraganaConverterTheme { + LicenseContent( + libs = MockLibs.item, + navigateLicenseDetail = { _, _ -> }, + onBackPressed = {}, + ) + } +} diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt similarity index 87% rename from feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt rename to feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt index b12b3df4..dc655000 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licensedetail/LicenseDetailScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt @@ -1,4 +1,4 @@ -package ksnd.hiraganaconverter.feature.info.licensedetail +package ksnd.hiraganaconverter.feature.info.licence.licensedetail import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column @@ -25,18 +25,21 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.unit.dp import com.mikepenz.aboutlibraries.ui.compose.m3.HtmlText import kotlinx.coroutines.launch import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable import ksnd.hiraganaconverter.core.ui.parts.BackTopBar +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun LicenseDetailScreen( libraryName: String, licenseContent: String, - onBackPressed: () -> Unit + onBackPressed: () -> Unit, ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) val coroutineScope = rememberCoroutineScope() @@ -101,3 +104,15 @@ fun LicenseDetailScreen( } } } + +@UiModePreview +@Composable +fun PreviewLicenseDetailScreen() { + HiraganaConverterTheme { + LicenseDetailScreen( + libraryName = "SampleLibrary", + licenseContent = LoremIpsum().values.first(), + onBackPressed = {}, + ) + } +} diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt new file mode 100644 index 00000000..f3a1a723 --- /dev/null +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt @@ -0,0 +1,42 @@ +package ksnd.hiraganaconverter.feature.info.licence.mock + +import com.mikepenz.aboutlibraries.Libs +import com.mikepenz.aboutlibraries.entity.Developer +import com.mikepenz.aboutlibraries.entity.Library +import com.mikepenz.aboutlibraries.entity.License +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf + +object MockLibs { + private val mockLicense = License( + name = "SampleLicense", + url = "https://example.com", + licenseContent = "SampleLicenseContent", + hash = "1" + ) + + private val mockLibrary = Library( + uniqueId = "1", + artifactVersion = "1.0.0", + name = "SampleLibrary", + description = "", + website = "", + developers = persistentListOf( + Developer("SampleDeveloper", "https://example.com"), + ), + licenses = persistentSetOf(mockLicense), + organization = null, + scm = null, + ) + + val item = Libs( + libraries = persistentListOf( + mockLibrary, + mockLibrary.copy(uniqueId = "2", licenses = persistentSetOf()), + mockLibrary.copy(uniqueId = "3", licenses = persistentSetOf(mockLicense, mockLicense.copy(hash = "2"))), + ), + licenses = persistentSetOf( + mockLicense, + ), + ) +} From 1309e29664b0a4c2daf0976c81bc94f765af0bf5 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 12 May 2024 17:16:34 +0900 Subject: [PATCH 11/64] fix: bot warn --- .../hiraganaconverter/feature/info/licence/mock/MockLibs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt index f3a1a723..4917d8ef 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/mock/MockLibs.kt @@ -12,7 +12,7 @@ object MockLibs { name = "SampleLicense", url = "https://example.com", licenseContent = "SampleLicenseContent", - hash = "1" + hash = "1", ) private val mockLibrary = Library( From f512606ee5491d40cdaef51adc163401952f64f0 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 12 May 2024 17:51:24 +0900 Subject: [PATCH 12/64] chore: delete ossLicense in AndroidManifest --- app/src/main/AndroidManifest.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a456f2ff..0ea420ff 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,14 +29,6 @@ - - - - Date: Sun, 12 May 2024 18:23:16 +0900 Subject: [PATCH 13/64] chore: add private [skip ci] --- .../hiraganaconverter/feature/info/licence/LicenseScreen.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 3e5f414f..dc783686 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -70,7 +70,7 @@ fun LicenseScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable -fun LicenseContent( +private fun LicenseContent( libs: Libs?, navigateLicenseDetail: (libraryName: String, licenseContent: String) -> Unit, onBackPressed: () -> Unit, @@ -136,7 +136,7 @@ fun LicenseContent( } @Composable -fun LibraryItem( +private fun LibraryItem( library: Library, navigateLicenseDetail: (libraryName: String, licenseContent: String) -> Unit, ) { From c2ac103749c9ed297ae124a1bfe49285003df775 Mon Sep 17 00:00:00 2001 From: KSND <60963155+kosenda@users.noreply.github.com> Date: Sun, 12 May 2024 18:30:12 +0900 Subject: [PATCH 14/64] Update LicenseScreen.kt for space --- .../hiraganaconverter/feature/info/licence/LicenseScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index dc783686..9eba9fd3 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -111,7 +111,7 @@ private fun LicenseContent( end = innerPadding.calculateEndPadding(LocalLayoutDirection.current), ), ), - verticalArrangement = Arrangement.spacedBy(8.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), state = lazyListState, contentPadding = PaddingValues(horizontal = 16.dp), ) { From 47bf5bea7ce1e63b303f6e630a94f0b76f3bee0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 15:56:37 +0000 Subject: [PATCH 15/64] chore(deps): update dependency com.google.firebase.crashlytics to v3 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 43242dda..d9a62025 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ coroutineTest = "1.8.1" dokka = "1.9.20" gmsPlugin = "4.4.1" firebaseBom = "33.0.0" -firebaseCrashlyticsPlugin = "2.9.9" +firebaseCrashlyticsPlugin = "3.0.1" firebasePerfPlugin = "1.4.2" firebaseAppdistributionPlugin = "5.0.0" hilt = "2.51.1" From c7ad7539955e96a9302c7eb776cf774de69b6965 Mon Sep 17 00:00:00 2001 From: kosenda Date: Wed, 15 May 2024 02:01:33 +0900 Subject: [PATCH 16/64] feature: change paddings in ConverterScreen --- .../core/ui/parts/card/ErrorCard.kt | 6 +-- .../feature/converter/ConverterScreen.kt | 40 ++++++++----------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ErrorCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ErrorCard.kt index 8f375071..c09b3613 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ErrorCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ErrorCard.kt @@ -29,7 +29,7 @@ import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.rememberButtonScaleState import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme -const val ERROR_CARD_ANIMATUIB_DURATION = 500 +const val ERROR_CARD_ANIMATE_DURATION = 500 @Composable fun ErrorCard( @@ -41,8 +41,8 @@ fun ErrorCard( AnimatedVisibility( visible = visible, modifier = Modifier.background(color = MaterialTheme.colorScheme.surface), - enter = expandVertically(expandFrom = Alignment.Top, animationSpec = tween(ERROR_CARD_ANIMATUIB_DURATION)), - exit = shrinkVertically(shrinkTowards = Alignment.Top, animationSpec = tween(ERROR_CARD_ANIMATUIB_DURATION)), + enter = expandVertically(expandFrom = Alignment.Top, animationSpec = tween(ERROR_CARD_ANIMATE_DURATION)), + exit = shrinkVertically(shrinkTowards = Alignment.Top, animationSpec = tween(ERROR_CARD_ANIMATE_DURATION)), ) { Card( modifier = Modifier diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index b1cea8bf..2d486322 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -10,13 +10,11 @@ import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding -import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions @@ -71,7 +69,7 @@ import ksnd.hiraganaconverter.core.ui.parts.button.CustomButtonWithBackground import ksnd.hiraganaconverter.core.ui.parts.button.CustomIconButton import ksnd.hiraganaconverter.core.ui.parts.button.MoveTopButton import ksnd.hiraganaconverter.core.ui.parts.card.ConversionTypeCard -import ksnd.hiraganaconverter.core.ui.parts.card.ERROR_CARD_ANIMATUIB_DURATION +import ksnd.hiraganaconverter.core.ui.parts.card.ERROR_CARD_ANIMATE_DURATION import ksnd.hiraganaconverter.core.ui.parts.card.ErrorCard import ksnd.hiraganaconverter.core.ui.parts.card.OfflineCard import ksnd.hiraganaconverter.core.ui.preview.UiModePreview @@ -98,7 +96,8 @@ fun ConverterScreen( LaunchedEffect(uiState.showErrorCard) { if (uiState.convertErrorType != null && uiState.showErrorCard.not()) { - delay(ERROR_CARD_ANIMATUIB_DURATION.toLong()) + // Prevents text from disappearing during Animation + delay(ERROR_CARD_ANIMATE_DURATION.toLong()) viewModel.clearConvertErrorType() } } @@ -143,24 +142,7 @@ fun ConverterScreenContent( val isConnectNetwork = LocalIsConnectNetwork.current Scaffold( - modifier = modifier - .background(MaterialTheme.colorScheme.surface) - .padding( - start = WindowInsets.displayCutout - .asPaddingValues() - .calculateStartPadding(layoutDirection), - end = WindowInsets.displayCutout - .asPaddingValues() - .calculateEndPadding(layoutDirection), - ) - .padding( - start = WindowInsets.navigationBars - .asPaddingValues() - .calculateStartPadding(layoutDirection), - end = WindowInsets.navigationBars - .asPaddingValues() - .calculateEndPadding(layoutDirection), - ), + modifier = modifier.background(MaterialTheme.colorScheme.surface), topBar = topBar, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, containerColor = MaterialTheme.colorScheme.surface, @@ -174,8 +156,19 @@ fun ConverterScreenContent( ) { Column( modifier = Modifier + .padding( + start = innerPadding.calculateStartPadding(layoutDirection), + end = innerPadding.calculateEndPadding(layoutDirection), + ) + .padding( + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), + ) .padding(horizontal = 8.dp) - .consumeWindowInsets(innerPadding) .fillMaxSize() .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(scrollState) @@ -221,6 +214,7 @@ fun ConverterScreenContent( id = R.string.limit_local_count, LIMIT_CONVERT_COUNT, ) + else -> "" }, onClick = hideErrorCard, From 1b1dd8e48f6249aba992d3bf97737103adde04ab Mon Sep 17 00:00:00 2001 From: kosenda Date: Wed, 15 May 2024 02:06:12 +0900 Subject: [PATCH 17/64] fix: use consumeWindowInsets --- .../hiraganaconverter/feature/converter/ConverterScreen.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index 2d486322..b212282f 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize @@ -156,10 +157,7 @@ fun ConverterScreenContent( ) { Column( modifier = Modifier - .padding( - start = innerPadding.calculateStartPadding(layoutDirection), - end = innerPadding.calculateEndPadding(layoutDirection), - ) + .consumeWindowInsets(innerPadding) .padding( start = WindowInsets.displayCutout .asPaddingValues() From 62bffd479544d1960708b53d6a512d5866935bfa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 18:26:58 +0000 Subject: [PATCH 18/64] fix(deps): update dependency androidx.appcompat:appcompat to v1.7.0-rc01 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 43242dda..505afd2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ accompanist = "0.34.0" activity = "1.9.0" androidGradlePlugin = "8.4.0" -androidxAppCompat = "1.7.0-beta01" +androidxAppCompat = "1.7.0-rc01" androidxCompose = "1.6.7" androidxComposeMaterial3 = "1.2.1" androidxCoreSplashscreen = "1.0.1" From b2bb02baffa5e69c4203e537a7546bde06a4b228 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 00:15:32 +0000 Subject: [PATCH 19/64] fix(deps): update androidxlifecycle to v2.8.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 43242dda..5a870a1f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ androidxComposeMaterial3 = "1.2.1" androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.1.1" androidxHilt = "1.2.0" -androidxLifecycle = "2.7.0" +androidxLifecycle = "2.8.0" androidxNavigation = "2.8.0-alpha08" androidxTestCore = "1.5.0" appUpdate = "2.1.0" From 28fadc9369824efb6446c3eb8d1f23d1159d38de Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 00:15:35 +0000 Subject: [PATCH 20/64] fix(deps): update dependency org.jetbrains.kotlinx:kotlinx-datetime to v0.6.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 43242dda..da53ebe0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ hilt = "2.51.1" junit4 = "4.13.2" kotlin = "1.9.23" kotlinxSerializationJson = "1.6.3" -kotlinxDatetime = "0.5.0" +kotlinxDatetime = "0.6.0" ksp = "1.9.23-1.0.20" ktlint = "1.2.1" lazyColumnScrollbar = "1.9.0" From 23554ea38627df019f63b04d7b7a09878d830d34 Mon Sep 17 00:00:00 2001 From: kosenda Date: Thu, 16 May 2024 01:41:45 +0900 Subject: [PATCH 21/64] fix: topBarHeight and padding --- .../view/navigation/Navigation.kt | 18 +--------- .../view/screen/ConverterScreenTest.kt | 6 ++-- .../core/ui/parts}/TopBar.kt | 36 ++++++++++++------- .../core/ui/parts/button/MoveTopButton.kt | 15 ++++++++ .../feature/converter/ConverterScreen.kt | 26 +++++++++----- 5 files changed, 59 insertions(+), 42 deletions(-) rename {app/src/main/java/ksnd/hiraganaconverter/view => core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts}/TopBar.kt (74%) diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt index 571f83f8..ea270898 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt +++ b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt @@ -15,12 +15,7 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.onSizeChanged import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner @@ -37,7 +32,6 @@ import ksnd.hiraganaconverter.feature.info.InfoScreen import ksnd.hiraganaconverter.feature.info.licence.LicenseScreen import ksnd.hiraganaconverter.feature.info.licence.licensedetail.LicenseDetailScreen import ksnd.hiraganaconverter.feature.setting.SettingScreen -import ksnd.hiraganaconverter.view.TopBar @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -48,7 +42,6 @@ fun Navigation( ) { val navController = rememberNavController() val lifecycleOwner = LocalLifecycleOwner.current - var topBarHeight by remember { mutableIntStateOf(0) } val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) // Ignore click events when you've started navigating to another screen @@ -78,16 +71,7 @@ fun Navigation( viewModel = hiltViewModel(), snackbarHostState = snackbarHostState, scrollBehavior = scrollBehavior, - topBarHeight = topBarHeight, - topBar = { - TopBar( - modifier = Modifier.onSizeChanged { topBarHeight = it.height }, - scrollBehavior = scrollBehavior, - transitionHistory = { navigateScreen(Nav.History) }, - transitionSetting = { navigateScreen(Nav.Setting) }, - transitionInfo = { navigateScreen(Nav.Info) }, - ) - }, + navigateScreen = ::navigateScreen, ) } slideHorizontallyComposable { diff --git a/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt b/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt index a5a446bf..a218dcaa 100644 --- a/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt +++ b/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt @@ -16,7 +16,7 @@ import com.github.takahirom.roborazzi.captureRoboImage import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme import ksnd.hiraganaconverter.feature.converter.ConvertUiState import ksnd.hiraganaconverter.feature.converter.ConverterScreenContent -import ksnd.hiraganaconverter.view.TopBar +import ksnd.hiraganaconverter.core.ui.parts.TopBar import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -40,7 +40,7 @@ class ConverterScreenTest { TopBar( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, scrollBehavior = scrollBehavior, - transitionHistory = {}, + navigateHistory = {}, transitionSetting = {}, transitionInfo = {}, ) @@ -71,7 +71,7 @@ class ConverterScreenTest { TopBar( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, scrollBehavior = scrollBehavior, - transitionHistory = {}, + navigateHistory = {}, transitionSetting = {}, transitionInfo = {}, ) diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/TopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt similarity index 74% rename from app/src/main/java/ksnd/hiraganaconverter/view/TopBar.kt rename to core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt index 95798f0b..54cfff2c 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/TopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt @@ -1,10 +1,15 @@ -package ksnd.hiraganaconverter.view +package ksnd.hiraganaconverter.core.ui.parts import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme @@ -18,30 +23,37 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.isTest -import ksnd.hiraganaconverter.core.ui.parts.GooCreditImage +import ksnd.hiraganaconverter.core.ui.navigation.Nav import ksnd.hiraganaconverter.core.ui.parts.button.CustomIconButton import ksnd.hiraganaconverter.core.ui.preview.UiModePreview @OptIn(ExperimentalMaterial3Api::class) @Composable fun TopBar( - modifier: Modifier = Modifier, scrollBehavior: TopAppBarScrollBehavior, - transitionHistory: () -> Unit, - transitionSetting: () -> Unit, - transitionInfo: () -> Unit, + modifier: Modifier = Modifier, + navigateScreen: (Nav) -> Unit, ) { + val layoutDirection = LocalLayoutDirection.current val isShowTopBar by remember(scrollBehavior.state.collapsedFraction) { derivedStateOf { scrollBehavior.state.collapsedFraction != 1.toFloat() } } AnimatedVisibility( visible = isShowTopBar, - modifier = modifier, + modifier = modifier.padding( + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), + ), enter = fadeIn(), exit = fadeOut(), ) { @@ -58,18 +70,18 @@ fun TopBar( modifier = Modifier.padding(horizontal = 8.dp), contentDescription = "info", painter = painterResource(id = R.drawable.ic_outline_info_24), - onClick = transitionInfo, + onClick = { navigateScreen(Nav.Info) }, ) CustomIconButton( modifier = Modifier.padding(end = 8.dp), contentDescription = "settings", painter = painterResource(id = R.drawable.ic_outline_settings_24), - onClick = transitionSetting, + onClick = { navigateScreen(Nav.Setting) }, ) CustomIconButton( contentDescription = "history", painter = painterResource(id = R.drawable.ic_baseline_history_24), - onClick = transitionHistory, + onClick = { navigateScreen(Nav.History) }, ) Spacer(modifier = Modifier.weight(1f)) if (isTest().not()) { @@ -87,8 +99,6 @@ fun TopBar( fun PreviewTopBar() { TopBar( scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()), - transitionHistory = {}, - transitionSetting = {}, - transitionInfo = {}, + navigateScreen = {}, ) } diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt index 4acd31fd..c51c0ffb 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt @@ -8,6 +8,11 @@ import androidx.compose.animation.slideOut import androidx.compose.foundation.Image import androidx.compose.foundation.ScrollState import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState @@ -21,6 +26,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.IntOffset @@ -33,6 +39,7 @@ import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @Composable fun MoveTopButton(scrollState: ScrollState) { val coroutineScope = rememberCoroutineScope() + val layoutDirection = LocalLayoutDirection.current val offset = IntOffset(x = 100, y = 100) val showVisibleTopBar by remember { derivedStateOf { scrollState.value > 0 } @@ -40,6 +47,14 @@ fun MoveTopButton(scrollState: ScrollState) { AnimatedVisibility( visible = showVisibleTopBar, + modifier = Modifier.padding( + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), + ), enter = scaleIn() + slideIn(initialOffset = { offset }), exit = scaleOut() + slideOut(targetOffset = { offset }), ) { diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index b212282f..7878264c 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -36,13 +36,16 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.ClipboardManager import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalContext @@ -65,6 +68,8 @@ import ksnd.hiraganaconverter.core.model.ui.HiraKanaType import ksnd.hiraganaconverter.core.resource.LIMIT_CONVERT_COUNT import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.LocalIsConnectNetwork +import ksnd.hiraganaconverter.core.ui.navigation.Nav +import ksnd.hiraganaconverter.core.ui.parts.TopBar import ksnd.hiraganaconverter.core.ui.parts.button.ConvertButton import ksnd.hiraganaconverter.core.ui.parts.button.CustomButtonWithBackground import ksnd.hiraganaconverter.core.ui.parts.button.CustomIconButton @@ -84,9 +89,8 @@ fun ConverterScreen( viewModel: ConvertViewModel, snackbarHostState: SnackbarHostState, scrollBehavior: TopAppBarScrollBehavior, - topBarHeight: Int, modifier: Modifier = Modifier, - topBar: @Composable () -> Unit, + navigateScreen: (Nav) -> Unit, ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle(ConvertUiState()) val analytics = LocalAnalytics.current @@ -107,8 +111,6 @@ fun ConverterScreen( modifier = modifier, uiState = uiState, snackbarHostState = snackbarHostState, - topBar = topBar, - topBarHeight = topBarHeight, scrollBehavior = scrollBehavior, changeHiraKanaType = viewModel::changeHiraKanaType, clearAllText = viewModel::clearAllText, @@ -116,6 +118,7 @@ fun ConverterScreen( updateInputText = viewModel::updateInputText, updateOutputText = viewModel::updateOutputText, hideErrorCard = viewModel::hideErrorCard, + navigateScreen = navigateScreen, ) } @@ -125,8 +128,6 @@ fun ConverterScreenContent( modifier: Modifier = Modifier, uiState: ConvertUiState, snackbarHostState: SnackbarHostState, - topBar: @Composable () -> Unit, - topBarHeight: Int, scrollBehavior: TopAppBarScrollBehavior, changeHiraKanaType: (HiraKanaType) -> Unit, clearAllText: () -> Unit, @@ -134,6 +135,7 @@ fun ConverterScreenContent( updateInputText: (String) -> Unit, updateOutputText: (String) -> Unit, hideErrorCard: () -> Unit, + navigateScreen: (Nav) -> Unit, ) { val focusManager = LocalFocusManager.current val clipboardManager: ClipboardManager = LocalClipboardManager.current @@ -141,10 +143,17 @@ fun ConverterScreenContent( val layoutDirection = LocalLayoutDirection.current val scrollState = rememberScrollState() val isConnectNetwork = LocalIsConnectNetwork.current + var topBarHeight by remember { mutableIntStateOf(0) } Scaffold( modifier = modifier.background(MaterialTheme.colorScheme.surface), - topBar = topBar, + topBar = { + TopBar( + modifier = Modifier.onSizeChanged { topBarHeight = it.height }, + scrollBehavior = scrollBehavior, + navigateScreen = navigateScreen, + ) + }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, containerColor = MaterialTheme.colorScheme.surface, floatingActionButton = { MoveTopButton(scrollState = scrollState) }, @@ -353,8 +362,6 @@ fun PreviewConverterScreenContent( ConverterScreenContent( uiState = uiState, snackbarHostState = remember { SnackbarHostState() }, - topBar = { }, - topBarHeight = 0, scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()), changeHiraKanaType = {}, clearAllText = {}, @@ -362,6 +369,7 @@ fun PreviewConverterScreenContent( updateInputText = {}, updateOutputText = {}, hideErrorCard = {}, + navigateScreen = {}, ) } } From 96c5eda445978ccd344f45edd15e793e555e5a63 Mon Sep 17 00:00:00 2001 From: kosenda Date: Thu, 16 May 2024 01:45:12 +0900 Subject: [PATCH 22/64] refactor: remove strange modifier pass --- .../hiraganaconverter/feature/converter/ConverterScreen.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index 7878264c..5c6acc11 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -89,7 +89,6 @@ fun ConverterScreen( viewModel: ConvertViewModel, snackbarHostState: SnackbarHostState, scrollBehavior: TopAppBarScrollBehavior, - modifier: Modifier = Modifier, navigateScreen: (Nav) -> Unit, ) { val uiState by viewModel.uiState.collectAsStateWithLifecycle(ConvertUiState()) @@ -108,7 +107,6 @@ fun ConverterScreen( } ConverterScreenContent( - modifier = modifier, uiState = uiState, snackbarHostState = snackbarHostState, scrollBehavior = scrollBehavior, @@ -125,7 +123,6 @@ fun ConverterScreen( @OptIn(ExperimentalMaterial3Api::class) @Composable fun ConverterScreenContent( - modifier: Modifier = Modifier, uiState: ConvertUiState, snackbarHostState: SnackbarHostState, scrollBehavior: TopAppBarScrollBehavior, @@ -146,7 +143,7 @@ fun ConverterScreenContent( var topBarHeight by remember { mutableIntStateOf(0) } Scaffold( - modifier = modifier.background(MaterialTheme.colorScheme.surface), + modifier = Modifier.background(MaterialTheme.colorScheme.surface), topBar = { TopBar( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, From 5e0fe5f395d8fe65df61d81e6015273f0f8d7dbd Mon Sep 17 00:00:00 2001 From: kosenda Date: Thu, 16 May 2024 01:53:31 +0900 Subject: [PATCH 23/64] fix: ConverterScreenTest --- .../view/screen/ConverterScreenTest.kt | 37 ++----------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt b/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt index a218dcaa..a2bdf03b 100644 --- a/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt +++ b/app/src/test/java/ksnd/hiraganaconverter/view/screen/ConverterScreenTest.kt @@ -4,19 +4,12 @@ import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.layout.onSizeChanged import androidx.test.ext.junit.runners.AndroidJUnit4 import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers import com.github.takahirom.roborazzi.captureRoboImage import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme import ksnd.hiraganaconverter.feature.converter.ConvertUiState import ksnd.hiraganaconverter.feature.converter.ConverterScreenContent -import ksnd.hiraganaconverter.core.ui.parts.TopBar import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config @@ -30,29 +23,18 @@ class ConverterScreenTest { @Test fun converterScreen_light() { captureRoboImage { - var topBarHeight by remember { mutableIntStateOf(0) } - val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) HiraganaConverterTheme(isDarkTheme = false) { ConverterScreenContent( uiState = ConvertUiState(), snackbarHostState = SnackbarHostState(), - topBar = { - TopBar( - modifier = Modifier.onSizeChanged { topBarHeight = it.height }, - scrollBehavior = scrollBehavior, - navigateHistory = {}, - transitionSetting = {}, - transitionInfo = {}, - ) - }, - topBarHeight = topBarHeight, - scrollBehavior = scrollBehavior, + scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()), changeHiraKanaType = {}, clearAllText = {}, convert = {}, updateInputText = {}, updateOutputText = {}, hideErrorCard = {}, + navigateScreen = {}, ) } } @@ -61,29 +43,18 @@ class ConverterScreenTest { @Test fun converterScreen_dark() { captureRoboImage { - var topBarHeight by remember { mutableIntStateOf(0) } - val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) HiraganaConverterTheme(isDarkTheme = true) { ConverterScreenContent( uiState = ConvertUiState(), snackbarHostState = SnackbarHostState(), - topBar = { - TopBar( - modifier = Modifier.onSizeChanged { topBarHeight = it.height }, - scrollBehavior = scrollBehavior, - navigateHistory = {}, - transitionSetting = {}, - transitionInfo = {}, - ) - }, - topBarHeight = topBarHeight, - scrollBehavior = scrollBehavior, + scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()), changeHiraKanaType = {}, clearAllText = {}, convert = {}, updateInputText = {}, updateOutputText = {}, hideErrorCard = {}, + navigateScreen = {}, ) } } From e4b7ac5fffa30e35d259b580c0427d7fd3b9e230 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 13:50:39 +0000 Subject: [PATCH 24/64] chore(deps): update roborazzi --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 43242dda..813d083a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.10" -roborazzi = "1.15.0" +roborazzi = "1.16.0" showkase = "1.0.2" aboutLibraries = "11.1.4" From 35eabea4ca79d935a3f7007060f58ecc28adf7e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 15:50:28 +0000 Subject: [PATCH 25/64] fix(deps): update dependency io.mockk:mockk to v1.13.11 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 813d083a..d83b7cb5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,7 +40,7 @@ secrets = "2.0.1" timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" -mockk = "1.13.10" +mockk = "1.13.11" roborazzi = "1.16.0" showkase = "1.0.2" aboutLibraries = "11.1.4" From d0b9749f8af29209830a172746718f25a40afbd0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:14:46 +0000 Subject: [PATCH 26/64] chore(deps): update roborazzi to v1.16.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d83b7cb5..28dcc546 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.11" -roborazzi = "1.16.0" +roborazzi = "1.16.1" showkase = "1.0.2" aboutLibraries = "11.1.4" From db01b8e0d4faf7553fd55ac1ed7042bb2ba557f4 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 18 May 2024 01:18:13 +0900 Subject: [PATCH 27/64] feature: use coVerifyCount --- .../feature/setting/SettingsViewModelTest.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/feature/setting/src/test/java/ksnd/hiraganaconverter/feature/setting/SettingsViewModelTest.kt b/feature/setting/src/test/java/ksnd/hiraganaconverter/feature/setting/SettingsViewModelTest.kt index 41cf0ccd..6962858b 100644 --- a/feature/setting/src/test/java/ksnd/hiraganaconverter/feature/setting/SettingsViewModelTest.kt +++ b/feature/setting/src/test/java/ksnd/hiraganaconverter/feature/setting/SettingsViewModelTest.kt @@ -1,6 +1,7 @@ package ksnd.hiraganaconverter.feature.setting import io.mockk.coVerify +import io.mockk.coVerifyCount import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.flow.flowOf @@ -34,9 +35,11 @@ class SettingsViewModelTest { @Test fun uiState_initial_callRepositoryMethods() = runTest { - coVerify(exactly = 1) { dataStoreRepository.theme() } - coVerify(exactly = 1) { dataStoreRepository.fontType() } - coVerify(exactly = 1) { dataStoreRepository.enableInAppUpdate() } + coVerifyCount { + 1 * { dataStoreRepository.theme() } + 1 * { dataStoreRepository.fontType() } + 1 * { dataStoreRepository.enableInAppUpdate() } + } } @Test @@ -50,7 +53,7 @@ class SettingsViewModelTest { fun updateFontType_newFontType_isCalledUpdateFontType() = runTest { viewModel.updateFontType(NEW_FONT_TYPE) - coVerify(exactly = 1) { dataStoreRepository.updateFontType(fontType = NEW_FONT_TYPE) } + coVerify { dataStoreRepository.updateFontType(fontType = NEW_FONT_TYPE) } } @Test From 06d5ca9c93665c91d9e672dbc96a44081ccebd12 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 18 May 2024 17:30:48 +0900 Subject: [PATCH 28/64] feature: use dropUnlessResumed --- .../view/navigation/Navigation.kt | 25 ++++++------------- .../hiraganaconverter/core/ui/parts/TopBar.kt | 7 +++--- .../feature/info/licence/LicenseScreen.kt | 3 ++- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt index ea270898..e0867332 100644 --- a/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt +++ b/app/src/main/java/ksnd/hiraganaconverter/view/navigation/Navigation.kt @@ -17,8 +17,7 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.compose.dropUnlessResumed import androidx.navigation.NavBackStackEntry import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.NavHost @@ -41,18 +40,8 @@ fun Navigation( receivedText: CharSequence?, ) { val navController = rememberNavController() - val lifecycleOwner = LocalLifecycleOwner.current val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) - // Ignore click events when you've started navigating to another screen - // https://stackoverflow.com/a/76386604/4339442 - fun navigateUp() { - val currentState = lifecycleOwner.lifecycle.currentState - if (currentState.isAtLeast(Lifecycle.State.RESUMED)) { - navController.navigateUp() - } - } - fun navigateScreen(nav: Nav) { navController.navigate(nav) { launchSingleTop = true } } @@ -77,34 +66,34 @@ fun Navigation( slideHorizontallyComposable { ConvertHistoryScreen( viewModel = hiltViewModel(), - onBackPressed = ::navigateUp, + onBackPressed = dropUnlessResumed(block = navController::navigateUp), ) } slideHorizontallyComposable { SettingScreen( viewModel = hiltViewModel(), - onBackPressed = ::navigateUp, + onBackPressed = dropUnlessResumed(block = navController::navigateUp), ) } slideHorizontallyComposable { InfoScreen( viewModel = hiltViewModel(), - onBackPressed = ::navigateUp, - onClickLicense = { navigateScreen(Nav.License) }, + onBackPressed = dropUnlessResumed(block = navController::navigateUp), + onClickLicense = dropUnlessResumed { navigateScreen(Nav.License) }, ) } slideHorizontallyComposable { LicenseScreen( viewModel = hiltViewModel(), navigateLicenseDetail = ::navigateLicenseDetail, - onBackPressed = ::navigateUp, + onBackPressed = dropUnlessResumed(block = navController::navigateUp), ) } slideHorizontallyComposable { LicenseDetailScreen( libraryName = it.toRoute().libraryName, licenseContent = it.toRoute().licenseContent, - onBackPressed = ::navigateUp, + onBackPressed = dropUnlessResumed(block = navController::navigateUp), ) } } diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt index 54cfff2c..766354a9 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.dropUnlessResumed import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.isTest import ksnd.hiraganaconverter.core.ui.navigation.Nav @@ -70,18 +71,18 @@ fun TopBar( modifier = Modifier.padding(horizontal = 8.dp), contentDescription = "info", painter = painterResource(id = R.drawable.ic_outline_info_24), - onClick = { navigateScreen(Nav.Info) }, + onClick = dropUnlessResumed { navigateScreen(Nav.Info) }, ) CustomIconButton( modifier = Modifier.padding(end = 8.dp), contentDescription = "settings", painter = painterResource(id = R.drawable.ic_outline_settings_24), - onClick = { navigateScreen(Nav.Setting) }, + onClick = dropUnlessResumed { navigateScreen(Nav.Setting) }, ) CustomIconButton( contentDescription = "history", painter = painterResource(id = R.drawable.ic_baseline_history_24), - onClick = { navigateScreen(Nav.History) }, + onClick = dropUnlessResumed { navigateScreen(Nav.History) }, ) Spacer(modifier = Modifier.weight(1f)) if (isTest().not()) { diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 9eba9fd3..29334d47 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.compose.dropUnlessResumed import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.entity.Library import com.mikepenz.aboutlibraries.ui.compose.m3.util.author @@ -149,7 +150,7 @@ private fun LibraryItem( .scale(scale = buttonScaleState.animationScale.value) .noRippleClickable( interactionSource = buttonScaleState.interactionSource, - onClick = { + onClick = dropUnlessResumed { if (isNotExistLicenseContent) { library.licenses.first().url?.let { urlHandler.openUri(it) From 4b0a764875a0f9a8d0caf871ed1ca3194a5ea4f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 08:38:39 +0000 Subject: [PATCH 29/64] fix(deps): update dependency org.robolectric:robolectric to v4.12.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f1c162e9..f812da90 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,7 +34,7 @@ okhttp3 = "4.12.0" playReview = "2.0.1" retrofit = "2.11.0" retrofitSerialization = "1.0.0" -robolectric = "4.12.1" +robolectric = "4.12.2" room = "2.6.1" secrets = "2.0.1" timber = "5.0.1" From da6b4988f36191d84131bdcad695e9976e724dcb Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 18 May 2024 17:44:07 +0900 Subject: [PATCH 30/64] feature: update composeCompiler and ksp --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 28ecb3c9..097fbe9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,7 @@ junit4 = "4.13.2" kotlin = "1.9.24" kotlinxSerializationJson = "1.6.3" kotlinxDatetime = "0.5.0" -ksp = "1.9.23-1.0.20" +ksp = "1.9.24-1.0.20" ktlint = "1.2.1" lazyColumnScrollbar = "1.9.0" lottie = "6.4.0" @@ -47,7 +47,7 @@ roborazzi = "1.14.0" showkase = "1.0.2" # ** I'm using it, so no deletions allowed. ** -androidxComposeCompiler = "1.5.11" +androidxComposeCompiler = "1.5.14" jacoco = "0.8.10" [libraries] From 7cb373dccbab832c5e94c24710e3a194c5db1fbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 18 May 2024 09:03:15 +0000 Subject: [PATCH 31/64] fix(deps): update dependency androidx.navigation:navigation-compose to v2.8.0-beta01 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index deda8212..6687ec10 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.1.1" androidxHilt = "1.2.0" androidxLifecycle = "2.8.0" -androidxNavigation = "2.8.0-alpha08" +androidxNavigation = "2.8.0-beta01" androidxTestCore = "1.5.0" appUpdate = "2.1.0" coil = "2.6.0" From 4045920ac0ce8b14bb2fc55eb20f01028db02eee Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 18 May 2024 18:36:28 +0900 Subject: [PATCH 32/64] feature: add RobolectricTestRunner --- .../feature/converter/ConvertViewModelTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/feature/converter/src/test/java/ksnd/hiraganaconverter/feature/converter/ConvertViewModelTest.kt b/feature/converter/src/test/java/ksnd/hiraganaconverter/feature/converter/ConvertViewModelTest.kt index 48777134..08bea2d1 100644 --- a/feature/converter/src/test/java/ksnd/hiraganaconverter/feature/converter/ConvertViewModelTest.kt +++ b/feature/converter/src/test/java/ksnd/hiraganaconverter/feature/converter/ConvertViewModelTest.kt @@ -14,7 +14,10 @@ import ksnd.hiraganaconverter.core.testing.MainDispatcherRule import ksnd.hiraganaconverter.core.ui.navigation.Nav import org.junit.Rule import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +@RunWith(RobolectricTestRunner::class) class ConvertViewModelTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() From 5afd0cdc2e67d92139e752e20706829b5aeebd7e Mon Sep 17 00:00:00 2001 From: kosenda Date: Tue, 21 May 2024 01:37:14 +0900 Subject: [PATCH 33/64] feature: change design --- .../core/ui/parts/BackTopBar.kt | 83 +++++++++++++------ .../core/ui/parts/card/CovertHistoryCard.kt | 1 - .../feature/history/ConvertHistoryScreen.kt | 59 +++++++------ .../feature/info/InfoScreen.kt | 43 ++++++---- .../feature/setting/SettingScreen.kt | 47 +++++++---- 5 files changed, 149 insertions(+), 84 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt index 98809b8e..13b0872d 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt @@ -1,8 +1,17 @@ package ksnd.hiraganaconverter.core.ui.parts +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -13,11 +22,15 @@ import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +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.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.resource.R @@ -32,33 +45,51 @@ fun BackTopBar( onBackPressed: () -> Unit, title: @Composable () -> Unit = {}, ) { - TopAppBar( - title = title, - modifier = modifier, - scrollBehavior = scrollBehavior, - navigationIcon = { - Box( - modifier = Modifier - .displayCutoutPadding() - .padding(start = 16.dp) - .clip(shape = CircleShape) - .size(48.dp) - .clickable(onClick = onBackPressed), - contentAlignment = Alignment.Center, - ) { - Image( - modifier = Modifier.size(28.dp), - painter = painterResource(id = R.drawable.baseline_arrow_back_24), - contentDescription = "back screen", - colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.primary), - ) - } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = Color.Transparent, - scrolledContainerColor = Color.Transparent, + val layoutDirection = LocalLayoutDirection.current + val isShowTopBar by remember(scrollBehavior.state.collapsedFraction) { + derivedStateOf { scrollBehavior.state.collapsedFraction != 1.toFloat() } + } + + AnimatedVisibility( + visible = isShowTopBar, + modifier = modifier.padding( + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), ), - ) + enter = fadeIn(), + exit = fadeOut(), + ) { + TopAppBar( + title = title, + modifier = modifier.background(MaterialTheme.colorScheme.surface), + scrollBehavior = scrollBehavior, + navigationIcon = { + Box( + modifier = Modifier + .padding(start = 16.dp) + .clip(shape = CircleShape) + .size(48.dp) + .clickable(onClick = onBackPressed), + contentAlignment = Alignment.Center, + ) { + Image( + modifier = Modifier.size(28.dp), + painter = painterResource(id = R.drawable.baseline_arrow_back_24), + contentDescription = "back screen", + colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.primary), + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = Color.Transparent, + scrolledContainerColor = Color.Transparent, + ), + ) + } } @OptIn(ExperimentalMaterial3Api::class) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/CovertHistoryCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/CovertHistoryCard.kt index b9a8fdd6..ec92fb87 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/CovertHistoryCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/CovertHistoryCard.kt @@ -39,7 +39,6 @@ fun ConvertHistoryCard( val buttonScaleState = rememberButtonScaleState() Card( modifier = modifier - .padding(top = 8.dp) .wrapContentHeight() .fillMaxWidth() .scale(scale = buttonScaleState.animationScale.value) diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt index 6d653c7e..a504f339 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt @@ -1,16 +1,18 @@ package ksnd.hiraganaconverter.feature.history -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding -import androidx.compose.foundation.layout.displayCutoutPadding +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -29,11 +31,16 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign @@ -81,7 +88,7 @@ fun ConvertHistoryScreen( } } -@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ConvertHistoryScreenContent( state: ConvertHistoryUiState, @@ -94,20 +101,23 @@ private fun ConvertHistoryScreenContent( val layoutDirection = LocalLayoutDirection.current val lazyListState = rememberLazyListState() val coroutineScope = rememberCoroutineScope() + var topBarHeight by remember { mutableIntStateOf(0) } + val density = LocalDensity.current.density Scaffold( modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection) - .background(MaterialTheme.colorScheme.surface) - .displayCutoutPadding(), + .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( scrollBehavior = scrollBehavior, - modifier = Modifier.noRippleClickable { - coroutineScope.launch { - lazyListState.animateScrollToItem(0) + modifier = Modifier + .noRippleClickable { + coroutineScope.launch { + lazyListState.animateScrollToItem(0) + } } - }, + .onSizeChanged { topBarHeight = it.height }, onBackPressed = onBackPressed, ) { if (state.convertHistories.isNotEmpty()) { @@ -121,35 +131,36 @@ private fun ConvertHistoryScreenContent( } } }, - ) { padding -> + ) { innerPadding -> Column( modifier = Modifier + .fillMaxSize() + .consumeWindowInsets(innerPadding) .padding( - paddingValues = PaddingValues( - start = padding.calculateStartPadding(layoutDirection), - top = padding.calculateTopPadding(), - end = padding.calculateEndPadding(layoutDirection), - ), - ) - .fillMaxSize(), + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), + ), ) { if (state.convertHistories.isEmpty()) { EmptyHistoryImage() } else { LazyColumn( state = lazyListState, + verticalArrangement = Arrangement.spacedBy(12.dp), ) { + item { + Spacer(modifier = Modifier.height((topBarHeight / density).toInt().dp)) + } items( items = state.convertHistories, key = { history -> history.id }, ) { history -> ConvertHistoryCard( - modifier = Modifier - .padding(horizontal = 16.dp) - .then( - // adding the condition because it behaves strangely when set while scrolling - if (lazyListState.isScrollInProgress) Modifier else Modifier.animateItemPlacement(), - ), + modifier = Modifier.padding(horizontal = 16.dp), beforeText = history.before, time = history.time, onClick = { showConvertHistoryDetailDialog(history) }, diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt index 63a0ebff..1ac6600e 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt @@ -6,12 +6,14 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding -import androidx.compose.foundation.layout.displayCutoutPadding +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -32,6 +34,7 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -42,7 +45,9 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.painterResource @@ -101,37 +106,43 @@ private fun InfoScreenContent( val scrollState = rememberScrollState() var isShowMovesToAppSiteDialog by remember { mutableStateOf(false) } var isShowMovesToApiSiteDialog by remember { mutableStateOf(false) } + var topBarHeight by remember { mutableIntStateOf(0) } + val density = LocalDensity.current.density Scaffold( modifier = Modifier .nestedScroll(scrollBehavior.nestedScrollConnection) - .background(MaterialTheme.colorScheme.surface) - .displayCutoutPadding(), + .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( scrollBehavior = scrollBehavior, - modifier = Modifier.noRippleClickable { - coroutineScope.launch { - scrollState.animateScrollTo(0) + modifier = Modifier + .noRippleClickable { + coroutineScope.launch { + scrollState.animateScrollTo(0) + } } - }, + .onSizeChanged { topBarHeight = it.height }, onBackPressed = onBackPressed, ) }, ) { innerPadding -> Column( modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState) + .consumeWindowInsets(innerPadding) .padding( - paddingValues = PaddingValues( - start = innerPadding.calculateStartPadding(layoutDirection), - top = innerPadding.calculateTopPadding(), - end = innerPadding.calculateEndPadding(layoutDirection), - ), + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), ) - .verticalScroll(scrollState) - .padding(horizontal = 16.dp) - .fillMaxSize(), + .padding(horizontal = 16.dp), ) { + Spacer(modifier = Modifier.height((topBarHeight / density).toInt().dp)) AppInfoContent(versionName = versionName, onURLClick = { isShowMovesToAppSiteDialog = true }) DeveloperInfoContent() APIInfoContent(onURLClick = { isShowMovesToApiSiteDialog = true }) diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt index ceb961a4..6d13b717 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt @@ -2,11 +2,13 @@ package ksnd.hiraganaconverter.feature.setting import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding -import androidx.compose.foundation.layout.displayCutoutPadding +import androidx.compose.foundation.layout.consumeWindowInsets +import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -23,12 +25,17 @@ import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -83,6 +90,8 @@ private fun SettingScreenContent( val isShowSelectLanguageDialog = rememberSaveable { mutableStateOf(false) } val coroutineScope = rememberCoroutineScope() val scrollState = rememberScrollState() + var topBarHeight by remember { mutableIntStateOf(0) } + val density = LocalDensity.current.density if (isShowSelectLanguageDialog.value) { SelectLanguageDialog( @@ -91,35 +100,39 @@ private fun SettingScreenContent( } Scaffold( - modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection) - .background(MaterialTheme.colorScheme.surface) - .displayCutoutPadding(), + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection) + .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( scrollBehavior = scrollBehavior, - modifier = Modifier.noRippleClickable { - coroutineScope.launch { - scrollState.animateScrollTo(0) + modifier = Modifier + .noRippleClickable { + coroutineScope.launch { + scrollState.animateScrollTo(0) + } } - }, + .onSizeChanged { topBarHeight = it.height }, onBackPressed = onBackPressed, ) }, ) { innerPadding -> Column( modifier = Modifier - .displayCutoutPadding() - .padding( - paddingValues = PaddingValues( - start = innerPadding.calculateStartPadding(layoutDirection), - top = innerPadding.calculateTopPadding(), - end = innerPadding.calculateEndPadding(layoutDirection), - ), - ) .fillMaxSize() .verticalScroll(scrollState) + .consumeWindowInsets(innerPadding) + .padding( + start = WindowInsets.displayCutout + .asPaddingValues() + .calculateStartPadding(layoutDirection), + end = WindowInsets.displayCutout + .asPaddingValues() + .calculateEndPadding(layoutDirection), + ) .padding(horizontal = 16.dp), ) { + Spacer(modifier = Modifier.height((topBarHeight / density).toInt().dp)) SettingThemeContent( onRadioButtonClick = updateTheme, selectedTheme = uiState.theme, From 4822c9ac8cb034547c5cf3ed42409bb158cee104 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 01:31:36 +0000 Subject: [PATCH 34/64] chore(deps): update androidgradleplugin to v8.4.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6687ec10..348ff10d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] accompanist = "0.34.0" activity = "1.9.0" -androidGradlePlugin = "8.4.0" +androidGradlePlugin = "8.4.1" androidxAppCompat = "1.7.0-rc01" androidxCompose = "1.6.7" androidxComposeMaterial3 = "1.2.1" From 89d9a4da142f5e20292012d348170f72a06cdba0 Mon Sep 17 00:00:00 2001 From: kosenda Date: Wed, 22 May 2024 01:11:33 +0900 Subject: [PATCH 35/64] feature: add bottom navigation padding --- .../feature/converter/ConverterScreen.kt | 4 +++- .../feature/history/ConvertHistoryScreen.kt | 4 +++- .../hiraganaconverter/feature/info/InfoScreen.kt | 4 +++- .../feature/info/licence/LicenseScreen.kt | 13 +++++-------- .../licence/licensedetail/LicenseDetailScreen.kt | 11 +++++------ .../feature/setting/SettingScreen.kt | 4 +++- 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index 5c6acc11..23f70272 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions @@ -141,6 +142,7 @@ fun ConverterScreenContent( val scrollState = rememberScrollState() val isConnectNetwork = LocalIsConnectNetwork.current var topBarHeight by remember { mutableIntStateOf(0) } + val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() Scaffold( modifier = Modifier.background(MaterialTheme.colorScheme.surface), @@ -246,7 +248,7 @@ fun ConverterScreenContent( onValueChange = updateOutputText, ) - Spacer(modifier = Modifier.height(120.dp)) + Spacer(modifier = Modifier.height(120.dp + navigationHeight)) } } } diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt index a504f339..eb8369ff 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -103,6 +104,7 @@ private fun ConvertHistoryScreenContent( val coroutineScope = rememberCoroutineScope() var topBarHeight by remember { mutableIntStateOf(0) } val density = LocalDensity.current.density + val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() Scaffold( modifier = Modifier @@ -167,7 +169,7 @@ private fun ConvertHistoryScreenContent( onDeleteClick = { deleteConvertHistory(history) }, ) } - item { Spacer(modifier = Modifier.height(48.dp)) } + item { Spacer(modifier = Modifier.height(48.dp + navigationHeight)) } } } } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt index 1ac6600e..4f1bc762 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState @@ -108,6 +109,7 @@ private fun InfoScreenContent( var isShowMovesToApiSiteDialog by remember { mutableStateOf(false) } var topBarHeight by remember { mutableIntStateOf(0) } val density = LocalDensity.current.density + val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() Scaffold( modifier = Modifier @@ -148,7 +150,7 @@ private fun InfoScreenContent( APIInfoContent(onURLClick = { isShowMovesToApiSiteDialog = true }) LicensesContent(onClickLicense = onClickLicense) PrivacyPolicyContent() - Spacer(modifier = Modifier.height(48.dp)) + Spacer(modifier = Modifier.height(48.dp + navigationHeight)) } } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 29334d47..556ae8cc 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -7,11 +7,13 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -79,6 +81,7 @@ private fun LicenseContent( val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) val coroutineScope = rememberCoroutineScope() val lazyListState = rememberLazyListState() + val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() Scaffold( modifier = Modifier @@ -125,13 +128,7 @@ private fun LicenseContent( navigateLicenseDetail = navigateLicenseDetail, ) } - item { - Spacer( - modifier = Modifier - .navigationBarsPadding() - .height(48.dp), - ) - } + item { Spacer(modifier = Modifier.height(48.dp + navigationHeight)) } } } } diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt index dc655000..9aa63d8e 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt @@ -4,11 +4,13 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -44,6 +46,7 @@ fun LicenseDetailScreen( val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(rememberTopAppBarState()) val coroutineScope = rememberCoroutineScope() val scrollState = rememberScrollState() + val navigationBarHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() Scaffold( modifier = Modifier @@ -96,11 +99,7 @@ fun LicenseDetailScreen( color = MaterialTheme.colorScheme.secondary, ) - Spacer( - modifier = Modifier - .navigationBarsPadding() - .height(48.dp), - ) + Spacer(modifier = Modifier.height(48.dp + navigationBarHeight)) } } } diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt index 6d13b717..20cac86b 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.consumeWindowInsets import androidx.compose.foundation.layout.displayCutout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -92,6 +93,7 @@ private fun SettingScreenContent( val scrollState = rememberScrollState() var topBarHeight by remember { mutableIntStateOf(0) } val density = LocalDensity.current.density + val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() if (isShowSelectLanguageDialog.value) { SelectLanguageDialog( @@ -150,7 +152,7 @@ private fun SettingScreenContent( enableInAppUpdate = uiState.enableInAppUpdate, onCheckedChange = updateUseInAppUpdate, ) - Spacer(modifier = Modifier.height(48.dp)) + Spacer(modifier = Modifier.height(48.dp + navigationHeight)) } } } From 2957873aeee99ddd466be6ba90a1a8d004feffdb Mon Sep 17 00:00:00 2001 From: kosenda Date: Wed, 22 May 2024 01:29:20 +0900 Subject: [PATCH 36/64] feature: add title in each screens --- core/resource/src/main/res/values-ja/strings.xml | 5 +++++ core/resource/src/main/res/values/strings.xml | 5 +++++ .../core/ui/parts/BackTopBar.kt | 16 +++++++++++++--- .../feature/history/ConvertHistoryScreen.kt | 14 ++++++-------- .../hiraganaconverter/feature/info/InfoScreen.kt | 1 + .../feature/info/licence/LicenseScreen.kt | 8 +------- .../licence/licensedetail/LicenseDetailScreen.kt | 11 +---------- .../feature/setting/SettingScreen.kt | 1 + 8 files changed, 33 insertions(+), 28 deletions(-) diff --git a/core/resource/src/main/res/values-ja/strings.xml b/core/resource/src/main/res/values-ja/strings.xml index 0e2d4b81..3f9b54cb 100644 --- a/core/resource/src/main/res/values-ja/strings.xml +++ b/core/resource/src/main/res/values-ja/strings.xml @@ -39,6 +39,11 @@ アプリのレビューをしていただけないでしょうか? 後で + + 情報 + 設定 + 履歴 + ひらがな カタカナ diff --git a/core/resource/src/main/res/values/strings.xml b/core/resource/src/main/res/values/strings.xml index b8df3974..15342bde 100644 --- a/core/resource/src/main/res/values/strings.xml +++ b/core/resource/src/main/res/values/strings.xml @@ -39,6 +39,11 @@ Could you please review the application? Later + + Info + Settings + History + ひらがな カタカナ diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt index 13b0872d..d45b543b 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/BackTopBar.kt @@ -7,17 +7,18 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.displayCutout -import androidx.compose.foundation.layout.displayCutoutPadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior @@ -40,10 +41,11 @@ import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @OptIn(ExperimentalMaterial3Api::class) @Composable fun BackTopBar( + title: String, scrollBehavior: TopAppBarScrollBehavior, modifier: Modifier = Modifier, onBackPressed: () -> Unit, - title: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, ) { val layoutDirection = LocalLayoutDirection.current val isShowTopBar by remember(scrollBehavior.state.collapsedFraction) { @@ -64,7 +66,13 @@ fun BackTopBar( exit = fadeOut(), ) { TopAppBar( - title = title, + title = { + Text( + text = title, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.primary, + ) + }, modifier = modifier.background(MaterialTheme.colorScheme.surface), scrollBehavior = scrollBehavior, navigationIcon = { @@ -84,6 +92,7 @@ fun BackTopBar( ) } }, + actions = actions, colors = TopAppBarDefaults.topAppBarColors( containerColor = Color.Transparent, scrolledContainerColor = Color.Transparent, @@ -98,6 +107,7 @@ fun BackTopBar( fun PreviewBackTopBar() { HiraganaConverterTheme { BackTopBar( + title = "Title", scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(), onBackPressed = {}, ) diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt index eb8369ff..84a0ef12 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.background 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.asPaddingValues @@ -44,6 +43,7 @@ import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -112,6 +112,7 @@ private fun ConvertHistoryScreenContent( .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( + title = stringResource(id = R.string.title_history), scrollBehavior = scrollBehavior, modifier = Modifier .noRippleClickable { @@ -123,13 +124,10 @@ private fun ConvertHistoryScreenContent( onBackPressed = onBackPressed, ) { if (state.convertHistories.isNotEmpty()) { - Row { - Spacer(modifier = Modifier.weight(1f)) - DeleteButton( - modifier = Modifier.padding(end = 16.dp), - onClick = deleteAllConvertHistory, - ) - } + DeleteButton( + modifier = Modifier.padding(end = 16.dp), + onClick = deleteAllConvertHistory, + ) } } }, diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt index 4f1bc762..85f1e7fb 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt @@ -117,6 +117,7 @@ private fun InfoScreenContent( .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( + title = stringResource(id = R.string.title_info), scrollBehavior = scrollBehavior, modifier = Modifier .noRippleClickable { diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt index 556ae8cc..1ef2c439 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/LicenseScreen.kt @@ -90,6 +90,7 @@ private fun LicenseContent( .displayCutoutPadding(), topBar = { BackTopBar( + title = stringResource(id = R.string.licenses_title), scrollBehavior = scrollBehavior, modifier = Modifier.noRippleClickable { coroutineScope.launch { @@ -97,13 +98,6 @@ private fun LicenseContent( } }, onBackPressed = onBackPressed, - title = { - Text( - text = stringResource(id = R.string.licenses_title), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.primary, - ) - }, ) }, ) { innerPadding -> diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt index 9aa63d8e..86adc0c9 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/licence/licensedetail/LicenseDetailScreen.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.datasource.LoremIpsum import androidx.compose.ui.unit.dp import com.mikepenz.aboutlibraries.ui.compose.m3.HtmlText @@ -55,6 +54,7 @@ fun LicenseDetailScreen( .displayCutoutPadding(), topBar = { BackTopBar( + title = libraryName, scrollBehavior = scrollBehavior, modifier = Modifier.noRippleClickable { coroutineScope.launch { @@ -62,15 +62,6 @@ fun LicenseDetailScreen( } }, onBackPressed = onBackPressed, - title = { - Text( - text = libraryName, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.primary, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - ) - }, ) }, ) { innerPadding -> diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt index 20cac86b..e60ff39b 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt @@ -107,6 +107,7 @@ private fun SettingScreenContent( .background(MaterialTheme.colorScheme.surface), topBar = { BackTopBar( + title = stringResource(id = R.string.title_settings), scrollBehavior = scrollBehavior, modifier = Modifier .noRippleClickable { From 6c5c288efec11ff48b99b1fa4253960221405b32 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 01:02:03 +0000 Subject: [PATCH 37/64] chore(deps): update slack orb to v4.13.3 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b2f86e9f..a2e7e87c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 orbs: - slack: circleci/slack@4.13.2 + slack: circleci/slack@4.13.3 gh: circleci/github-cli@2.3.0 executors: From e397e0121315a9946e22152ab59801ae2cbbba26 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 01:02:07 +0000 Subject: [PATCH 38/64] chore(deps): update aboutlibraries to v11.2.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 348ff10d..14ee0269 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,7 +43,7 @@ turbine = "1.1.0" mockk = "1.13.11" roborazzi = "1.16.1" showkase = "1.0.2" -aboutLibraries = "11.1.4" +aboutLibraries = "11.2.0" # ** I'm using it, so no deletions allowed. ** androidxComposeCompiler = "1.5.14" From 2f67b693aaa29581d44271182fa88e572c033bbf Mon Sep 17 00:00:00 2001 From: kosenda Date: Thu, 23 May 2024 01:17:18 +0900 Subject: [PATCH 39/64] feature: change desing --- .../src/main/res/values-ja/strings.xml | 1 - core/resource/src/main/res/values/strings.xml | 1 - .../hiraganaconverter/core/ui/parts/TopBar.kt | 10 +-- .../core/ui/parts/button/CustomlIconButton.kt | 12 +-- .../core/ui/parts/button/DeleteButton.kt | 78 ------------------- .../core/ui/parts/dialog/DialogTopBar.kt | 4 +- .../feature/converter/ConverterScreen.kt | 10 +-- .../history/ConvertHistoryDetailDialog.kt | 4 +- .../feature/history/ConvertHistoryScreen.kt | 9 ++- .../feature/info/InfoScreen.kt | 10 +-- 10 files changed, 31 insertions(+), 108 deletions(-) delete mode 100644 core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/DeleteButton.kt diff --git a/core/resource/src/main/res/values-ja/strings.xml b/core/resource/src/main/res/values-ja/strings.xml index 3f9b54cb..18d8bda4 100644 --- a/core/resource/src/main/res/values-ja/strings.xml +++ b/core/resource/src/main/res/values-ja/strings.xml @@ -16,7 +16,6 @@ テーマ 言語 フォント - すべて削除 Top ネットワークに接続していません… diff --git a/core/resource/src/main/res/values/strings.xml b/core/resource/src/main/res/values/strings.xml index 15342bde..bf5ab5b1 100644 --- a/core/resource/src/main/res/values/strings.xml +++ b/core/resource/src/main/res/values/strings.xml @@ -16,7 +16,6 @@ Theme Language Font - Delete all Top Not connected to network… diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt index 766354a9..b60c7847 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/TopBar.kt @@ -68,20 +68,20 @@ fun TopBar( ), actions = { CustomIconButton( - modifier = Modifier.padding(horizontal = 8.dp), - contentDescription = "info", painter = painterResource(id = R.drawable.ic_outline_info_24), + contentDescription = "", + modifier = Modifier.padding(horizontal = 8.dp), onClick = dropUnlessResumed { navigateScreen(Nav.Info) }, ) CustomIconButton( - modifier = Modifier.padding(end = 8.dp), - contentDescription = "settings", painter = painterResource(id = R.drawable.ic_outline_settings_24), + contentDescription = "", + modifier = Modifier.padding(end = 8.dp), onClick = dropUnlessResumed { navigateScreen(Nav.Setting) }, ) CustomIconButton( - contentDescription = "history", painter = painterResource(id = R.drawable.ic_baseline_history_24), + contentDescription = "", onClick = dropUnlessResumed { navigateScreen(Nav.History) }, ) Spacer(modifier = Modifier.weight(1f)) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomlIconButton.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomlIconButton.kt index b374ccfe..0ac07c8c 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomlIconButton.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomlIconButton.kt @@ -24,10 +24,10 @@ import ksnd.hiraganaconverter.core.ui.theme.secondaryBrush @Composable fun CustomIconButton( - modifier: Modifier = Modifier, - contentDescription: String, painter: Painter, - contentColor: Color? = MaterialTheme.colorScheme.primary, + contentDescription: String, + modifier: Modifier = Modifier, + contentColor: Color? = null, containerColor: Color = MaterialTheme.colorScheme.surface, onClick: () -> Unit, ) { @@ -45,15 +45,15 @@ fun CustomIconButton( Image( painter = painter, contentDescription = contentDescription, - colorFilter = if (contentColor == null) null else ColorFilter.tint(contentColor), + colorFilter = contentColor?.let { ColorFilter.tint(it) }, contentScale = ContentScale.Fit, modifier = Modifier .size(32.dp) .then( if (contentColor == null) { - Modifier - } else { Modifier.contentBrush(brush = secondaryBrush()) + } else { + Modifier }, ), ) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/DeleteButton.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/DeleteButton.kt deleted file mode 100644 index 1b467b91..00000000 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/DeleteButton.kt +++ /dev/null @@ -1,78 +0,0 @@ -package ksnd.hiraganaconverter.core.ui.parts.button - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.scale -import androidx.compose.ui.graphics.ColorFilter -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import ksnd.hiraganaconverter.core.resource.R -import ksnd.hiraganaconverter.core.ui.preview.UiModePreview -import ksnd.hiraganaconverter.core.ui.rememberButtonScaleState -import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme - -@Composable -fun DeleteButton( - modifier: Modifier = Modifier, - onClick: () -> Unit, -) { - val buttonScaleState = rememberButtonScaleState() - Button( - modifier = modifier - .padding(vertical = 8.dp) - .defaultMinSize(minHeight = 48.dp) - .scale(scale = buttonScaleState.animationScale.value), - onClick = onClick, - interactionSource = buttonScaleState.interactionSource, - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.errorContainer, - ), - ) { - Row( - modifier = Modifier.wrapContentSize(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - ) { - Image( - painter = painterResource(id = R.drawable.ic_baseline_delete_outline_24), - contentDescription = "convert", - colorFilter = ColorFilter.tint( - MaterialTheme.colorScheme.error, - ), - contentScale = ContentScale.Fit, - modifier = Modifier.size(36.dp), - ) - Text( - text = stringResource(id = R.string.delete_all), - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.error, - modifier = Modifier.padding(start = 8.dp), - ) - } - } -} - -@UiModePreview -@Composable -fun PreviewDeleteButton() { - HiraganaConverterTheme { - Surface(color = MaterialTheme.colorScheme.surface) { - DeleteButton(onClick = {}) - } - } -} diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/DialogTopBar.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/DialogTopBar.kt index d2b0d470..23639eca 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/DialogTopBar.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/DialogTopBar.kt @@ -42,9 +42,9 @@ fun DialogTopBar( ) { Row(modifier = Modifier.weight(1f), content = leftContent) CustomIconButton( - modifier = Modifier.padding(end = 8.dp), - contentDescription = "", painter = painterResource(id = R.drawable.baseline_close_24), + contentDescription = "", + modifier = Modifier.padding(end = 8.dp), onClick = onCloseClick, ) } diff --git a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt index 23f70272..1cb52d2b 100644 --- a/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/ksnd/hiraganaconverter/feature/converter/ConverterScreen.kt @@ -281,18 +281,18 @@ private fun BeforeOrAfterTextField( if (isBefore) { CustomIconButton( - modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), - contentDescription = "pasteText", painter = painterResource(id = R.drawable.ic_baseline_content_paste_24), + contentDescription = "", + modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), onClick = { onValueChange(clipboardManager.getText()?.text ?: "") }, ) } else { CustomIconButton( - modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), - contentDescription = "share", painter = painterResource(id = R.drawable.baseline_share_24), + contentDescription = "", + modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), onClick = { context.startActivity( ShareCompat.IntentBuilder(context) @@ -305,7 +305,7 @@ private fun BeforeOrAfterTextField( CustomIconButton( modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), - contentDescription = "copyText", + contentDescription = "", painter = painterResource(id = R.drawable.ic_baseline_content_copy_24), onClick = { clipboardManager.setText(AnnotatedString(text)) diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt index 6561d4c2..2f772937 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt @@ -141,9 +141,9 @@ private fun BeforeOrAfterText( color = MaterialTheme.colorScheme.onSurface, ) CustomIconButton( - modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), - contentDescription = "copyText", painter = painterResource(id = R.drawable.ic_baseline_content_copy_24), + contentDescription = "", + modifier = Modifier.padding(top = 16.dp, bottom = 16.dp, end = 16.dp), onClick = { clipboardManager.setText( AnnotatedString( diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt index 84a0ef12..f0f37063 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt @@ -54,7 +54,7 @@ import ksnd.hiraganaconverter.core.model.ConvertHistoryData import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable import ksnd.hiraganaconverter.core.ui.parts.BackTopBar -import ksnd.hiraganaconverter.core.ui.parts.button.DeleteButton +import ksnd.hiraganaconverter.core.ui.parts.button.CustomIconButton import ksnd.hiraganaconverter.core.ui.parts.card.ConvertHistoryCard import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @@ -124,8 +124,11 @@ private fun ConvertHistoryScreenContent( onBackPressed = onBackPressed, ) { if (state.convertHistories.isNotEmpty()) { - DeleteButton( + CustomIconButton( + painter = painterResource(id = R.drawable.ic_baseline_delete_outline_24), + contentDescription = "", modifier = Modifier.padding(end = 16.dp), + contentColor = MaterialTheme.colorScheme.error, onClick = deleteAllConvertHistory, ) } @@ -183,7 +186,7 @@ private fun EmptyHistoryImage() { Column { Image( painter = painterResource(id = R.drawable.desert), - contentDescription = "no data", + contentDescription = "", modifier = Modifier .fillMaxWidth() .size(144.dp), diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt index 85f1e7fb..ebfa13d7 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/InfoScreen.kt @@ -267,17 +267,17 @@ private fun DeveloperInfoContent() { FlowRow { BodyMedium(text = stringResource(id = R.string.developer_name)) CustomIconButton( - contentDescription = "", painter = painterResource(id = R.drawable.ic_github_logo), - contentColor = null, + contentDescription = "", + contentColor = Color.Black, containerColor = Color.White, onClick = { uriHandler.openUri(uri = "https://github.com/kosenda") }, ) CustomIconButton( - modifier = Modifier.padding(start = 8.dp), - contentDescription = "", painter = painterResource(id = R.drawable.ic_x_logo), - contentColor = null, + contentDescription = "", + modifier = Modifier.padding(start = 8.dp), + contentColor = Color.White, containerColor = Color.Black, onClick = { uriHandler.openUri(uri = "https://twitter.com/ksnd_dev") }, ) From 3b7e8bb4ea60b5f44f1b824510ea79d495e9a569 Mon Sep 17 00:00:00 2001 From: kosenda Date: Thu, 23 May 2024 01:37:02 +0900 Subject: [PATCH 40/64] feature: add ConfirmDeleteDialog --- .../src/main/res/values-ja/strings.xml | 4 +++ core/resource/src/main/res/values/strings.xml | 5 ++++ .../core/ui/parts/dialog/MovesToSiteDialog.kt | 8 ++--- .../feature/history/ConvertHistoryScreen.kt | 29 ++++++++++++++++++- 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/core/resource/src/main/res/values-ja/strings.xml b/core/resource/src/main/res/values-ja/strings.xml index 18d8bda4..0c8c45e7 100644 --- a/core/resource/src/main/res/values-ja/strings.xml +++ b/core/resource/src/main/res/values-ja/strings.xml @@ -43,6 +43,10 @@ 設定 履歴 + + 削除確認 + 変換履歴を全て削除します。 + ひらがな カタカナ diff --git a/core/resource/src/main/res/values/strings.xml b/core/resource/src/main/res/values/strings.xml index bf5ab5b1..00857e14 100644 --- a/core/resource/src/main/res/values/strings.xml +++ b/core/resource/src/main/res/values/strings.xml @@ -43,6 +43,10 @@ Settings History + + Confirmation + Delete all conversion history. + ひらがな カタカナ @@ -57,6 +61,7 @@ App Info App Name OK + Cancel Developer KSND diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/MovesToSiteDialog.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/MovesToSiteDialog.kt index c41c8240..f996ead5 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/MovesToSiteDialog.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/dialog/MovesToSiteDialog.kt @@ -18,16 +18,12 @@ fun MovesToSiteDialog(onDismissRequest: () -> Unit, onClick: () -> Unit, url: St text = { Text(text = url) }, confirmButton = { TextButton(onClick = onClick) { - Text( - text = "OK", - ) + Text(text = stringResource(id = R.string.ok)) } }, dismissButton = { TextButton(onClick = onDismissRequest) { - Text( - text = "Cancel", - ) + Text(text = stringResource(id = R.string.cancel)) } }, ) diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt index f0f37063..5f695bb3 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryScreen.kt @@ -21,17 +21,20 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.AlertDialog import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue @@ -105,6 +108,7 @@ private fun ConvertHistoryScreenContent( var topBarHeight by remember { mutableIntStateOf(0) } val density = LocalDensity.current.density val navigationHeight = WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + var isShowConfirmDeleteDialog by remember { mutableStateOf(false) } Scaffold( modifier = Modifier @@ -129,7 +133,7 @@ private fun ConvertHistoryScreenContent( contentDescription = "", modifier = Modifier.padding(end = 16.dp), contentColor = MaterialTheme.colorScheme.error, - onClick = deleteAllConvertHistory, + onClick = { isShowConfirmDeleteDialog = true }, ) } } @@ -175,6 +179,29 @@ private fun ConvertHistoryScreenContent( } } } + + if (isShowConfirmDeleteDialog) { + AlertDialog( + onDismissRequest = { isShowConfirmDeleteDialog = false }, + title = { Text(text = stringResource(id = R.string.delete_history_dialog_title)) }, + text = { Text(text = stringResource(id = R.string.delete_history_dialog_message)) }, + confirmButton = { + TextButton( + onClick = { + deleteAllConvertHistory() + isShowConfirmDeleteDialog = false + }, + ) { + Text(text = stringResource(id = R.string.ok)) + } + }, + dismissButton = { + TextButton(onClick = { isShowConfirmDeleteDialog = false }) { + Text(text = stringResource(id = R.string.cancel)) + } + }, + ) + } } @Composable From eb1f6908598ff81de1337cbb7889dc3fb71a5181 Mon Sep 17 00:00:00 2001 From: kosenda Date: Fri, 24 May 2024 01:47:36 +0900 Subject: [PATCH 41/64] fix: settingscreen --- .../feature/setting/SettingScreen.kt | 61 +++++++++++-------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt index e60ff39b..d0d69c4f 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface @@ -33,7 +34,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity @@ -163,24 +163,6 @@ private fun SettingThemeContent( selectedTheme: Theme, onRadioButtonClick: (Theme) -> Unit, ) { - val modeRadioResourceTriple: List> = listOf( - Triple( - Theme.NIGHT, - stringResource(id = R.string.dark_mode), - painterResource(id = R.drawable.ic_baseline_brightness_2_24), - ), - Triple( - Theme.DAY, - stringResource(id = R.string.light_mode), - painterResource(id = R.drawable.ic_baseline_brightness_low_24), - ), - Triple( - Theme.AUTO, - stringResource(id = R.string.auto_mode), - painterResource(id = R.drawable.ic_baseline_brightness_auto_24), - ), - ) - TitleCard( text = stringResource(id = R.string.theme_setting), painter = painterResource(id = R.drawable.ic_baseline_brightness_4_24), @@ -191,14 +173,35 @@ private fun SettingThemeContent( ), modifier = Modifier.padding(vertical = 8.dp), ) { - modeRadioResourceTriple.map { resource -> - val (theme, displayThemeName, painter) = resource + listOf( + Triple( + Theme.NIGHT, + stringResource(id = R.string.dark_mode), + painterResource(id = R.drawable.ic_baseline_brightness_2_24), + ), + Triple( + Theme.DAY, + stringResource(id = R.string.light_mode), + painterResource(id = R.drawable.ic_baseline_brightness_low_24), + ), + Triple( + Theme.AUTO, + stringResource(id = R.string.auto_mode), + painterResource(id = R.drawable.ic_baseline_brightness_auto_24), + ), + ).forEachIndexed { index, (theme, displayThemeName, painter) -> CustomRadioButton( isSelected = theme == selectedTheme, buttonText = displayThemeName, painter = painter, onClick = { onRadioButtonClick(theme) }, ) + if (index != FontType.entries.size - 1) { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 8.dp), + color = MaterialTheme.colorScheme.surface, + ) + } } } } @@ -230,12 +233,16 @@ private fun SettingFontContent( ), modifier = Modifier.padding(vertical = 8.dp), ) { - Column(modifier = Modifier.padding(vertical = 8.dp)) { - FontType.entries.forEach { fontType -> - CustomRadioButton( - isSelected = fontType == selectFontType, - buttonText = fontType.fontName, - onClick = { onClickFontType(fontType) }, + FontType.entries.forEachIndexed { index, fontType -> + CustomRadioButton( + isSelected = fontType == selectFontType, + buttonText = fontType.fontName, + onClick = { onClickFontType(fontType) }, + ) + if (index != FontType.entries.size - 1) { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 8.dp), + color = MaterialTheme.colorScheme.surface, ) } } From 033fc86fbecd6671e351e9b16c17165f9cd76e91 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 25 May 2024 18:47:04 +0900 Subject: [PATCH 42/64] refactor: SettingScreen --- .../feature/setting/SettingScreen.kt | 114 ++---------------- .../setting/section/SettingFontSection.kt | 64 ++++++++++ .../SettingInAppUpdateSection.kt} | 30 ++++- .../setting/section/SettingLanguageSection.kt | 36 ++++++ .../setting/section/SettingThemeSection.kt | 84 +++++++++++++ 5 files changed, 218 insertions(+), 110 deletions(-) create mode 100644 feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt rename feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/{SettingInAppUpdateContent.kt => section/SettingInAppUpdateSection.kt} (65%) create mode 100644 feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt create mode 100644 feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt index d0d69c4f..65d99de1 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingScreen.kt @@ -15,10 +15,7 @@ import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface @@ -38,7 +35,6 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -50,11 +46,12 @@ import ksnd.hiraganaconverter.core.model.ui.Theme import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable import ksnd.hiraganaconverter.core.ui.parts.BackTopBar -import ksnd.hiraganaconverter.core.ui.parts.button.CustomRadioButton -import ksnd.hiraganaconverter.core.ui.parts.button.TransitionButton -import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme +import ksnd.hiraganaconverter.feature.setting.section.SettingFontSection +import ksnd.hiraganaconverter.feature.setting.section.SettingInAppUpdateSection +import ksnd.hiraganaconverter.feature.setting.section.SettingLanguageSection +import ksnd.hiraganaconverter.feature.setting.section.SettingThemeSection @Composable fun SettingScreen( @@ -136,20 +133,20 @@ private fun SettingScreenContent( .padding(horizontal = 16.dp), ) { Spacer(modifier = Modifier.height((topBarHeight / density).toInt().dp)) - SettingThemeContent( + SettingThemeSection( onRadioButtonClick = updateTheme, selectedTheme = uiState.theme, ) - SettingLanguageContent( + SettingLanguageSection( onClick = { isShowSelectLanguageDialog.value = true }, ) - SettingFontContent( + SettingFontSection( selectFontType = uiState.fontType, onClickFontType = { fontType -> updateFontType(fontType) }, ) - SettingInAppUpdateContent( + SettingInAppUpdateSection( enableInAppUpdate = uiState.enableInAppUpdate, onCheckedChange = updateUseInAppUpdate, ) @@ -158,104 +155,11 @@ private fun SettingScreenContent( } } -@Composable -private fun SettingThemeContent( - selectedTheme: Theme, - onRadioButtonClick: (Theme) -> Unit, -) { - TitleCard( - text = stringResource(id = R.string.theme_setting), - painter = painterResource(id = R.drawable.ic_baseline_brightness_4_24), - ) - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant, - ), - modifier = Modifier.padding(vertical = 8.dp), - ) { - listOf( - Triple( - Theme.NIGHT, - stringResource(id = R.string.dark_mode), - painterResource(id = R.drawable.ic_baseline_brightness_2_24), - ), - Triple( - Theme.DAY, - stringResource(id = R.string.light_mode), - painterResource(id = R.drawable.ic_baseline_brightness_low_24), - ), - Triple( - Theme.AUTO, - stringResource(id = R.string.auto_mode), - painterResource(id = R.drawable.ic_baseline_brightness_auto_24), - ), - ).forEachIndexed { index, (theme, displayThemeName, painter) -> - CustomRadioButton( - isSelected = theme == selectedTheme, - buttonText = displayThemeName, - painter = painter, - onClick = { onRadioButtonClick(theme) }, - ) - if (index != FontType.entries.size - 1) { - HorizontalDivider( - modifier = Modifier.padding(horizontal = 8.dp), - color = MaterialTheme.colorScheme.surface, - ) - } - } - } -} - -@Composable -private fun SettingLanguageContent(onClick: () -> Unit) { - TitleCard( - text = stringResource(id = R.string.language_setting), - painter = painterResource(id = R.drawable.ic_baseline_language_24), - ) - TransitionButton( - text = stringResource(id = R.string.select_language), - onClick = onClick, - ) -} - -@Composable -private fun SettingFontContent( - selectFontType: FontType, - onClickFontType: (FontType) -> Unit, -) { - TitleCard( - text = stringResource(id = R.string.font_setting), - painterResource(id = R.drawable.ic_baseline_text_fields_24), - ) - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surfaceVariant, - ), - modifier = Modifier.padding(vertical = 8.dp), - ) { - FontType.entries.forEachIndexed { index, fontType -> - CustomRadioButton( - isSelected = fontType == selectFontType, - buttonText = fontType.fontName, - onClick = { onClickFontType(fontType) }, - ) - if (index != FontType.entries.size - 1) { - HorizontalDivider( - modifier = Modifier.padding(horizontal = 8.dp), - color = MaterialTheme.colorScheme.surface, - ) - } - } - } -} - @UiModePreview @Composable fun PreviewSettingScreenContent() { HiraganaConverterTheme { - Surface( - modifier = Modifier.fillMaxSize(), - ) { + Surface { SettingScreenContent( uiState = SettingsUiState(), updateTheme = {}, diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt new file mode 100644 index 00000000..11febd38 --- /dev/null +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt @@ -0,0 +1,64 @@ +package ksnd.hiraganaconverter.feature.setting.section + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import ksnd.hiraganaconverter.core.model.ui.FontType +import ksnd.hiraganaconverter.core.resource.R +import ksnd.hiraganaconverter.core.ui.parts.button.CustomRadioButton +import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme + + +@Composable +fun SettingFontSection( + selectFontType: FontType, + onClickFontType: (FontType) -> Unit, +) { + TitleCard( + text = stringResource(id = R.string.font_setting), + painterResource(id = R.drawable.ic_baseline_text_fields_24), + ) + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + modifier = Modifier.padding(vertical = 8.dp), + ) { + FontType.entries.forEachIndexed { index, fontType -> + CustomRadioButton( + isSelected = fontType == selectFontType, + buttonText = fontType.fontName, + onClick = { onClickFontType(fontType) }, + ) + if (index != FontType.entries.size - 1) { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 8.dp), + color = MaterialTheme.colorScheme.surface, + ) + } + } + } +} + +@Preview +@Composable +fun PreviewSettingFontSection() { + HiraganaConverterTheme { + Surface { + Column { + SettingFontSection(FontType.DEFAULT) { } + } + } + } +} \ No newline at end of file diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingInAppUpdateContent.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingInAppUpdateSection.kt similarity index 65% rename from feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingInAppUpdateContent.kt rename to feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingInAppUpdateSection.kt index 5f5f3d13..f92b7ac6 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/SettingInAppUpdateContent.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingInAppUpdateSection.kt @@ -1,11 +1,12 @@ -package ksnd.hiraganaconverter.feature.setting +package ksnd.hiraganaconverter.feature.setting.section +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -16,9 +17,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @Composable -fun SettingInAppUpdateContent( +fun SettingInAppUpdateSection( enableInAppUpdate: Boolean, onCheckedChange: (Boolean) -> Unit, ) { @@ -33,12 +36,14 @@ fun SettingInAppUpdateContent( modifier = Modifier.padding(vertical = 8.dp), ) { Row( - modifier = Modifier.padding(all = 8.dp).fillMaxSize(), + modifier = Modifier.padding(all = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { Text( text = stringResource(id = R.string.in_app_update_show_update), - modifier = Modifier.padding(start = 16.dp).weight(1f), + modifier = Modifier + .padding(start = 16.dp) + .weight(1f), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.primary, ) @@ -46,3 +51,18 @@ fun SettingInAppUpdateContent( } } } + +@UiModePreview +@Composable +fun PreviewSettingInAppUpdateSection() { + HiraganaConverterTheme { + Surface { + Column { + SettingInAppUpdateSection( + enableInAppUpdate = true, + onCheckedChange = {}, + ) + } + } + } +} diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt new file mode 100644 index 00000000..5df12933 --- /dev/null +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt @@ -0,0 +1,36 @@ +package ksnd.hiraganaconverter.feature.setting.section + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import ksnd.hiraganaconverter.core.resource.R +import ksnd.hiraganaconverter.core.ui.parts.button.TransitionButton +import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme + +@Composable +fun SettingLanguageSection(onClick: () -> Unit) { + TitleCard( + text = stringResource(id = R.string.language_setting), + painter = painterResource(id = R.drawable.ic_baseline_language_24), + ) + TransitionButton( + text = stringResource(id = R.string.select_language), + onClick = onClick, + ) +} + +@Preview +@Composable +fun PreviewSettingLanguageSection() { + HiraganaConverterTheme { + Surface { + Column { + SettingLanguageSection {} + } + } + } +} diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt new file mode 100644 index 00000000..10877e86 --- /dev/null +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt @@ -0,0 +1,84 @@ +package ksnd.hiraganaconverter.feature.setting.section + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import ksnd.hiraganaconverter.core.model.ui.FontType +import ksnd.hiraganaconverter.core.model.ui.Theme +import ksnd.hiraganaconverter.core.resource.R +import ksnd.hiraganaconverter.core.ui.parts.button.CustomRadioButton +import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme + +@Composable +fun SettingThemeSection( + selectedTheme: Theme, + onRadioButtonClick: (Theme) -> Unit, +) { + TitleCard( + text = stringResource(id = R.string.theme_setting), + painter = painterResource(id = R.drawable.ic_baseline_brightness_4_24), + ) + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + modifier = Modifier.padding(vertical = 8.dp), + ) { + listOf( + Triple( + Theme.NIGHT, + stringResource(id = R.string.dark_mode), + painterResource(id = R.drawable.ic_baseline_brightness_2_24), + ), + Triple( + Theme.DAY, + stringResource(id = R.string.light_mode), + painterResource(id = R.drawable.ic_baseline_brightness_low_24), + ), + Triple( + Theme.AUTO, + stringResource(id = R.string.auto_mode), + painterResource(id = R.drawable.ic_baseline_brightness_auto_24), + ), + ).forEachIndexed { index, (theme, displayThemeName, painter) -> + CustomRadioButton( + isSelected = theme == selectedTheme, + buttonText = displayThemeName, + painter = painter, + onClick = { onRadioButtonClick(theme) }, + ) + if (index != FontType.entries.size - 1) { + HorizontalDivider( + modifier = Modifier.padding(horizontal = 8.dp), + color = MaterialTheme.colorScheme.surface, + ) + } + } + } +} + +@Preview +@Composable +fun PreviewSettingThemeSection() { + HiraganaConverterTheme { + Surface { + Column { + SettingThemeSection( + selectedTheme = Theme.NIGHT, + onRadioButtonClick = {}, + ) + } + } + } +} From a9f060c5e75c550d7f0280e61cc64e31f8308471 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 25 May 2024 19:08:27 +0900 Subject: [PATCH 43/64] fix: preview and lint --- .../feature/setting/section/SettingFontSection.kt | 7 +++---- .../feature/setting/section/SettingLanguageSection.kt | 4 ++-- .../feature/setting/section/SettingThemeSection.kt | 3 ++- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt index 11febd38..863b00f9 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingFontSection.kt @@ -11,15 +11,14 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.model.ui.FontType import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.parts.button.CustomRadioButton import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme - @Composable fun SettingFontSection( selectFontType: FontType, @@ -51,7 +50,7 @@ fun SettingFontSection( } } -@Preview +@UiModePreview @Composable fun PreviewSettingFontSection() { HiraganaConverterTheme { @@ -61,4 +60,4 @@ fun PreviewSettingFontSection() { } } } -} \ No newline at end of file +} diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt index 5df12933..ca2a6504 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingLanguageSection.kt @@ -5,10 +5,10 @@ import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.parts.button.TransitionButton import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @Composable @@ -23,7 +23,7 @@ fun SettingLanguageSection(onClick: () -> Unit) { ) } -@Preview +@UiModePreview @Composable fun PreviewSettingLanguageSection() { HiraganaConverterTheme { diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt index 10877e86..28ae8a1c 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt @@ -18,6 +18,7 @@ import ksnd.hiraganaconverter.core.model.ui.Theme import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.parts.button.CustomRadioButton import ksnd.hiraganaconverter.core.ui.parts.card.TitleCard +import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @Composable @@ -68,7 +69,7 @@ fun SettingThemeSection( } } -@Preview +@UiModePreview @Composable fun PreviewSettingThemeSection() { HiraganaConverterTheme { From e4f1ad01b3d36be2063ec3fe285f3e22f24f1bb4 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 25 May 2024 19:16:51 +0900 Subject: [PATCH 44/64] chore: delete unused import --- .../feature/setting/section/SettingThemeSection.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt index 28ae8a1c..e7a16765 100644 --- a/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt +++ b/feature/setting/src/main/java/ksnd/hiraganaconverter/feature/setting/section/SettingThemeSection.kt @@ -11,7 +11,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.model.ui.FontType import ksnd.hiraganaconverter.core.model.ui.Theme From b8a8f7acc591770e7a9357bee4d8cec34f1df6c3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 25 May 2024 10:22:40 +0000 Subject: [PATCH 45/64] chore(deps): update roborazzi to v1.18.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 14ee0269..e37677b1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.11" -roborazzi = "1.16.1" +roborazzi = "1.18.0" showkase = "1.0.2" aboutLibraries = "11.2.0" From 9ae27606a5fc87b0fb1ad81bcae7177d3b0bba24 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 14:08:33 +0000 Subject: [PATCH 46/64] chore(deps): update kotlin monorepo to v2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e37677b1..4a0c8750 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,7 +23,7 @@ firebasePerfPlugin = "1.4.2" firebaseAppdistributionPlugin = "5.0.0" hilt = "2.51.1" junit4 = "4.13.2" -kotlin = "1.9.24" +kotlin = "2.0.0" kotlinxSerializationJson = "1.6.3" kotlinxDatetime = "0.6.0" ksp = "1.9.24-1.0.20" From e71ea9d908d0339c9248a7836bd5eb4caba4d50d Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 26 May 2024 11:35:51 +0900 Subject: [PATCH 47/64] feature: migrate kotlin 2.0 --- app/build.gradle.kts | 5 ++--- .../hiraganaconverter/AndroidApplicationPlugin.kt | 8 +------- .../AndroidLibraryComposePlugin.kt | 9 +-------- build.gradle.kts | 13 ++++--------- gradle/libs.versions.toml | 4 ++-- 5 files changed, 10 insertions(+), 29 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4fad6067..2abd0aeb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -73,11 +73,10 @@ android { } } buildFeatures { - compose = true buildConfig = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.androidxComposeCompiler.get() + composeCompiler { + enableStrongSkippingMode = true } packaging { resources { diff --git a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt index b4b86c9a..6869cdf1 100644 --- a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt +++ b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt @@ -11,10 +11,10 @@ import org.gradle.kotlin.dsl.getByType class AndroidApplicationPlugin : Plugin { override fun apply(target: Project) { with(target) { - val libs = extensions.getByType().named("libs") with(pluginManager) { apply("com.android.application") apply("org.jetbrains.kotlin.android") + apply("org.jetbrains.kotlin.plugin.compose") } extensions.configure { compileSdk = 34 @@ -33,12 +33,6 @@ class AndroidApplicationPlugin : Plugin { kotlinOptions { jvmTarget = JavaVersion.VERSION_17.toString() } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() - } } } } diff --git a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt index a5dcc35c..5d724ce4 100644 --- a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt +++ b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt @@ -13,16 +13,9 @@ class AndroidLibraryComposePlugin : Plugin { with(target) { with(pluginManager) { apply("com.google.devtools.ksp") + apply("org.jetbrains.kotlin.plugin.compose") } val libs = extensions.getByType().named("libs") - extensions.configure { - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.findVersion("androidxComposeCompiler").get().toString() - } - } dependencies { add("implementation", libs.findLibrary("androidx.compose.material3").get()) add("implementation", libs.findLibrary("androidx.compose.ui").get()) diff --git a/build.gradle.kts b/build.gradle.kts index 18f83029..d4499353 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,6 +5,7 @@ plugins { jacoco alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.android) apply false + alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.hilt) apply false alias(libs.plugins.kotlin.serialization) apply false @@ -71,19 +72,13 @@ tasks.create("jacocoTestReport") { subprojects { tasks.withType().configureEach { - kotlinOptions { + compilerOptions { val composeCompilerDir = "${project.layout.buildDirectory.get()}/compose_compiler" if (project.findProperty("composeCompilerReports") == "true") { - freeCompilerArgs += listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$composeCompilerDir" - ) + freeCompilerArgs.add("-P=plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=$composeCompilerDir") } if (project.findProperty("composeCompilerMetrics") == "true") { - freeCompilerArgs += listOf( - "-P", - "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$composeCompilerDir" - ) + freeCompilerArgs.add("-P=plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=$composeCompilerDir") } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4a0c8750..05c4413d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,7 @@ junit4 = "4.13.2" kotlin = "2.0.0" kotlinxSerializationJson = "1.6.3" kotlinxDatetime = "0.6.0" -ksp = "1.9.24-1.0.20" +ksp = "2.0.0-1.0.21" ktlint = "1.2.1" lazyColumnScrollbar = "1.9.0" lottie = "6.4.0" @@ -46,7 +46,6 @@ showkase = "1.0.2" aboutLibraries = "11.2.0" # ** I'm using it, so no deletions allowed. ** -androidxComposeCompiler = "1.5.14" jacoco = "0.8.10" [libraries] @@ -159,6 +158,7 @@ aboutLibraries = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", v [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } From 9537f7a4163dea91b4cbd9613ebb8f4fd223da7f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 05:02:59 +0000 Subject: [PATCH 48/64] fix(deps): update dependency com.airbnb.android:lottie-compose to v6.4.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 05c4413d..8102d46f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,7 +29,7 @@ kotlinxDatetime = "0.6.0" ksp = "2.0.0-1.0.21" ktlint = "1.2.1" lazyColumnScrollbar = "1.9.0" -lottie = "6.4.0" +lottie = "6.4.1" okhttp3 = "4.12.0" playReview = "2.0.1" retrofit = "2.11.0" From 6c578ece6e436314f69ec3a87ac47d894f100f54 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 14:13:59 +0000 Subject: [PATCH 49/64] chore(deps): update roborazzi to v1.19.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8102d46f..ff5e1c49 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.11" -roborazzi = "1.18.0" +roborazzi = "1.19.0" showkase = "1.0.2" aboutLibraries = "11.2.0" From f9c5a4b1fa265bcbab1b3586032c5850aeac053f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 04:51:04 +0000 Subject: [PATCH 50/64] chore(deps): update roborazzi to v1.20.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff5e1c49..205814fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ timber = "5.0.1" truth = "1.4.2" turbine = "1.1.0" mockk = "1.13.11" -roborazzi = "1.19.0" +roborazzi = "1.20.0" showkase = "1.0.2" aboutLibraries = "11.2.0" From d9699103767bde74b5a09c5839b5255a2c276d0a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 18:21:45 +0000 Subject: [PATCH 51/64] fix(deps): update androidxlifecycle to v2.8.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff5e1c49..3883eff1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ androidxComposeMaterial3 = "1.2.1" androidxCoreSplashscreen = "1.0.1" androidxDataStore = "1.1.1" androidxHilt = "1.2.0" -androidxLifecycle = "2.8.0" +androidxLifecycle = "2.8.1" androidxNavigation = "2.8.0-beta01" androidxTestCore = "1.5.0" appUpdate = "2.1.0" From ef25ec3f01c7bb201c3fb98e5dff74faa1f2bd81 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 18:21:48 +0000 Subject: [PATCH 52/64] fix(deps): update dependency androidx.appcompat:appcompat to v1.7.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff5e1c49..f5d76c78 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,7 @@ accompanist = "0.34.0" activity = "1.9.0" androidGradlePlugin = "8.4.1" -androidxAppCompat = "1.7.0-rc01" +androidxAppCompat = "1.7.0" androidxCompose = "1.6.7" androidxComposeMaterial3 = "1.2.1" androidxCoreSplashscreen = "1.0.1" From 2552e282902b938edfbde10abcb1a67cf5757646 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 08:29:56 +0000 Subject: [PATCH 53/64] chore(deps): update aboutlibraries to v11.2.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff5e1c49..2140737f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,7 +43,7 @@ turbine = "1.1.0" mockk = "1.13.11" roborazzi = "1.19.0" showkase = "1.0.2" -aboutLibraries = "11.2.0" +aboutLibraries = "11.2.1" # ** I'm using it, so no deletions allowed. ** jacoco = "0.8.10" From 312fd335c829a24bba03f3b030bf6ffd944b75d2 Mon Sep 17 00:00:00 2001 From: kosenda Date: Fri, 31 May 2024 01:23:38 +0900 Subject: [PATCH 54/64] feature: use canScrollBackward --- .../core/ui/parts/button/MoveTopButton.kt | 8 +------- .../feature/history/ConvertHistoryDetailDialog.kt | 11 +---------- .../feature/info/PrivacyPolicyContent.kt | 4 +--- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt index c51c0ffb..8f94b153 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/MoveTopButton.kt @@ -19,9 +19,6 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -41,12 +38,9 @@ fun MoveTopButton(scrollState: ScrollState) { val coroutineScope = rememberCoroutineScope() val layoutDirection = LocalLayoutDirection.current val offset = IntOffset(x = 100, y = 100) - val showVisibleTopBar by remember { - derivedStateOf { scrollState.value > 0 } - } AnimatedVisibility( - visible = showVisibleTopBar, + visible = scrollState.canScrollBackward, modifier = Modifier.padding( start = WindowInsets.displayCutout .asPaddingValues() diff --git a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt index 2f772937..4cf9c80d 100644 --- a/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt +++ b/feature/history/src/main/java/ksnd/hiraganaconverter/feature/history/ConvertHistoryDetailDialog.kt @@ -22,9 +22,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.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.ClipboardManager @@ -68,12 +65,6 @@ private fun ConvertHistoryDetailDialogContent( val clipboardManager: ClipboardManager = LocalClipboardManager.current val scrollState = rememberScrollState() - val isScrolled by remember { - derivedStateOf { - scrollState.value > 10 - } - } - Scaffold( modifier = Modifier .fillMaxHeight(0.95f) @@ -82,7 +73,7 @@ private fun ConvertHistoryDetailDialogContent( .clip(RoundedCornerShape(16.dp)), topBar = { DialogTopBar( - isScrolled = isScrolled, + isScrolled = scrollState.canScrollBackward, leftContent = { Text( text = historyData.time, diff --git a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/PrivacyPolicyContent.kt b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/PrivacyPolicyContent.kt index c72e8c8e..3877e141 100644 --- a/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/PrivacyPolicyContent.kt +++ b/feature/info/src/main/java/ksnd/hiraganaconverter/feature/info/PrivacyPolicyContent.kt @@ -21,7 +21,6 @@ import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf @@ -63,7 +62,6 @@ fun PrivacyPolicyContent() { val webViewState = rememberWebViewState(url = stringResource(id = R.string.privacy_policy_url)) val navigator = rememberWebViewNavigator() val scrollState = rememberScrollState() - val isScrollTop by remember(scrollState.value) { derivedStateOf { scrollState.value == 0 } } val analytics = LocalAnalytics.current LaunchedEffect(isShowWebView) { @@ -102,7 +100,7 @@ fun PrivacyPolicyContent() { modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomEnd, ) { - this@ModalBottomSheet.AnimatedVisibility(visible = isScrollTop.not()) { + this@ModalBottomSheet.AnimatedVisibility(visible = scrollState.canScrollBackward) { ToTopFloatingButton( scrollState = scrollState, sizeChangedHeight = { floatingPlayerHeight = it }, From 90cff87728eba88048b0fce8cf36cb910ac2e858 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 18:13:11 +0000 Subject: [PATCH 55/64] fix(deps): update dependency com.google.firebase:firebase-bom to v33.1.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index af670f17..474adb6f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,7 +17,7 @@ coroutines = "1.8.1" coroutineTest = "1.8.1" dokka = "1.9.20" gmsPlugin = "4.4.1" -firebaseBom = "33.0.0" +firebaseBom = "33.1.0" firebaseCrashlyticsPlugin = "3.0.1" firebasePerfPlugin = "1.4.2" firebaseAppdistributionPlugin = "5.0.0" From 12c3d72eb37d04cae6c0e101da734a76c11bc995 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 17:12:24 +0000 Subject: [PATCH 56/64] chore(deps): update dependency com.google.gms.google-services to v4.4.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 474adb6f..0ffc3859 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ coil = "2.6.0" coroutines = "1.8.1" coroutineTest = "1.8.1" dokka = "1.9.20" -gmsPlugin = "4.4.1" +gmsPlugin = "4.4.2" firebaseBom = "33.1.0" firebaseCrashlyticsPlugin = "3.0.1" firebasePerfPlugin = "1.4.2" From cd18f013b69b54b7c6fd994b3f5a5eb991a0784d Mon Sep 17 00:00:00 2001 From: kosenda Date: Sat, 1 Jun 2024 02:31:21 +0900 Subject: [PATCH 57/64] bug-fix: add compose true in buildFeatures --- app/build.gradle.kts | 1 + .../ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2abd0aeb..b4912e07 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -74,6 +74,7 @@ android { } buildFeatures { buildConfig = true + compose = true } composeCompiler { enableStrongSkippingMode = true diff --git a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt index 5d724ce4..cf90659a 100644 --- a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt +++ b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidLibraryComposePlugin.kt @@ -15,6 +15,11 @@ class AndroidLibraryComposePlugin : Plugin { apply("com.google.devtools.ksp") apply("org.jetbrains.kotlin.plugin.compose") } + extensions.configure { + buildFeatures { + compose = true + } + } val libs = extensions.getByType().named("libs") dependencies { add("implementation", libs.findLibrary("androidx.compose.material3").get()) From f1a69881b730734b2e2b1e384e130bb011e85300 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 22:15:39 +0000 Subject: [PATCH 58/64] chore(deps): update dependency gradle to v8.8 --- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b82aa23a..a4413138 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a42..b740cf13 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. From 6b315e654714748322cd1bd82053f77c3cc19bd9 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 12:52:27 +0900 Subject: [PATCH 59/64] feature: change ConversionTypeCard for flip --- .../core/ui/parts/card/ConversionTypeCard.kt | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt index 52e0f4a3..2ba5038e 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt @@ -1,6 +1,8 @@ package ksnd.hiraganaconverter.core.ui.parts.card import android.view.HapticFeedbackConstants +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material3.Card @@ -14,6 +16,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource @@ -33,6 +36,12 @@ fun ConversionTypeCard( val buttonScaleState = rememberButtonScaleState() val localView = LocalView.current + val rotation by animateFloatAsState( + targetValue = if (selectedTextType == HiraKanaType.HIRAGANA) 180f else 0f, + animationSpec = tween(500), + label = "", + ) + Card( modifier = Modifier .padding(all = 8.dp) @@ -47,19 +56,39 @@ fun ConversionTypeCard( } onSelectedChange(selectedTextType) }, - ), + ) + .graphicsLayer { + rotationY = rotation + cameraDistance = 10f * density + }, colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.tertiaryContainer, + containerColor = if (rotation <= 90f) { + MaterialTheme.colorScheme.secondaryContainer + } else { + MaterialTheme.colorScheme.tertiaryContainer + }, ), ) { - ConversionTypeSpinnerCardContent(selectedTextType = selectedTextType) + if (rotation <= 90f) { + ConversionTypeSpinnerCardContent( + selectedTextType = selectedTextType + ) + } else { + ConversionTypeSpinnerCardContent( + modifier = Modifier.graphicsLayer { rotationY = 180f }, + selectedTextType = selectedTextType + ) + } } } @Composable -private fun ConversionTypeSpinnerCardContent(selectedTextType: HiraKanaType) { +private fun ConversionTypeSpinnerCardContent( + selectedTextType: HiraKanaType, + modifier: Modifier = Modifier, +) { Column( - modifier = Modifier.padding(all = 8.dp), + modifier = modifier.padding(all = 8.dp), ) { Text( text = stringResource(id = R.string.conversion_type), From 6ce0f4eb2a793a3db698f8360074ab13edcacf12 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 13:05:25 +0900 Subject: [PATCH 60/64] chore: fix bot warn --- .../core/ui/parts/card/ConversionTypeCard.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt index 2ba5038e..851be66e 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt @@ -71,12 +71,12 @@ fun ConversionTypeCard( ) { if (rotation <= 90f) { ConversionTypeSpinnerCardContent( - selectedTextType = selectedTextType + selectedTextType = selectedTextType, ) } else { ConversionTypeSpinnerCardContent( modifier = Modifier.graphicsLayer { rotationY = 180f }, - selectedTextType = selectedTextType + selectedTextType = selectedTextType, ) } } From 6e930418db85c5da1e292244acd710871bcf34b4 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 13:19:22 +0900 Subject: [PATCH 61/64] fix: add isTest for vrt --- .../core/ui/parts/card/ConversionTypeCard.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt index 851be66e..f5ab7b44 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/card/ConversionTypeCard.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp import ksnd.hiraganaconverter.core.model.ui.HiraKanaType import ksnd.hiraganaconverter.core.resource.R import ksnd.hiraganaconverter.core.ui.extension.noRippleClickable +import ksnd.hiraganaconverter.core.ui.isTest import ksnd.hiraganaconverter.core.ui.preview.UiModePreview import ksnd.hiraganaconverter.core.ui.rememberButtonScaleState import ksnd.hiraganaconverter.core.ui.theme.HiraganaConverterTheme @@ -58,7 +59,7 @@ fun ConversionTypeCard( }, ) .graphicsLayer { - rotationY = rotation + if (isTest().not()) rotationY = rotation cameraDistance = 10f * density }, colors = CardDefaults.cardColors( @@ -69,7 +70,7 @@ fun ConversionTypeCard( }, ), ) { - if (rotation <= 90f) { + if (rotation <= 90f || isTest()) { ConversionTypeSpinnerCardContent( selectedTextType = selectedTextType, ) From 00c9a40325f4b83754f4d45dba7649b1246be7da Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 16:30:27 +0900 Subject: [PATCH 62/64] feature: add LocalRippleTheme --- .../button/CustomButtonWithBackground.kt | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt index b3cff8cb..8e51cd63 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt @@ -5,10 +5,14 @@ import androidx.annotation.DrawableRes import androidx.compose.foundation.Image import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.material.ripple.LocalRippleTheme +import androidx.compose.material.ripple.RippleAlpha +import androidx.compose.material.ripple.RippleTheme import androidx.compose.material3.IconButton import androidx.compose.material3.IconButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color @@ -34,25 +38,36 @@ fun CustomButtonWithBackground( ) { val buttonScaleState = rememberButtonScaleState() val localView = LocalView.current - IconButton( - modifier = modifier - .padding(all = 8.dp) - .size(size = 56.dp) - .scale(scale = buttonScaleState.animationScale.value), - onClick = { - localView.performHapticFeedback(CONTEXT_CLICK) - onClick() - }, - colors = IconButtonDefaults.iconButtonColors(containerColor = containerColor), - interactionSource = buttonScaleState.interactionSource, + + CompositionLocalProvider( + LocalRippleTheme provides object : RippleTheme { + @Composable + override fun defaultColor(): Color = Color.Transparent + + @Composable + override fun rippleAlpha(): RippleAlpha = RippleAlpha(0f, 0f, 0f, 0f) + } ) { - Image( - painter = painterResource(id = id), - contentDescription = convertDescription, - modifier = Modifier.size(36.dp), - contentScale = ContentScale.Fit, - colorFilter = ColorFilter.tint(color = contentColor), - ) + IconButton( + modifier = modifier + .padding(all = 8.dp) + .size(size = 56.dp) + .scale(scale = buttonScaleState.animationScale.value), + onClick = { + localView.performHapticFeedback(CONTEXT_CLICK) + onClick() + }, + colors = IconButtonDefaults.iconButtonColors(containerColor = containerColor), + interactionSource = buttonScaleState.interactionSource, + ) { + Image( + painter = painterResource(id = id), + contentDescription = convertDescription, + modifier = Modifier.size(36.dp), + contentScale = ContentScale.Fit, + colorFilter = ColorFilter.tint(color = contentColor), + ) + } } } From a1c657d25c6413343cd8ab0fdfa26d30efd8501a Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 16:38:51 +0900 Subject: [PATCH 63/64] chore: fix bot warn --- .../core/ui/parts/button/CustomButtonWithBackground.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt index 8e51cd63..0de3767f 100644 --- a/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt +++ b/core/ui/src/main/java/ksnd/hiraganaconverter/core/ui/parts/button/CustomButtonWithBackground.kt @@ -42,11 +42,11 @@ fun CustomButtonWithBackground( CompositionLocalProvider( LocalRippleTheme provides object : RippleTheme { @Composable - override fun defaultColor(): Color = Color.Transparent + override fun defaultColor() = Color.Transparent @Composable - override fun rippleAlpha(): RippleAlpha = RippleAlpha(0f, 0f, 0f, 0f) - } + override fun rippleAlpha() = RippleAlpha(0f, 0f, 0f, 0f) + }, ) { IconButton( modifier = modifier From 16a9bedbbb69484d5afccd1e0249ceea8177a3a8 Mon Sep 17 00:00:00 2001 From: kosenda Date: Sun, 2 Jun 2024 16:44:04 +0900 Subject: [PATCH 64/64] feature: versionUp v1.31 --- .../kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt index 6869cdf1..96072445 100644 --- a/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt +++ b/build-logic/convention/src/main/kotlin/ksnd/hiraganaconverter/AndroidApplicationPlugin.kt @@ -22,8 +22,8 @@ class AndroidApplicationPlugin : Plugin { applicationId = "ksnd.hiraganaconverter" minSdk = 26 targetSdk = 34 - versionCode = 41 - versionName = "1.30" + versionCode = 42 + versionName = "1.31" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } compileOptions {