Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
55c2c30
fix :: ์ฑ—๋ด‡ ์ž…๋ ฅ ์‹œ ํ•˜๋‹จ๋ฐ” ์œ ์ง€
ashxom Jul 6, 2026
0baa8ba
feat :: ์ฑ—๋ด‡ ๋‹ต๋ณ€ ๋งˆํฌ๋‹ค์šด ํ…์ŠคํŠธ ์ ์šฉ
ashxom Jul 6, 2026
5239d4f
fix :: ์ฑ—๋ด‡ ๋ฉ”์‹œ์ง€ ์Šคํฌ๋กค ํ•˜๋‹จ ์—ฌ๋ฐฑ ์กฐ์ •
ashxom Jul 6, 2026
3564f47
fix ;: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ๊ณผ ๋ฉ”์‹œ์ง€ ์˜์—ญ ๊ฒน์นจ ์ˆ˜์ •
ashxom Jul 6, 2026
57dd1ad
fix :: ํ‚ค๋ณด๋“œ ์ƒํƒœ ๋ฉ”์‹œ์ง€ ์—ฌ๋ฐฑ ์กฐ์ •
ashxom Jul 6, 2026
1d3c885
fix :: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ํ•˜๋‹จ ๋ฐฐ๊ฒฝ ์ฒ˜๋ฆฌ
ashxom Jul 6, 2026
96177f0
fix :: ์ž…๋ ฅ์ฐฝ๊ณผ ํ‚ค๋ณด๋“œ ์‚ฌ์ด ์—ฌ๋ฐฑ ์ œ๊ฑฐ
ashxom Jul 6, 2026
f12c712
fix :: ์ž…๋ ฅ์ฐฝ ํ‚ค๋ณด๋“œ ์ถ”์  ๋™์ž‘ ์ˆ˜์ •
ashxom Jul 6, 2026
1578205
fix :: ์ž…๋ ฅ์ฐฝ ํ‚ค๋ณด๋“œ ๊ฐ„๊ฒฉ ์กฐ์ •
ashxom Jul 7, 2026
87c4207
fix :: ์ž…๋ ฅ์ฐฝ ์ž…๋ ฅ ๋น„ํ™œ์„ฑ ๋ฌธ์ œ ์ˆ˜์ •
ashxom Jul 7, 2026
fe5d353
fix :: ํ‚ค๋ณด๋“œ ๊ฐ„๊ฒฉ ์กฐ์ •
ashxom Jul 7, 2026
bf48309
fix :: ์ž…๋ ฅ์ฐฝ ํ•˜๋‹จ ์—ฌ๋ฐฑ ๋ฐ ํ‚ค๋ณด๋“œ ์ธ์…‹ ์ฒ˜๋ฆฌ ๊ฐœ์„ 
ashxom Jul 7, 2026
c7bb618
fix :: ํ™”๋ฉด ํ‚ค๋ณด๋“œ ํ‘œ์‹œ ์‹œ ์ž…๋ ฅ์ฐฝ-ํ‚ค๋ณด๋“œ ์‚ฌ์ด ์—ฌ๋ฐฑ ์ˆ˜์ •
ashxom Jul 7, 2026
188aaab
fix :: ์ž…๋ ฅ์ฐฝ ํฌ์ปค์Šค ์‹œ ํ•˜๋‹จ๋ฐ” ์œ ์ง€
ashxom Jul 7, 2026
1351b5c
fix :: ์ž…๋ ฅ์ฐฝ ํ‚ค๋ณด๋“œ ๊ฐ„๊ฒฉ ์กฐ์ •
ashxom Jul 7, 2026
3b76a5a
fix :: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ํ‚ค๋ณด๋“œ ๋Œ€์‘ ๊ฐœ์„ 
ashxom Jul 7, 2026
2ed4553
fix :: ์ฑ—๋ด‡ ์ž…๋ ฅ์ฐฝ ํ‚ค๋ณด๋“œ ๊ฐ„๊ฒฉ ๋ณด์ •
ashxom Jul 7, 2026
4ce2130
refactor :: ์ฑ„ํŒ… ์ƒ๋‹จ ์•ˆ๋‚ด ๋ฌธ๊ตฌ ์ œ๊ฑฐ
ashxom Jul 7, 2026
34fc989
feat :: ์ž…๋ ฅ ์ค‘ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€
ashxom Jul 7, 2026
a8cb58b
style :: ์ฑ—๋ด‡ ์ž…๋ ฅ ์ค‘ ํ‘œ์‹œ ์œ„์น˜ ์กฐ์ •
ashxom Jul 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 35 additions & 47 deletions app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,59 @@
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import team.aliens.dms.android.app.MainActivityViewModel
import team.aliens.dms.android.app.navigation.AdjustProfileScreenNav
import team.aliens.dms.android.app.navigation.ApplicationScreenNav
import team.aliens.dms.android.app.navigation.BottomNavigationBar
import team.aliens.dms.android.app.navigation.ChatBotScreenNav
import team.aliens.dms.android.app.navigation.CheckPasswordScreenNav
import team.aliens.dms.android.app.navigation.EditPasswordScreenNav
import team.aliens.dms.android.app.navigation.FindIdScreenNav
import team.aliens.dms.android.app.navigation.HomeScreenNav
import team.aliens.dms.android.app.navigation.LateStudyNav
import team.aliens.dms.android.app.navigation.MealScreenNav
import team.aliens.dms.android.app.navigation.MyPageScreenNav
import team.aliens.dms.android.app.navigation.FindIdScreenNav
import team.aliens.dms.android.app.navigation.ResetPasswordScreenNav
import team.aliens.dms.android.app.navigation.NoticeDetailScreenNav
import team.aliens.dms.android.app.navigation.NotificationScreenNav
import team.aliens.dms.android.app.navigation.OnboardingScreenNav
import team.aliens.dms.android.app.navigation.PointHistoryScreenNav
import team.aliens.dms.android.app.navigation.RemainScreenNav
import team.aliens.dms.android.app.navigation.EditPasswordScreenNav
import team.aliens.dms.android.app.navigation.ResetPasswordScreenNav
import team.aliens.dms.android.app.navigation.SelectProfileScreenNav
import team.aliens.dms.android.app.navigation.SettingScreenNav
import team.aliens.dms.android.app.navigation.SignInScreenNav
import team.aliens.dms.android.app.navigation.SignUpCompleteNav
import team.aliens.dms.android.app.navigation.SignUpEnterEmailNav
import team.aliens.dms.android.app.navigation.SignUpEnterEmailVerificationCodeNav
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationCodeNav
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationQuestionNav
import team.aliens.dms.android.app.navigation.SignUpEnterStudentNumberNav
import team.aliens.dms.android.app.navigation.SignUpSetIdNav
import team.aliens.dms.android.app.navigation.SignUpSetPasswordNav
import team.aliens.dms.android.app.navigation.SignUpTermsNav
import team.aliens.dms.android.app.navigation.VoteScreenNav
import team.aliens.dms.android.app.MainActivityViewModel
import team.aliens.dms.android.app.navigation.LateStudyNav
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBar
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBarVisuals
import team.aliens.dms.android.core.ui.navigation.LocalResultStore
import team.aliens.dms.android.core.ui.navigation.rememberResultStore
import team.aliens.dms.android.data.voting.model.AllVoteSearch
import team.aliens.dms.android.feature.chatbot.ui.ChatBotRoute
import team.aliens.dms.android.feature.editpassword.navigation.CheckPasswordRoute
import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordRoute
import team.aliens.dms.android.feature.findid.navigation.FindIdRoute
import team.aliens.dms.android.feature.latestudy.navigation.LateStudyRoute
import team.aliens.dms.android.feature.main.application.navigation.ApplicationRoute
import team.aliens.dms.android.feature.main.home.navigation.HomeRoute
import team.aliens.dms.android.feature.main.mypage.navigation.MyPageRoute
Expand All @@ -60,9 +71,6 @@
import team.aliens.dms.android.feature.profile.route.AdjustProfileRoute
import team.aliens.dms.android.feature.profile.route.SelectProfileRoute
import team.aliens.dms.android.feature.remain.navigation.RemainApplicationRoute
import team.aliens.dms.android.feature.editpassword.navigation.CheckPasswordRoute
import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordRoute
import team.aliens.dms.android.feature.findid.navigation.FindIdRoute
import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordRoute
import team.aliens.dms.android.feature.setting.navigation.SettingRoute
import team.aliens.dms.android.feature.signin.navigation.SignInRoute
Expand All @@ -76,20 +84,7 @@
import team.aliens.dms.android.feature.signup.navigation.SignUpSetPasswordRoute
import team.aliens.dms.android.feature.signup.navigation.SignUpTermsRoute
import team.aliens.dms.android.feature.vote.navigation.VoteRoute
import team.aliens.dms.android.app.navigation.SignUpCompleteNav
import team.aliens.dms.android.app.navigation.SignUpEnterEmailNav
import team.aliens.dms.android.app.navigation.SignUpEnterEmailVerificationCodeNav
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationCodeNav
import team.aliens.dms.android.app.navigation.SignUpEnterSchoolVerificationQuestionNav
import team.aliens.dms.android.app.navigation.SignUpEnterStudentNumberNav
import team.aliens.dms.android.app.navigation.SignUpSetIdNav
import team.aliens.dms.android.app.navigation.SignUpSetPasswordNav
import team.aliens.dms.android.app.navigation.SignUpTermsNav
import team.aliens.dms.android.feature.latestudy.navigation.LateStudyRoute
import java.util.UUID
import team.aliens.dms.android.app.navigation.ChatBotScreenNav
import team.aliens.dms.android.feature.chatbot.ui.ChatBotRoute


