diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6c350ede..570e3265 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -8,12 +8,14 @@ plugins { android { namespace = "com.yapp.orbit" - compileSdk = 35 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - versionCode = 6 - versionName = "1.1.3" - targetSdk = 35 + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() + + versionCode = libs.versions.versionCode.get().toInt() + versionName = libs.versions.versionName.get() } buildTypes { diff --git a/build-logic/src/main/java/com/yapp/convention/ComposeAndroid.kt b/build-logic/src/main/java/com/yapp/convention/ComposeAndroid.kt index f705f061..3b3de5e7 100644 --- a/build-logic/src/main/java/com/yapp/convention/ComposeAndroid.kt +++ b/build-logic/src/main/java/com/yapp/convention/ComposeAndroid.kt @@ -8,9 +8,9 @@ import org.jetbrains.kotlin.compose.compiler.gradle.ComposeCompilerGradlePluginE internal fun Project.configureComposeAndroid() { with(plugins) { apply("org.jetbrains.kotlin.plugin.compose") + apply("com.github.skydoves.compose.stability.analyzer") } - val libs = extensions.libs androidExtension.apply { dependencies { val bom = libs.findLibrary("compose.bom").get() diff --git a/build-logic/src/main/java/com/yapp/convention/CoroutineAndroid.kt b/build-logic/src/main/java/com/yapp/convention/CoroutineAndroid.kt index 1a8ec58c..52fd35a4 100644 --- a/build-logic/src/main/java/com/yapp/convention/CoroutineAndroid.kt +++ b/build-logic/src/main/java/com/yapp/convention/CoroutineAndroid.kt @@ -9,7 +9,6 @@ internal fun Project.configureCoroutine() { } private fun Project.addImplementation(libraryKey: String) { - val libs = extensions.libs dependencies { "implementation"(libs.findLibrary(libraryKey).get()) } diff --git a/build-logic/src/main/java/com/yapp/convention/Extension.kt b/build-logic/src/main/java/com/yapp/convention/Extension.kt index 3ebad57f..4408c796 100644 --- a/build-logic/src/main/java/com/yapp/convention/Extension.kt +++ b/build-logic/src/main/java/com/yapp/convention/Extension.kt @@ -6,7 +6,6 @@ import com.android.build.api.dsl.LibraryExtension import org.gradle.api.Project import org.gradle.api.artifacts.VersionCatalog import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.api.plugins.ExtensionContainer import org.gradle.kotlin.dsl.getByType import org.jetbrains.kotlin.konan.properties.Properties @@ -22,8 +21,8 @@ internal val Project.androidExtension: CommonExtension<*, *, *, *, *, *> .onFailure { println("Could not find Library or Application extension from this project") } .getOrThrow() -internal val ExtensionContainer.libs: VersionCatalog - get() = getByType().named("libs") +internal val Project.libs: VersionCatalog + get() = extensions.getByType().named("libs") internal fun CommonExtension<*, *, *, *, *, *>.addBuildConfigFields(project: Project) { val baseUrl = project.getLocalProperty("baseUrl", "https://default.example.com") diff --git a/build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt b/build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt index 15db09ff..dec5fc7a 100644 --- a/build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt +++ b/build-logic/src/main/java/com/yapp/convention/HiltAndroid.kt @@ -10,7 +10,6 @@ internal fun Project.configureHiltAndroid() { apply("com.google.devtools.ksp") } - val libs = extensions.libs dependencies { "implementation"(libs.findLibrary("hilt.android").get()) "ksp"(libs.findLibrary("hilt.android.compiler").get()) diff --git a/build-logic/src/main/java/com/yapp/convention/HiltKotlin.kt b/build-logic/src/main/java/com/yapp/convention/HiltKotlin.kt index 46330dcc..c654dfdd 100644 --- a/build-logic/src/main/java/com/yapp/convention/HiltKotlin.kt +++ b/build-logic/src/main/java/com/yapp/convention/HiltKotlin.kt @@ -9,7 +9,6 @@ internal fun Project.configureHiltKotlin() { apply("com.google.devtools.ksp") } - val libs = extensions.libs dependencies { "implementation"(libs.findLibrary("hilt.core").get()) "ksp"(libs.findLibrary("hilt.compiler").get()) diff --git a/build-logic/src/main/java/com/yapp/convention/KotlinAndroid.kt b/build-logic/src/main/java/com/yapp/convention/KotlinAndroid.kt index b842ac37..f0b21aa2 100644 --- a/build-logic/src/main/java/com/yapp/convention/KotlinAndroid.kt +++ b/build-logic/src/main/java/com/yapp/convention/KotlinAndroid.kt @@ -15,10 +15,10 @@ internal fun Project.configureKotlinAndroid() { pluginManager.apply("org.jetbrains.kotlin.plugin.serialization") androidExtension.apply { - compileSdk = 34 + compileSdk = libs.findVersion("compileSdk").get().requiredVersion.toInt() defaultConfig { - minSdk = 28 + minSdk = libs.findVersion("minSdk").get().requiredVersion.toInt() } buildFeatures { diff --git a/build-logic/src/main/java/com/yapp/convention/TestAndroid.kt b/build-logic/src/main/java/com/yapp/convention/TestAndroid.kt index e4fcee6b..fa1a6124 100644 --- a/build-logic/src/main/java/com/yapp/convention/TestAndroid.kt +++ b/build-logic/src/main/java/com/yapp/convention/TestAndroid.kt @@ -12,7 +12,6 @@ internal fun Project.configureTestAndroid() { } internal fun Project.configureComposeUiTest() { - val libs = extensions.libs dependencies { "androidTestImplementation"(libs.findLibrary("compose-ui-test-junit4").get()) "debugImplementation"(libs.findLibrary("compose-ui-test-manifest").get()) @@ -24,7 +23,6 @@ internal fun Project.configureJUnitAndroid() { androidExtension.apply { defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } - val libs = extensions.libs dependencies { "androidTestImplementation"(libs.findLibrary("androidx-test-ext-junit").get()) "androidTestImplementation"(libs.findLibrary("androidx-test-runner").get()) diff --git a/build-logic/src/main/java/com/yapp/convention/TestCoverage.kt b/build-logic/src/main/java/com/yapp/convention/TestCoverage.kt index 70510798..5dd83030 100644 --- a/build-logic/src/main/java/com/yapp/convention/TestCoverage.kt +++ b/build-logic/src/main/java/com/yapp/convention/TestCoverage.kt @@ -13,7 +13,6 @@ import org.gradle.testing.jacoco.tasks.JacocoReport internal fun Project.configureTestCoverage() { pluginManager.apply("jacoco") - val libs = extensions.libs extensions.configure { toolVersion = libs.findVersion("jacoco").get().toString() } diff --git a/build-logic/src/main/java/com/yapp/convention/TestKotlin.kt b/build-logic/src/main/java/com/yapp/convention/TestKotlin.kt index 790833c0..efbf3db7 100644 --- a/build-logic/src/main/java/com/yapp/convention/TestKotlin.kt +++ b/build-logic/src/main/java/com/yapp/convention/TestKotlin.kt @@ -4,7 +4,6 @@ import org.gradle.api.Project import org.gradle.kotlin.dsl.dependencies internal fun Project.configureTestKotlin() { - val libs = extensions.libs dependencies { // JUnit4 단위 테스트 프레임워크 "testImplementation"(libs.findLibrary("junit4").get()) diff --git a/build-logic/src/main/java/orbit.android.feature.gradle.kts b/build-logic/src/main/java/orbit.android.feature.gradle.kts index 47d5c072..42b7094f 100644 --- a/build-logic/src/main/java/orbit.android.feature.gradle.kts +++ b/build-logic/src/main/java/orbit.android.feature.gradle.kts @@ -9,7 +9,6 @@ dependencies { implementation(project(":core:designsystem")) implementation(project(":core:ui")) - val libs = project.extensions.libs implementation(libs.findLibrary("compose-navigation").get()) implementation(libs.findLibrary("lifecycle-viewmodel").get()) implementation(libs.findLibrary("lifecycle-runtime").get()) diff --git a/build.gradle.kts b/build.gradle.kts index 3f1d3f7f..01648063 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ plugins { alias(libs.plugins.google.service) apply false alias(libs.plugins.firebase.app.distribution) apply false alias(libs.plugins.firebase.crashlytics) apply false + alias(libs.plugins.stability.analyzer) apply false } apply { diff --git a/core/common/src/main/java/com/yapp/common/navigation/OrbitNavigator.kt b/core/common/src/main/java/com/yapp/common/navigation/OrbitNavigator.kt index ec884f97..2a8c2df0 100644 --- a/core/common/src/main/java/com/yapp/common/navigation/OrbitNavigator.kt +++ b/core/common/src/main/java/com/yapp/common/navigation/OrbitNavigator.kt @@ -2,6 +2,7 @@ package com.yapp.common.navigation import android.util.Log import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.runtime.remember import androidx.navigation.NavHostController import androidx.navigation.NavOptions @@ -20,6 +21,7 @@ import com.yapp.common.navigation.route.SplashRoute import com.yapp.common.navigation.route.WebViewRoute import com.yapp.domain.model.Alarm +@Stable class OrbitNavigator( val navController: NavHostController, ) { diff --git a/core/designsystem/src/main/java/com/yapp/designsystem/theme/OrbitColors.kt b/core/designsystem/src/main/java/com/yapp/designsystem/theme/OrbitColors.kt index 186fa8df..4af827bd 100644 --- a/core/designsystem/src/main/java/com/yapp/designsystem/theme/OrbitColors.kt +++ b/core/designsystem/src/main/java/com/yapp/designsystem/theme/OrbitColors.kt @@ -1,11 +1,13 @@ package com.yapp.designsystem.theme +import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color +@Stable class OrbitColors( main: Color = Color(0xFFFEFF65), sub_main: Color = Color(0xFFFDFE90), diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index beabc390..86e0b160 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -18,5 +18,4 @@ dependencies { implementation(libs.retrofit.kotlin.serialization) implementation(libs.okhttp.logging) implementation(libs.kotlinx.serialization.json) - implementation(libs.process.phoenix) } diff --git a/core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetState.kt b/core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetState.kt index b558e1d8..3c09c74b 100644 --- a/core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetState.kt +++ b/core/ui/src/main/java/com/yapp/ui/component/bottomsheet/OrbitBottomSheetState.kt @@ -4,6 +4,7 @@ import androidx.compose.material.ModalBottomSheetState import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -32,6 +33,7 @@ fun rememberOrbitBottomSheetState(): OrbitBottomSheetState { } } +@Stable class OrbitBottomSheetState( val state: ModalBottomSheetState, val contentState: State, diff --git a/core/ui/src/main/java/com/yapp/ui/component/timepicker/OrbitPickerItem.kt b/core/ui/src/main/java/com/yapp/ui/component/timepicker/OrbitPickerItem.kt index 729421a2..34c4246b 100644 --- a/core/ui/src/main/java/com/yapp/ui/component/timepicker/OrbitPickerItem.kt +++ b/core/ui/src/main/java/com/yapp/ui/component/timepicker/OrbitPickerItem.kt @@ -10,7 +10,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember @@ -27,11 +27,11 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.yapp.designsystem.theme.OrbitTheme -import com.yapp.ui.utils.toPx import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlin.math.abs +@Stable @Composable fun OrbitPickerItem( modifier: Modifier = Modifier, @@ -113,25 +113,6 @@ fun OrbitPickerItem( .pointerInput(Unit) { detectVerticalDragGestures { change, _ -> change.consume() } }, ) { items(listScrollCount, key = { index -> index }) { index -> - val layoutInfo by remember { derivedStateOf { listState.layoutInfo } } - - val viewportCenterOffset = layoutInfo.viewportStartOffset + - (layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset) / 2 - - val itemInfo = layoutInfo.visibleItemsInfo.find { it.index == index } - val itemCenterOffset = itemInfo?.offset?.let { it + (itemInfo.size / 2) } ?: 0 - - val distanceFromCenter = abs(viewportCenterOffset - itemCenterOffset) - val maxDistance = totalItemHeight.toPx() * visibleItemsMiddle - - val alpha = if (distanceFromCenter <= maxDistance) { - ((maxDistance - distanceFromCenter) / maxDistance).coerceIn(0.2f, 1f) - } else { - 0.2f - } - - val scaleY = 1f - (0.2f * (distanceFromCenter / maxDistance)).coerceIn(0f, 0.4f) - val item = getItemForIndex( index = index, items = items, @@ -143,10 +124,35 @@ fun OrbitPickerItem( text = item?.let { itemFormatter(it) } ?: "", maxLines = 1, style = textStyle, - color = OrbitTheme.colors.white.copy(alpha = alpha), + color = OrbitTheme.colors.white, modifier = Modifier .padding(vertical = itemSpacing / 2) - .graphicsLayer(scaleY = scaleY) + .graphicsLayer { + val layoutInfo = listState.layoutInfo + + val viewportCenterOffset = layoutInfo.viewportStartOffset + + (layoutInfo.viewportEndOffset - layoutInfo.viewportStartOffset) / 2 + + val itemInfo = layoutInfo.visibleItemsInfo.find { it.index == index } + val itemCenterOffset = itemInfo?.offset?.let { it + (itemInfo.size / 2) } ?: 0 + + val distanceFromCenter = abs(viewportCenterOffset - itemCenterOffset) + val maxDistance = totalItemHeight.toPx() * visibleItemsMiddle + + if (maxDistance <= 0f) { + alpha = 1f + scaleY = 1f + return@graphicsLayer + } + + alpha = if (distanceFromCenter <= maxDistance) { + ((maxDistance - distanceFromCenter) / maxDistance).coerceIn(0.2f, 1f) + } else { + 0.2f + } + + scaleY = 1f - (0.2f * (distanceFromCenter / maxDistance)).coerceIn(0f, 0.4f) + } .onSizeChanged { size -> itemHeightPixels = size.height } .then(textModifier), ) diff --git a/core/ui/src/main/java/com/yapp/ui/component/timepicker/PickerState.kt b/core/ui/src/main/java/com/yapp/ui/component/timepicker/PickerState.kt index 2e8b9793..2c7914e9 100644 --- a/core/ui/src/main/java/com/yapp/ui/component/timepicker/PickerState.kt +++ b/core/ui/src/main/java/com/yapp/ui/component/timepicker/PickerState.kt @@ -3,10 +3,12 @@ package com.yapp.ui.component.timepicker import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.runtime.remember import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +@Stable class PickerState( val lazyListState: LazyListState, val initialIndex: Int, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2d1248b6..c2dd2ace 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,25 +1,24 @@ [versions] # SDK Versions -compileSdk = "34" +compileSdk = "35" minSdk = "28" -targetSdk = "34" -jdkVersion = "17" +targetSdk = "35" # App Versioning -versionName = "1.0.0" -versionCode = "1" +versionName = "1.1.3" +versionCode = "6" ## Android Gradle Plugin android-gradle-plugin = "8.7.2" ## Kotlin Symbol Processing -ksp = "2.0.0-1.0.22" +ksp = "2.2.21-2.0.4" ## Formatting Plugins ktlint = "11.5.1" ## Kotlin Versions -kotlin = "2.0.0" +kotlin = "2.2.21" kotlinx-serialization-json = "1.7.0" kotlinx-coroutines = "1.9.0-RC" kotlinx-collections = "0.3.7" @@ -43,9 +42,9 @@ compose-ui = "1.7.6" activity-compose = "1.9.3" ## Hilt -hilt = "2.51.1" -hilt-navigation-compose = "1.2.0" -hilt-work = "1.2.0" +hilt = "2.57.2" +hilt-navigation-compose = "1.3.0" +hilt-work = "1.3.0" ## Third Party okhttp = "4.12.0" @@ -74,11 +73,11 @@ timber = "5.0.1" orbit = "6.1.0" espressoCore = "3.6.1" material = "1.12.0" -process-pheonix = "3.0.0" -lottie = "6.1.0" +lottie = "6.7.1" accompanist = "0.37.0" materialAndroid = "1.7.5" amplitude = "1.20.3" +stability-analyzer = "0.5.0" [libraries] @@ -170,7 +169,6 @@ androidx-test-core = { group = "androidx.test", name = "core", version.ref = "an androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } -process-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "process-pheonix" } lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref= "lottie" } accompanist-permission = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" } androidx-material-android = { group = "androidx.compose.material", name = "material-android", version.ref = "materialAndroid" } @@ -196,3 +194,4 @@ compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = " google-service = { id = "com.google.gms.google-services", version.ref = "google-service" } firebase-app-distribution = { id = "com.google.firebase.appdistribution", version.ref = "firebase-app-distribution" } firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebase-crashlytics" } +stability-analyzer = { id = "com.github.skydoves.compose.stability.analyzer", version.ref = "stability-analyzer" }