Skip to content

Commit bf2f89c

Browse files
authored
πŸ”€ :: (#956) AI 챗봇 μ±„νŒ… ν™”λ©΄ μ‚¬μš©μ„± κ°œμ„ 
πŸ”€ :: (#956) AI 챗봇 μ±„νŒ… ν™”λ©΄ μ‚¬μš©μ„± κ°œμ„ 
2 parents e5652b5 + a8cb58b commit bf2f89c

4 files changed

Lines changed: 186 additions & 93 deletions

File tree

β€Žapp/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.ktβ€Ž

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -7,48 +7,59 @@ import androidx.compose.foundation.layout.padding
77
import androidx.compose.foundation.layout.statusBarsPadding
88
import androidx.compose.material3.Scaffold
99
import androidx.compose.material3.SnackbarHost
10-
import androidx.compose.material3.windowsizeclass.WindowSizeClass
1110
import androidx.compose.runtime.Composable
1211
import androidx.compose.runtime.CompositionLocalProvider
1312
import androidx.compose.runtime.LaunchedEffect
1413
import androidx.compose.runtime.collectAsState
1514
import androidx.compose.runtime.getValue
16-
import androidx.compose.runtime.mutableStateOf
17-
import androidx.compose.runtime.remember
18-
import androidx.compose.runtime.setValue
1915
import androidx.compose.ui.Alignment
2016
import androidx.compose.ui.Modifier
2117
import androidx.compose.ui.unit.dp
2218
import androidx.lifecycle.viewmodel.compose.viewModel
2319
import androidx.navigation3.runtime.entryProvider
2420
import androidx.navigation3.runtime.rememberNavBackStack
2521
import androidx.navigation3.ui.NavDisplay
22+
import team.aliens.dms.android.app.MainActivityViewModel
2623
import team.aliens.dms.android.app.navigation.AdjustProfileScreenNav
2724
import team.aliens.dms.android.app.navigation.ApplicationScreenNav
2825
import team.aliens.dms.android.app.navigation.BottomNavigationBar
26+
import team.aliens.dms.android.app.navigation.ChatBotScreenNav
2927
import team.aliens.dms.android.app.navigation.CheckPasswordScreenNav
28+
import team.aliens.dms.android.app.navigation.EditPasswordScreenNav
29+
import team.aliens.dms.android.app.navigation.FindIdScreenNav
3030
import team.aliens.dms.android.app.navigation.HomeScreenNav
31+
import team.aliens.dms.android.app.navigation.LateStudyNav
3132
import team.aliens.dms.android.app.navigation.MealScreenNav
3233
import team.aliens.dms.android.app.navigation.MyPageScreenNav
33-
import team.aliens.dms.android.app.navigation.FindIdScreenNav
34-
import team.aliens.dms.android.app.navigation.ResetPasswordScreenNav
3534
import team.aliens.dms.android.app.navigation.NoticeDetailScreenNav
3635
import team.aliens.dms.android.app.navigation.NotificationScreenNav
3736
import team.aliens.dms.android.app.navigation.OnboardingScreenNav
3837
import team.aliens.dms.android.app.navigation.PointHistoryScreenNav
3938
import team.aliens.dms.android.app.navigation.RemainScreenNav
40-
import team.aliens.dms.android.app.navigation.EditPasswordScreenNav
39+
import team.aliens.dms.android.app.navigation.ResetPasswordScreenNav
4140
import team.aliens.dms.android.app.navigation.SelectProfileScreenNav
4241
import team.aliens.dms.android.app.navigation.SettingScreenNav
4342
import team.aliens.dms.android.app.navigation.SignInScreenNav
43+
import team.aliens.dms.android.app.navigation.SignUpCompleteNav
44+
import team.aliens.dms.android.app.navigation.SignUpEnterEmailNav
45+
import team.aliens.dms.android.app.navigation.SignUpEnterEmailVerificationCodeNav
46+
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationCodeNav
47+
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationQuestionNav
48+
import team.aliens.dms.android.app.navigation.SignUpEnterStudentNumberNav
49+
import team.aliens.dms.android.app.navigation.SignUpSetIdNav
50+
import team.aliens.dms.android.app.navigation.SignUpSetPasswordNav
51+
import team.aliens.dms.android.app.navigation.SignUpTermsNav
4452
import team.aliens.dms.android.app.navigation.VoteScreenNav
45-
import team.aliens.dms.android.app.MainActivityViewModel
46-
import team.aliens.dms.android.app.navigation.LateStudyNav
4753
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBar
4854
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBarVisuals
4955
import team.aliens.dms.android.core.ui.navigation.LocalResultStore
5056
import team.aliens.dms.android.core.ui.navigation.rememberResultStore
5157
import team.aliens.dms.android.data.voting.model.AllVoteSearch
58+
import team.aliens.dms.android.feature.chatbot.ui.ChatBotRoute
59+
import team.aliens.dms.android.feature.editpassword.navigation.CheckPasswordRoute
60+
import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordRoute
61+
import team.aliens.dms.android.feature.findid.navigation.FindIdRoute
62+
import team.aliens.dms.android.feature.latestudy.navigation.LateStudyRoute
5263
import team.aliens.dms.android.feature.main.application.navigation.ApplicationRoute
5364
import team.aliens.dms.android.feature.main.home.navigation.HomeRoute
5465
import team.aliens.dms.android.feature.main.mypage.navigation.MyPageRoute
@@ -60,9 +71,6 @@ import team.aliens.dms.android.feature.point.navigation.PointHistoryRoute
6071
import team.aliens.dms.android.feature.profile.route.AdjustProfileRoute
6172
import team.aliens.dms.android.feature.profile.route.SelectProfileRoute
6273
import team.aliens.dms.android.feature.remain.navigation.RemainApplicationRoute
63-
import team.aliens.dms.android.feature.editpassword.navigation.CheckPasswordRoute
64-
import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordRoute
65-
import team.aliens.dms.android.feature.findid.navigation.FindIdRoute
6674
import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordRoute
6775
import team.aliens.dms.android.feature.setting.navigation.SettingRoute
6876
import team.aliens.dms.android.feature.signin.navigation.SignInRoute
@@ -76,20 +84,7 @@ import team.aliens.dms.android.feature.signup.navigation.SignUpSetIdRoute
7684
import team.aliens.dms.android.feature.signup.navigation.SignUpSetPasswordRoute
7785
import team.aliens.dms.android.feature.signup.navigation.SignUpTermsRoute
7886
import team.aliens.dms.android.feature.vote.navigation.VoteRoute
79-
import team.aliens.dms.android.app.navigation.SignUpCompleteNav
80-
import team.aliens.dms.android.app.navigation.SignUpEnterEmailNav
81-
import team.aliens.dms.android.app.navigation.SignUpEnterEmailVerificationCodeNav
82-
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationCodeNav
83-
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationQuestionNav
84-
import team.aliens.dms.android.app.navigation.SignUpEnterStudentNumberNav
85-
import team.aliens.dms.android.app.navigation.SignUpSetIdNav
86-
import team.aliens.dms.android.app.navigation.SignUpSetPasswordNav
87-
import team.aliens.dms.android.app.navigation.SignUpTermsNav
88-
import team.aliens.dms.android.feature.latestudy.navigation.LateStudyRoute
8987
import java.util.UUID
90-
import team.aliens.dms.android.app.navigation.ChatBotScreenNav
91-
import team.aliens.dms.android.feature.chatbot.ui.ChatBotRoute
92-
9388

9489
@Composable
9590
fun DmsApp(
@@ -102,14 +97,13 @@ fun DmsApp(
10297

10398
val backStack = rememberNavBackStack(OnboardingScreenNav)
10499
val resultStore = rememberResultStore()
105-
var isChatInputFocused by remember { mutableStateOf(false) }
106100
val currentScreen = backStack.lastOrNull()
107101
val shouldShowBottomBar = currentScreen in listOf(
108102
HomeScreenNav,
109103
ApplicationScreenNav,
110104
ChatBotScreenNav,
111105
MyPageScreenNav,
112-
) && !(currentScreen == ChatBotScreenNav && isChatInputFocused)
106+
)
113107

114108
LaunchedEffect(isStartupResolved, isOnboardingCompleted, isJwtAvailable) {
115109
if (!isStartupResolved) return@LaunchedEffect
@@ -127,8 +121,7 @@ fun DmsApp(
127121
}
128122

129123
Box(
130-
modifier = Modifier
131-
.fillMaxSize(),
124+
modifier = Modifier.fillMaxSize(),
132125
) {
133126
Scaffold(
134127
bottomBar = {
@@ -145,16 +138,15 @@ fun DmsApp(
145138
}
146139
backStack.add(destination)
147140
}
148-
}
141+
},
149142
)
150143
}
151144
},
152145
contentWindowInsets = WindowInsets(0),
153146
) { paddingValues ->
154147
CompositionLocalProvider(LocalResultStore provides resultStore) {
155148
NavDisplay(
156-
modifier = Modifier
157-
.padding(paddingValues),
149+
modifier = Modifier.padding(paddingValues),
158150
backStack = backStack,
159151
onBack = { backStack.removeLastOrNull() },
160152
entryProvider = entryProvider {
@@ -214,22 +206,18 @@ fun DmsApp(
214206
},
215207
onNavigateLateStudyApplication = {
216208
backStack.add(LateStudyNav)
217-
}
209+
},
218210
)
219211
}
220212
entry<ChatBotScreenNav> {
221-
ChatBotRoute(
222-
onInputFocusChange = { focused ->
223-
isChatInputFocused = focused
224-
},
225-
)
213+
ChatBotRoute()
226214
}
227215
entry<VoteScreenNav> {
228216
VoteRoute(
229217
onNavigateBack = { backStack.remove(VoteScreenNav) },
230218
onShowSnackBar = { snackBarType, message ->
231219
appState.showSnackBar(snackBarType, message)
232-
}
220+
},
233221
)
234222
}
235223
entry<RemainScreenNav> {
@@ -240,7 +228,7 @@ fun DmsApp(
240228
},
241229
onShowSnackBar = { snackBarType, message ->
242230
appState.showSnackBar(snackBarType, message)
243-
}
231+
},
244232
)
245233
}
246234
entry<LateStudyNav> {
@@ -274,7 +262,7 @@ fun DmsApp(
274262
}
275263
entry<MealScreenNav> {
276264
MealRoute(
277-
onNavigateBack = { backStack.remove(MealScreenNav) }
265+
onNavigateBack = { backStack.remove(MealScreenNav) },
278266
)
279267
}
280268
entry<SettingScreenNav> {
@@ -288,13 +276,13 @@ fun DmsApp(
288276
},
289277
onShowSnackBar = { snackBarType, message ->
290278
appState.showSnackBar(snackBarType, message)
291-
}
279+
},
292280
)
293281
}
294282
entry<PointHistoryScreenNav> {
295283
PointHistoryRoute(
296284
pointType = it.pointType,
297-
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) }
285+
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) },
298286
)
299287
}
300288
entry<EditPasswordScreenNav> {
@@ -316,7 +304,7 @@ fun DmsApp(
316304
onNavigateEditPassword = { backStack.add(EditPasswordScreenNav(it)) },
317305
onShowSnackBar = { snackBar, message ->
318306
appState.showSnackBar(snackBar, message)
319-
}
307+
},
320308
)
321309
}
322310
entry<SelectProfileScreenNav> {
@@ -325,7 +313,7 @@ fun DmsApp(
325313
onNavigateAdjustProfile = { backStack.add(AdjustProfileScreenNav(model = it)) },
326314
onShowSnackBar = { snackBar, message ->
327315
appState.showSnackBar(snackBar, message)
328-
}
316+
},
329317
)
330318
}
331319
entry<AdjustProfileScreenNav> {
@@ -334,7 +322,7 @@ fun DmsApp(
334322
model = it.model,
335323
onShowSnackBar = { snackBar, message ->
336324
appState.showSnackBar(snackBar, message)
337-
}
325+
},
338326
)
339327
}
340328
entry<NotificationScreenNav> {
@@ -349,7 +337,7 @@ fun DmsApp(
349337
},
350338
onShowSnackBar = { snackBarType, message ->
351339
appState.showSnackBar(snackBarType, message)
352-
}
340+
},
353341
)
354342
}
355343
entry<NoticeDetailScreenNav> {

β€Žfeature/src/main/kotlin/team/aliens/dms/android/feature/chatbot/ui/ChatBotScreen.ktβ€Ž

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package team.aliens.dms.android.feature.chatbot.ui
22

3+
import androidx.compose.animation.core.animateDpAsState
34
import androidx.compose.foundation.background
45
import androidx.compose.foundation.layout.Arrangement
56
import androidx.compose.foundation.layout.Box
67
import androidx.compose.foundation.layout.Column
78
import androidx.compose.foundation.layout.PaddingValues
9+
import androidx.compose.foundation.layout.WindowInsets
10+
import androidx.compose.foundation.layout.asPaddingValues
811
import androidx.compose.foundation.layout.fillMaxSize
912
import androidx.compose.foundation.layout.fillMaxWidth
10-
import androidx.compose.foundation.layout.imePadding
13+
import androidx.compose.foundation.layout.height
14+
import androidx.compose.foundation.layout.ime
1115
import androidx.compose.foundation.layout.padding
1216
import androidx.compose.foundation.layout.statusBarsPadding
1317
import androidx.compose.foundation.lazy.LazyColumn
@@ -35,6 +39,13 @@ import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotMessage
3539
import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotState
3640
import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotViewModel
3741

42+
private val ChatBotInputBarHeight = 64.dp
43+
private val ChatBotKeyboardInputBottomPadding = 12.dp
44+
private val ChatBotBottomNavigationInputPadding = 16.dp
45+
private val ChatBotScaffoldBottomBarPadding = 104.dp
46+
private val ChatBotInputBarHorizontalPadding = 20.dp
47+
private val ChatBotMessageBottomSpacing = 24.dp
48+
3849
@Composable
3950
fun ChatBotRoute(
4051
onInputFocusChange: (Boolean) -> Unit = {},
@@ -68,6 +79,28 @@ private fun ChatBotScreen(
6879
) {
6980
var isInputFocused by remember { mutableStateOf(false) }
7081
val listState = rememberLazyListState()
82+
val keyboardBottomPadding = WindowInsets.ime
83+
.asPaddingValues()
84+
.calculateBottomPadding()
85+
val isKeyboardVisible = keyboardBottomPadding > 0.dp
86+
87+
val targetInputBottomPadding = if (isKeyboardVisible) {
88+
(
89+
keyboardBottomPadding -
90+
ChatBotScaffoldBottomBarPadding +
91+
ChatBotKeyboardInputBottomPadding
92+
).coerceAtLeast(ChatBotKeyboardInputBottomPadding)
93+
} else {
94+
ChatBotBottomNavigationInputPadding
95+
}
96+
97+
val inputBottomPadding by animateDpAsState(
98+
targetValue = targetInputBottomPadding,
99+
label = "ChatBotInputBottomPadding",
100+
)
101+
102+
val inputBackgroundHeight = inputBottomPadding + ChatBotInputBarHeight
103+
val messageBottomPadding = inputBackgroundHeight + ChatBotMessageBottomSpacing
71104

72105
LaunchedEffect(state.messages.size, state.isLoading) {
73106
if (state.messages.isNotEmpty() || state.isLoading) {
@@ -92,6 +125,7 @@ private fun ChatBotScreen(
92125
horizontalAlignment = Alignment.CenterHorizontally,
93126
) {
94127
ChatBotHeader()
128+
95129
ChatBotSuggestionQuestions(
96130
onSuggestionClick = onSuggestionClick,
97131
)
@@ -104,19 +138,11 @@ private fun ChatBotScreen(
104138
.padding(horizontal = 20.dp),
105139
contentPadding = PaddingValues(
106140
top = 72.dp,
107-
bottom = if (isInputFocused) {
108-
112.dp
109-
} else {
110-
132.dp
111-
},
141+
bottom = messageBottomPadding,
112142
),
113143
verticalArrangement = Arrangement.spacedBy(12.dp),
114144
horizontalAlignment = Alignment.CenterHorizontally,
115145
) {
116-
item {
117-
ChatBotCompactHeader()
118-
}
119-
120146
state.messages.forEach { message ->
121147
item {
122148
ChatBotMessageItem(message = message)
@@ -131,26 +157,29 @@ private fun ChatBotScreen(
131157
}
132158
}
133159

160+
Box(
161+
modifier = Modifier
162+
.align(Alignment.BottomCenter)
163+
.fillMaxWidth()
164+
.height(inputBackgroundHeight)
165+
.background(DmsTheme.colorScheme.background),
166+
)
167+
134168
ChatBotInputBar(
135169
value = state.input,
136170
onValueChange = onInputChange,
137171
onSendClick = onSendClick,
138-
enabled = !state.isLoading,
172+
enabled = true,
139173
onFocusChange = { focused ->
140174
isInputFocused = focused
141175
onInputFocusChange(focused)
142176
},
143177
modifier = Modifier
144178
.align(Alignment.BottomCenter)
145-
.imePadding()
146179
.padding(
147-
start = 20.dp,
148-
end = 20.dp,
149-
bottom = if (isInputFocused) {
150-
12.dp
151-
} else {
152-
16.dp
153-
},
180+
start = ChatBotInputBarHorizontalPadding,
181+
end = ChatBotInputBarHorizontalPadding,
182+
bottom = inputBottomPadding,
154183
),
155184
)
156185
}
@@ -173,27 +202,14 @@ private fun ChatBotHeader() {
173202
modifier = Modifier
174203
.fillMaxWidth()
175204
.padding(top = 22.dp),
176-
text = "μ™ΈμΆœ, 점호, 벌점, 세탁싀 이용 λ“± κΈ°μˆ™μ‚¬ κ·œμ •μ„ AI\nκ°€ λΉ λ₯΄κ³  μ •ν™•ν•˜κ²Œ μ•ˆλ‚΄ν•΄ λ“œλ¦½λ‹ˆλ‹€.",
205+
text = "μ™ΈμΆœ, 점호, 벌점, 세탁싀 이용 λ“± κΈ°μˆ™μ‚¬ κ·œμ •μ„ \nAIκ°€ λΉ λ₯΄κ³  μ •ν™•ν•˜κ²Œ μ•ˆλ‚΄ν•΄ λ“œλ¦½λ‹ˆλ‹€.",
177206
color = DmsTheme.colorScheme.inverseSurface,
178207
style = DmsTheme.typography.body3,
179208
textAlign = TextAlign.Center,
180209
)
181210
}
182211
}
183212

184-
@Composable
185-
private fun ChatBotCompactHeader() {
186-
Text(
187-
modifier = Modifier
188-
.fillMaxWidth()
189-
.padding(top = 8.dp),
190-
text = "μ™ΈμΆœ, 점호, 벌점, 세탁싀 이용 λ“± κΈ°μˆ™μ‚¬ κ·œμ •μ„ AI\nκ°€ λΉ λ₯΄κ³  μ •ν™•ν•˜κ²Œ μ•ˆλ‚΄ν•΄ λ“œλ¦½λ‹ˆλ‹€.",
191-
color = DmsTheme.colorScheme.inverseSurface,
192-
style = DmsTheme.typography.body3,
193-
textAlign = TextAlign.Center,
194-
)
195-
}
196-
197213
@Composable
198214
private fun ChatBotSuggestionQuestions(
199215
onSuggestionClick: (String) -> Unit,

0 commit comments

Comments
Β (0)