@Composable
fun DmsApp(
Expand All @@ -102,14 +97,13 @@

val backStack = rememberNavBackStack(OnboardingScreenNav)
val resultStore = rememberResultStore()
var isChatInputFocused by remember { mutableStateOf(false) }
val currentScreen = backStack.lastOrNull()
val shouldShowBottomBar = currentScreen in listOf(
HomeScreenNav,
ApplicationScreenNav,
ChatBotScreenNav,
MyPageScreenNav,
) && !(currentScreen == ChatBotScreenNav && isChatInputFocused)
)

LaunchedEffect(isStartupResolved, isOnboardingCompleted, isJwtAvailable) {
if (!isStartupResolved) return@LaunchedEffect
Expand All @@ -127,8 +121,7 @@
}

Box(
modifier = Modifier
.fillMaxSize(),
modifier = Modifier.fillMaxSize(),
) {
Scaffold(
bottomBar = {
Expand All @@ -145,16 +138,15 @@
}
backStack.add(destination)
}
}
},
)
}
},
contentWindowInsets = WindowInsets(0),
) { paddingValues ->
CompositionLocalProvider(LocalResultStore provides resultStore) {
NavDisplay(
modifier = Modifier
.padding(paddingValues),
modifier = Modifier.padding(paddingValues),
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
entryProvider = entryProvider {
Expand Down Expand Up @@ -214,22 +206,18 @@
},
onNavigateLateStudyApplication = {
backStack.add(LateStudyNav)
}
},
)
}
entry<ChatBotScreenNav> {
ChatBotRoute(
onInputFocusChange = { focused ->
isChatInputFocused = focused
},
)
ChatBotRoute()
}
entry<VoteScreenNav> {
VoteRoute(
onNavigateBack = { backStack.remove(VoteScreenNav) },
onShowSnackBar = { snackBarType, message ->
appState.showSnackBar(snackBarType, message)
}
},
)
}
entry<RemainScreenNav> {
Expand All @@ -240,7 +228,7 @@
},
onShowSnackBar = { snackBarType, message ->
appState.showSnackBar(snackBarType, message)
}
},
)
}
entry<LateStudyNav> {
Expand Down Expand Up @@ -274,7 +262,7 @@
}
entry<MealScreenNav> {
MealRoute(
onNavigateBack = { backStack.remove(MealScreenNav) }
onNavigateBack = { backStack.remove(MealScreenNav) },
)
}
entry<SettingScreenNav> {
Expand All @@ -288,13 +276,13 @@
},
onShowSnackBar = { snackBarType, message ->
appState.showSnackBar(snackBarType, message)
}
},
)
}
entry<PointHistoryScreenNav> {
PointHistoryRoute(
pointType = it.pointType,
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) }
onBackClick = { backStack.remove(PointHistoryScreenNav(it.pointType)) },

