Skip to content

Commit 581fd6e

Browse files
Merge pull request #129 from Next-Room/feature/NR-128
NR-128 힌트 화면을 XML -> Compose로 마이그레이션
2 parents a0a9c88 + 4640c20 commit 581fd6e

14 files changed

Lines changed: 1208 additions & 223 deletions

File tree

gradle/libs.versions.toml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ biometric = "1.1.0"
5252
flipper = "0.200.0"
5353
soloader = "0.10.4"
5454
leak-canary = "2.14"
55+
compose-bom = "2024.02.00"
56+
coil = "2.5.0"
5557

5658
[libraries]
5759
androidx-activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activity-ktx" }
@@ -113,6 +115,19 @@ credentials-auth = { module = "androidx.credentials:credentials-play-services-au
113115
google-identity = { module = "com.google.android.libraries.identity.googleid:googleid", version.ref = "google-identity" }
114116
leak-canary = { module = "com.squareup.leakcanary:leakcanary-android", version.ref = "leak-canary" }
115117

118+
# Compose
119+
androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
120+
androidx-compose-ui = { module = "androidx.compose.ui:ui" }
121+
androidx-compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" }
122+
androidx-compose-foundation = { module = "androidx.compose.foundation:foundation" }
123+
androidx-compose-material3 = { module = "androidx.compose.material3:material3" }
124+
androidx-compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
125+
androidx-compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
126+
androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.8.2" }
127+
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" }
128+
androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" }
129+
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
130+
116131
[plugins]
117132
android-application = { id = "com.android.application", version.ref = "android" }
118133
android-library = { id = "com.android.library", version.ref = "android" }
@@ -134,3 +149,13 @@ network = ["retrofit", "converter-gson", "logging-interceptor"]
134149
db = ["androidx-datastore", "androidx-datastore-preferences-core", "androidx-room-runtime", "androidx-room-ktx"]
135150
firebase = ["firebase-analytics-ktx", "firebase-crashlytics-ktx"]
136151
flipper = ["flipper", "soloader", "flipper-network-plugin"]
152+
compose = [
153+
"androidx-compose-ui",
154+
"androidx-compose-ui-graphics",
155+
"androidx-compose-foundation",
156+
"androidx-compose-ui-tooling-preview",
157+
"androidx-compose-material3",
158+
"androidx-activity-compose",
159+
"androidx-lifecycle-viewmodel-compose",
160+
"androidx-lifecycle-runtime-compose"
161+
]

presentation/build.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,10 @@ android {
3838
buildFeatures {
3939
viewBinding = true
4040
buildConfig = true
41+
compose = true
4142
}
4243
composeOptions {
43-
kotlinCompilerExtensionVersion = "1.5.2"
44+
kotlinCompilerExtensionVersion = "1.5.3" // Kotlin 1.9.10과 호환
4445
}
4546
}
4647

@@ -75,6 +76,12 @@ dependencies {
7576
implementation(libs.photoview)
7677
implementation(libs.biometric)
7778
debugImplementation(libs.leak.canary)
79+
80+
// Compose
81+
implementation(platform(libs.androidx.compose.bom))
82+
implementation(libs.bundles.compose)
83+
debugImplementation(libs.androidx.compose.ui.tooling)
84+
implementation(libs.coil.compose)
7885

7986
implementation(platform(libs.firebase.bom))
8087
implementation(libs.firebase.analytics.ktx)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.nextroom.nextroom.presentation.base
2+
3+
import android.os.Bundle
4+
import android.view.View
5+
import androidx.core.os.bundleOf
6+
import androidx.fragment.app.Fragment
7+
import com.google.firebase.analytics.FirebaseAnalytics
8+
import com.nextroom.nextroom.presentation.extension.updateSystemPadding
9+
10+
abstract class ComposeBaseFragment : Fragment() {
11+
abstract val screenName: String
12+
13+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
14+
super.onViewCreated(view, savedInstanceState)
15+
updateSystemPadding()
16+
17+
initSubscribe()
18+
initObserve()
19+
setFragmentResultListeners()
20+
initViews()
21+
}
22+
23+
open fun initSubscribe() {}
24+
open fun initObserve() {}
25+
open fun setFragmentResultListeners() {}
26+
open fun initViews() {}
27+
28+
override fun onResume() {
29+
super.onResume()
30+
31+
FirebaseAnalytics.getInstance(requireContext())
32+
.logEvent("screen_view", bundleOf("screen_name" to screenName))
33+
}
34+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.nextroom.nextroom.presentation.base
2+
3+
import androidx.navigation.fragment.findNavController
4+
import com.nextroom.nextroom.presentation.NavGraphDirections
5+
import com.nextroom.nextroom.presentation.R
6+
import com.nextroom.nextroom.presentation.common.NROneButtonDialog
7+
import com.nextroom.nextroom.presentation.extension.repeatOnStarted
8+
import com.nextroom.nextroom.presentation.extension.safeNavigate
9+
import kotlinx.coroutines.launch
10+
11+
abstract class ComposeBaseViewModelFragment<VM : NewBaseViewModel> : ComposeBaseFragment() {
12+
abstract val viewModel: VM
13+
14+
override fun initObserve() {
15+
super.initObserve()
16+
17+
viewLifecycleOwner.repeatOnStarted {
18+
launch {
19+
viewModel.errorFlow.collect {
20+
NavGraphDirections.moveToNrOneButtonDialog(
21+
NROneButtonDialog.NROneButtonArgument(
22+
title = getString(R.string.dialog_noti),
23+
message = getString(R.string.error_something),
24+
btnText = getString(R.string.text_confirm),
25+
errorText = it.message,
26+
)
27+
).also { findNavController().safeNavigate(it) }
28+
}
29+
}
30+
}
31+
}
32+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.nextroom.nextroom.presentation.common.compose
2+
3+
import androidx.compose.ui.graphics.Color
4+
5+
object NRColor {
6+
// Basic Colors
7+
val White = Color(0xFFFFFFFF)
8+
val White5 = Color(0x0DFFFFFF)
9+
val White12 = Color(0x1FFFFFFF)
10+
val White20 = Color(0x33FFFFFF)
11+
val White50 = Color(0x80FFFFFF)
12+
val White70 = Color(0xB3FFFFFF)
13+
14+
val Black = Color(0xFF1D1B20)
15+
val Black60 = Color(0x99000000)
16+
val OnSurface = Color(0xFF1D1B20)
17+
val Surface = Color(0xFFFEF7FF)
18+
19+
// Material Colors
20+
val ColorPrimary = Color(0xFF6750A4)
21+
val ColorSurface = Color(0xFFFEF7FF)
22+
val ColorSecondarySurface = Color(0x146750A4)
23+
val ColorLightPrimary = Color(0x146750A4)
24+
25+
// Blue
26+
val Blue = Color(0xFF378EFF)
27+
val Blue15 = Color(0x26378EFF)
28+
29+
// Gray Scale
30+
val Dark01 = Color(0xFF151516)
31+
val Gray01 = Color(0xFF9898A0)
32+
val Gray02 = Color(0xFF47474E)
33+
val Gray03 = Color(0xFF222223)
34+
val Gray04 = Color(0xFF999999)
35+
val Gray05 = Color(0xFF46454A)
36+
37+
// Red
38+
val Red = Color(0xFFFF5065)
39+
val Red02 = Color(0xFFF04438)
40+
41+
// Sub Colors
42+
val Sub1 = Color(0xFF1F2023)
43+
val Sub2 = Color(0xFF3A3B3D)
44+
45+
// Background
46+
val BgMain = Color(0xFF131417)
47+
48+
// Button Colors
49+
val PrimaryButtonBackground = Color(0xFFFFFFFF)
50+
val DisabledButtonBackground = Color(0xFF2D2D2D)
51+
val PrimaryButtonText = Color(0xFF000000)
52+
val DisabledButtonText = Color(0xFF555555)
53+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.nextroom.nextroom.presentation.common.compose
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.gestures.detectTapGestures
5+
import androidx.compose.foundation.layout.Box
6+
import androidx.compose.foundation.layout.fillMaxSize
7+
import androidx.compose.material3.CircularProgressIndicator
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.ui.Alignment
10+
import androidx.compose.ui.Modifier
11+
import androidx.compose.ui.graphics.Color
12+
import androidx.compose.ui.input.pointer.pointerInput
13+
import androidx.compose.ui.tooling.preview.Preview
14+
15+
@Composable
16+
fun NRLoading(
17+
isVisible: Boolean,
18+
modifier: Modifier = Modifier
19+
) {
20+
if (!isVisible) return
21+
22+
Box(
23+
modifier = modifier
24+
.fillMaxSize()
25+
.background(Color.Transparent)
26+
.pointerInput(Unit) {
27+
detectTapGestures { }
28+
},
29+
contentAlignment = Alignment.Center
30+
) {
31+
CircularProgressIndicator(color = NRColor.White)
32+
}
33+
}
34+
35+
@Preview(showBackground = true, backgroundColor = 0xFF151516)
36+
@Composable
37+
private fun NRLoadingPreview() {
38+
Box(modifier = Modifier.fillMaxSize()) {
39+
NRLoading(isVisible = true)
40+
}
41+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package com.nextroom.nextroom.presentation.common.compose
2+
3+
import androidx.compose.foundation.Image
4+
import androidx.compose.foundation.background
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.fillMaxWidth
9+
import androidx.compose.foundation.layout.height
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.size
12+
import androidx.compose.foundation.shape.RoundedCornerShape
13+
import androidx.compose.material3.Text
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.ui.Alignment
16+
import androidx.compose.ui.Modifier
17+
import androidx.compose.ui.res.painterResource
18+
import androidx.compose.ui.res.stringResource
19+
import androidx.compose.ui.text.style.TextAlign
20+
import androidx.compose.ui.tooling.preview.Preview
21+
import androidx.compose.ui.unit.dp
22+
import com.nextroom.nextroom.presentation.R
23+
import com.nextroom.nextroom.presentation.extension.throttleClick
24+
25+
@Composable
26+
fun NRToolbar(
27+
title: String,
28+
onBackClick: () -> Unit,
29+
onRightButtonClick: () -> Unit,
30+
modifier: Modifier = Modifier
31+
) {
32+
Box(
33+
contentAlignment = Alignment.Center
34+
) {
35+
Text(
36+
text = title,
37+
style = NRTypo.Poppins.size20,
38+
color = NRColor.White,
39+
textAlign = TextAlign.Center,
40+
)
41+
42+
Row(
43+
modifier = modifier
44+
.fillMaxWidth()
45+
.height(64.dp),
46+
verticalAlignment = Alignment.CenterVertically,
47+
horizontalArrangement = Arrangement.SpaceBetween,
48+
) {
49+
Image(
50+
painter = painterResource(R.drawable.ic_navigate_back_24),
51+
modifier = modifier
52+
.size(64.dp)
53+
.throttleClick { onBackClick() }
54+
.padding(20.dp),
55+
contentDescription = null,
56+
)
57+
58+
Text(
59+
text = stringResource(R.string.memo_button),
60+
color = NRColor.Dark01,
61+
style = NRTypo.Poppins.size14,
62+
modifier = modifier
63+
.padding(end = 20.dp)
64+
.background(
65+
color = NRColor.White,
66+
shape = RoundedCornerShape(size = 50.dp)
67+
)
68+
.padding(vertical = 6.dp, horizontal = 16.dp)
69+
.throttleClick { onRightButtonClick() }
70+
)
71+
}
72+
}
73+
}
74+
75+
@Preview(showBackground = true, backgroundColor = 0xFF1D1B20)
76+
@Composable
77+
private fun NRToolbarPreview() {
78+
NRToolbar(
79+
title = "01:23:45",
80+
onBackClick = {},
81+
onRightButtonClick = {}
82+
)
83+
}

0 commit comments

Comments
 (0)