Check warning

Code scanning / Android Lint

Implicit SAM Instances Warning

This argument is a new instance so remove will not remove anything
)
}
entry<EditPasswordScreenNav> {
Expand All @@ -316,7 +304,7 @@
onNavigateEditPassword = { backStack.add(EditPasswordScreenNav(it)) },
onShowSnackBar = { snackBar, message ->
appState.showSnackBar(snackBar, message)
}
},
)
}
entry<SelectProfileScreenNav> {
Expand All @@ -325,7 +313,7 @@
onNavigateAdjustProfile = { backStack.add(AdjustProfileScreenNav(model = it)) },
onShowSnackBar = { snackBar, message ->
appState.showSnackBar(snackBar, message)
}
},
)
}
entry<AdjustProfileScreenNav> {
Expand All @@ -334,7 +322,7 @@
model = it.model,
onShowSnackBar = { snackBar, message ->
appState.showSnackBar(snackBar, message)
}
},
)
}
entry<NotificationScreenNav> {
Expand All @@ -349,7 +337,7 @@
},
onShowSnackBar = { snackBarType, message ->
appState.showSnackBar(snackBarType, message)
}
},
)
}
entry<NoticeDetailScreenNav> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package team.aliens.dms.android.feature.chatbot.ui

import androidx.compose.animation.core.animateDpAsState
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.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
Expand Down Expand Up @@ -35,6 +39,13 @@ import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotMessage
import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotState
import team.aliens.dms.android.feature.chatbot.viewmodel.ChatBotViewModel

private val ChatBotInputBarHeight = 64.dp
private val ChatBotKeyboardInputBottomPadding = 12.dp
private val ChatBotBottomNavigationInputPadding = 16.dp
private val ChatBotScaffoldBottomBarPadding = 104.dp
private val ChatBotInputBarHorizontalPadding = 20.dp
private val ChatBotMessageBottomSpacing = 24.dp

@Composable
fun ChatBotRoute(
onInputFocusChange: (Boolean) -> Unit = {},
Expand Down Expand Up @@ -68,6 +79,28 @@ private fun ChatBotScreen(
) {
var isInputFocused by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
val keyboardBottomPadding = WindowInsets.ime
.asPaddingValues()
.calculateBottomPadding()
val isKeyboardVisible = keyboardBottomPadding > 0.dp

val targetInputBottomPadding = if (isKeyboardVisible) {
(
keyboardBottomPadding -
ChatBotScaffoldBottomBarPadding +
ChatBotKeyboardInputBottomPadding
).coerceAtLeast(ChatBotKeyboardInputBottomPadding)
} else {
ChatBotBottomNavigationInputPadding
}

val inputBottomPadding by animateDpAsState(
targetValue = targetInputBottomPadding,
label = "ChatBotInputBottomPadding",
)

val inputBackgroundHeight = inputBottomPadding + ChatBotInputBarHeight
val messageBottomPadding = inputBackgroundHeight + ChatBotMessageBottomSpacing

LaunchedEffect(state.messages.size, state.isLoading) {
if (state.messages.isNotEmpty() || state.isLoading) {
Expand All @@ -92,6 +125,7 @@ private fun ChatBotScreen(
horizontalAlignment = Alignment.CenterHorizontally,
) {
ChatBotHeader()

ChatBotSuggestionQuestions(
onSuggestionClick = onSuggestionClick,
)
Expand All @@ -104,19 +138,11 @@ private fun ChatBotScreen(
.padding(horizontal = 20.dp),
contentPadding = PaddingValues(
top = 72.dp,
bottom = if (isInputFocused) {
112.dp
} else {
132.dp
},
bottom = messageBottomPadding,
),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
item {
ChatBotCompactHeader()
}

state.messages.forEach { message ->
item {
ChatBotMessageItem(message = message)
Expand All @@ -131,26 +157,29 @@ private fun ChatBotScreen(
}
}

Box(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth()
.height(inputBackgroundHeight)
.background(DmsTheme.colorScheme.background),
)

ChatBotInputBar(
value = state.input,
onValueChange = onInputChange,
onSendClick = onSendClick,
enabled = !state.isLoading,
enabled = true,
onFocusChange = { focused ->
isInputFocused = focused
onInputFocusChange(focused)
},
modifier = Modifier
.align(Alignment.BottomCenter)
.imePadding()
.padding(
start = 20.dp,
end = 20.dp,
bottom = if (isInputFocused) {
12.dp
} else {
16.dp
},
start = ChatBotInputBarHorizontalPadding,
end = ChatBotInputBarHorizontalPadding,
bottom = inputBottomPadding,
),
)
}
Expand All @@ -173,27 +202,14 @@ private fun ChatBotHeader() {
modifier = Modifier
.fillMaxWidth()
.padding(top = 22.dp),
text = "์™ธ์ถœ, ์ ํ˜ธ, ๋ฒŒ์ , ์„ธํƒ์‹ค ์ด์šฉ ๋“ฑ ๊ธฐ์ˆ™์‚ฌ ๊ทœ์ •์„ AI\n๊ฐ€ ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ์•ˆ๋‚ดํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
text = "์™ธ์ถœ, ์ ํ˜ธ, ๋ฒŒ์ , ์„ธํƒ์‹ค ์ด์šฉ ๋“ฑ ๊ธฐ์ˆ™์‚ฌ ๊ทœ์ •์„ \nAI๊ฐ€ ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ์•ˆ๋‚ดํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
color = DmsTheme.colorScheme.inverseSurface,
style = DmsTheme.typography.body3,
textAlign = TextAlign.Center,
)
}
}

@Composable
private fun ChatBotCompactHeader() {
Text(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
text = "์™ธ์ถœ, ์ ํ˜ธ, ๋ฒŒ์ , ์„ธํƒ์‹ค ์ด์šฉ ๋“ฑ ๊ธฐ์ˆ™์‚ฌ ๊ทœ์ •์„ AI\n๊ฐ€ ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•˜๊ฒŒ ์•ˆ๋‚ดํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
color = DmsTheme.colorScheme.inverseSurface,
style = DmsTheme.typography.body3,
textAlign = TextAlign.Center,
)
}

@Composable
private fun ChatBotSuggestionQuestions(
onSuggestionClick: (String) -> Unit,
Expand Down
Loading
Loading