Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5d538e8
design :: λ°”ν…€ λ„€λΉ„κ²Œμ΄μ…˜ λ°” μ•„μ΄μ½˜ λ¦¬μ†ŒμŠ€ μΆ”κ°€
uson1004 Dec 20, 2025
7a050a5
feat :: DmsItemButton μ»΄ν¬λ„ŒνŠΈ κ΅¬ν˜„
uson1004 Dec 20, 2025
dfd3d38
refactor :: BaseStateViewModel κ°œμ„ 
uson1004 Dec 20, 2025
bc045dd
refactor :: MyPage λͺ¨λΈ 및 맀퍼 μˆ˜μ •
uson1004 Dec 20, 2025
85b797d
feat :: ν™ˆ ν™”λ©΄ κ΅¬ν˜„
uson1004 Dec 20, 2025
6e082c0
feat :: μ‹ μ²­ ν™”λ©΄ κ΅¬ν˜„
uson1004 Dec 20, 2025
3a1521c
feat :: λ§ˆμ΄νŽ˜μ΄μ§€ ν™”λ©΄ κ΅¬ν˜„
uson1004 Dec 20, 2025
cb524b9
feat :: λ°”ν…€ λ„€λΉ„κ²Œμ΄μ…˜ λ°” κ΅¬ν˜„
uson1004 Dec 20, 2025
d3129dd
feat :: DmsApp λ„€λΉ„κ²Œμ΄μ…˜ 톡합 및 λ°”ν…€λ°” 연동
uson1004 Dec 20, 2025
c9ed5dc
feat :: 이미지 μΆ”κ°€
uson1004 Dec 22, 2025
714abe9
feat :: Meal Screen κ΅¬ν˜„
uson1004 Dec 22, 2025
6a880db
feat :: μ»΄ν¬λ„ŒνŠΈ 및 λ·°λͺ¨λΈ κ΅¬ν˜„
uson1004 Dec 22, 2025
fb5f68b
feat :: NavHost MealScreen 등둝
uson1004 Dec 22, 2025
3873625
feat :: 탑 app bar, μΊ˜λ¦°λ” λ””μžμΈ μ‹œμŠ€ν…œ κ΅¬ν˜„
uson1004 Dec 22, 2025
680ed64
refactor :: paddingDefault 파일 λͺ¨λ“ˆ 경둜 λ””μžμΈ μ‹œμŠ€ν…œμœΌλ‘œ λ³€κ²½
uson1004 Dec 22, 2025
1cecdaa
refactor :: paddingDefault λ³€κ²½μœΌλ‘œ μΈν•œ 변경사항 적용
uson1004 Dec 22, 2025
1b0e25b
refactor :: LocalDate java.time으둜 λ³€κ²½
uson1004 Dec 22, 2025
28a511a
refactor :: λ°”ν…€ λ°” 인디케이터 투λͺ… μƒ‰μœΌλ‘œ λ³€κ²½
uson1004 Dec 22, 2025
7890207
refactor :: home screen icon μˆ˜μ •
uson1004 Dec 22, 2025
011b107
feat :: brush 적용
uson1004 Dec 22, 2025
5cad217
feat :: immutable 라이브러리 μΆ”κ°€
uson1004 Dec 22, 2025
8987417
refactor :: UI 일뢀 둜직 λ·°λͺ¨λΈλ‘œ μ΄μ „ν•˜μ—¬ κ°œμ„ 
uson1004 Dec 22, 2025
674c121
refactor :: μ»΄ν¬λ„ŒνŠΈ λ‚ μ§œ ν˜•μ‹ λ³€κ²½
uson1004 Dec 22, 2025
93853bb
refactor :: μ»΄ν¬λ„ŒνŠΈ 및 λ””μžμΈ μ‹œμŠ€ν…œ μ•ˆμ“°μ΄λŠ” μš”μ†Œ λ³€κ²½
uson1004 Dec 23, 2025
5471c61
feat :: manifest 파일 νŒŒμ΄μ–΄λ² μ΄μŠ€ 적용
uson1004 Dec 23, 2025
5591f6c
refactor :: meal repository κ΅¬ν˜„μ²΄ result 객체 λ°˜ν™˜
uson1004 Dec 23, 2025
89eea07
refactor :: java.time 라이브러리 sdk 21+ 지원
uson1004 Dec 23, 2025
3605f56
refactor :: minsdk 24+ 지원
uson1004 Dec 23, 2025
8665f98
refactor :: 슀크둀 λ˜λ„λ‘ 적용 / λ°”ν…€ λ°” ν‘œμ‹œ νŽ˜μ΄μ§€ λ³€κ²½
uson1004 Dec 23, 2025
93976dd
refactor :: meal screen νŒ¨λ”© κ°’ μˆ˜μ •
uson1004 Dec 23, 2025
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
5 changes: 5 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ android {
applicationIdSuffix = ".dev"
versionNameSuffix = "-dev"
buildConfigField("String", "ENVIRONMENT", "\"dev\"")

compileOptions {
isCoreLibraryDesugaringEnabled = true
}
Comment on lines +38 to +41
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Enable desugaring for prod flavor as well.

Desugaring is only enabled for the dev flavor, but the coreLibraryDesugaring dependency is added globally (Line 147). Since the PR migrates to java.time APIs and minSdk = 23 (API 23 < 26), the prod build will crash at runtime when using java.time classes without desugaring.

πŸ”Ž Proposed fix to enable desugaring for prod flavor
     create("prod") {
         dimension = "environment"
         buildConfigField("String", "ENVIRONMENT", "\"prod\"")
+
+        compileOptions {
+            isCoreLibraryDesugaringEnabled = true
+        }
     }

Committable suggestion skipped: line range outside the PR's diff.

πŸ€– Prompt for AI Agents
In app/build.gradle.kts around lines 38 to 41, desugaring is enabled only for
the dev flavor but the coreLibraryDesugaring dependency is added globally,
causing prod builds to crash when using java.time on minSdk 23; enable
desugaring for prod by moving or adding isCoreLibraryDesugaringEnabled = true to
a global compileOptions block under android (or add the same flag inside the
prod flavor block) so both flavors use core library desugaring.

}

create("prod") {
Expand Down Expand Up @@ -140,6 +144,7 @@ dependencies {
implementation(libs.material)

implementation(libs.javax.inject)
coreLibraryDesugaring(libs.desugar.jdk.libs)

implementation(libs.okhttp)
implementation(libs.okhttp.interceptor.logging)
Expand Down
20 changes: 20 additions & 0 deletions app/src/dev/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

<application
android:name="team.aliens.dms.android.app.DevApplication"
tools:replace="android:name">
Expand All @@ -24,5 +30,19 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service android:name=".android.app.service.DmsMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>

<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/primary" />
</application>
</manifest>
36 changes: 36 additions & 0 deletions app/src/dev/kotlin/team/aliens/dms/android/app/BottomMenu.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package team.aliens.dms.android.app

import androidx.annotation.DrawableRes
import androidx.navigation3.runtime.NavKey
import team.aliens.dms.android.core.designsystem.foundation.DmsIcon
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

sealed class BottomMenu(
val route: NavKey,
@DrawableRes val icon: Int,
@DrawableRes val selectedIcon: Int,
val title: String,
) {
data object Home : BottomMenu(
route = HomeScreenNav,
icon = DmsIcon.Home,
selectedIcon = DmsIcon.HomeFill,
title = "ν™ˆ",
)

data object Application : BottomMenu(
route = ApplicationScreenNav,
icon = DmsIcon.CheckCircle,
selectedIcon = DmsIcon.CheckCircleFill,
title = "μ‹ μ²­",
)

data object MyPage : BottomMenu(
route = MyPageScreenNav,
icon = DmsIcon.MyPage,
selectedIcon = DmsIcon.MyPageFill,
title = "λ§ˆμ΄νŽ˜μ΄μ§€",
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package team.aliens.dms.android.app

import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.BottomAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemColors
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.navigation3.runtime.NavKey
import team.aliens.dms.android.core.designsystem.DmsTheme
import team.aliens.dms.android.core.designsystem.labelB

private val bottomMenus = listOf(
BottomMenu.Home,
BottomMenu.Application,
BottomMenu.MyPage,
)

@Composable
fun BottomNavigationBar(
currentScreen: NavKey?,
onNavigate: (NavKey) -> Unit,
) {

BottomAppBar(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp)),
containerColor = DmsTheme.colorScheme.surfaceTint,
) {
bottomMenus.forEach { destination ->
val selected = currentScreen == destination.route
val color by animateColorAsState(
targetValue = if (selected) {
DmsTheme.colorScheme.inverseOnSurface
} else {
DmsTheme.colorScheme.scrim
},
)

NavigationBarItem(
selected = selected,
enabled = !selected,
onClick = {
onNavigate(destination.route)
},
colors = NavigationBarItemDefaults.colors(
indicatorColor = Color.Transparent,
),
icon = {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
modifier = Modifier.size(32.dp),
painter = painterResource(id = if (selected) destination.selectedIcon else destination.icon),
contentDescription = destination.title,
tint = color,
)
Text(
text = destination.title,
style = DmsTheme.typography.labelB,
color = color,
)
}
},
)
}
}
}
110 changes: 81 additions & 29 deletions app/src/dev/kotlin/team/aliens/dms/android/app/DmsApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ package team.aliens.dms.android.app

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Text
import androidx.compose.material3.windowsizeclass.WindowSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
Expand All @@ -15,16 +16,18 @@ import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.Serializable
import team.aliens.dms.android.core.designsystem.DmsTheme
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBar
import team.aliens.dms.android.core.designsystem.snackbar.DmsSnackBarVisuals
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
import team.aliens.dms.android.feature.meal.navigation.MealRoute
import team.aliens.dms.android.feature.onboarding.navigation.OnboardingRoute
import team.aliens.dms.android.feature.signin.navigation.SignInRoute

Expand All @@ -35,7 +38,16 @@ data object OnboardingScreenNav : NavKey
data object SignInScreenNav : NavKey

@Serializable
data object MainScreenNav : NavKey
data object HomeScreenNav : NavKey

@Serializable
data object MealScreenNav : NavKey

@Serializable
data object ApplicationScreenNav : NavKey

@Serializable
data object MyPageScreenNav : NavKey

@Composable
fun DmsApp(
Expand All @@ -48,11 +60,17 @@ fun DmsApp(
val isJwtAvailableState by isJwtAvailable.collectAsState()

val backStack = rememberNavBackStack(OnboardingScreenNav)
val currentScreen = backStack.lastOrNull()
val shouldShowBottomBar = currentScreen in listOf(
HomeScreenNav,
ApplicationScreenNav,
MyPageScreenNav,
)

LaunchedEffect(isOnboardingCompleted, isJwtAvailableState) {
val initialScreen = when {
!isOnboardingCompleted -> OnboardingScreenNav
isJwtAvailableState -> MainScreenNav
isJwtAvailableState -> HomeScreenNav
else -> SignInScreenNav
}

Expand All @@ -62,11 +80,29 @@ fun DmsApp(
}
}

Box(
modifier = Modifier.fillMaxWidth(),
) {
Scaffold(
bottomBar = {
if (shouldShowBottomBar) {
BottomNavigationBar(
currentScreen = currentScreen,
onNavigate = { destination ->
if (currentScreen != destination) {
backStack.removeAll {
it is HomeScreenNav ||
it is ApplicationScreenNav ||
it is MyPageScreenNav
}
backStack.add(destination)
}
}
)
}
}
) { paddingValues ->
NavDisplay(
modifier = Modifier.systemBarsPadding(),
modifier = Modifier
.padding(paddingValues)
.navigationBarsPadding(),
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
entryProvider = entryProvider {
Expand All @@ -80,35 +116,51 @@ fun DmsApp(
}
entry<SignInScreenNav> {
SignInRoute(
navigateToMain = { backStack.add(MainScreenNav) },
navigateToMain = {
backStack.clear()
backStack.add(HomeScreenNav)
},
navigateToSignUp = {},
onShowSnackBar = { snackBarType, message ->
appState.showSnackBar(snackBarType, message)
},
)
}
entry<MainScreenNav> {
Text(
text = "Main Screen (TODO)",
color = DmsTheme.colorScheme.onSurface,
entry<HomeScreenNav> {
HomeRoute(
onNavigateMeal = {
backStack.add(MealScreenNav)
}
)
}
entry<ApplicationScreenNav> {
ApplicationRoute()
}
entry<MyPageScreenNav> {
MyPageRoute()
}
entry<MealScreenNav> {
MealRoute(
onNavigateBack = { backStack.removeLastOrNull() }
)
}
},
)
SnackbarHost(
modifier = Modifier
.align(Alignment.TopCenter)
.statusBarsPadding()
.padding(top = 16.dp)
.zIndex(2f),
hostState = appState.snackBarHostState,
snackbar = {
val visuals = it.visuals as? DmsSnackBarVisuals ?: return@SnackbarHost
DmsSnackBar(
snackBarType = visuals.snackBarType,
message = visuals.message,
)
},
)
Box {
SnackbarHost(
modifier = Modifier
.statusBarsPadding()
.padding(top = 16.dp)
.align(Alignment.Center),
hostState = appState.snackBarHostState,
snackbar = {
val visuals = it.visuals as? DmsSnackBarVisuals ?: return@SnackbarHost
DmsSnackBar(
snackBarType = visuals.snackBarType,
message = visuals.message,
)
},
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.threeten.bp.ZoneOffset
import java.time.ZoneOffset
import javax.inject.Singleton

@Module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.threeten.bp.ZoneOffset
import java.time.ZoneOffset
import javax.inject.Singleton

@Module
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/ProjectProperties.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object ProjectProperties {
const val COMPILE_SDK = 36
const val MIN_SDK = 23
const val MIN_SDK = 24
const val TARGET_SDK = 36
const val VERSION_CODE = 28
const val VERSION_NAME = "1.5.3"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package team.aliens.dms.android.core.database.converter

import androidx.room.ProvidedTypeConverter
import androidx.room.TypeConverter
import org.threeten.bp.LocalDate
import org.threeten.bp.LocalDateTime
import org.threeten.bp.ZoneOffset
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneOffset
import team.aliens.dms.android.shared.date.toLocalDate
import team.aliens.dms.android.shared.date.toLocalDateTime
import javax.inject.Inject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import org.threeten.bp.LocalDate
import java.time.LocalDate
import team.aliens.dms.android.core.database.entity.MealEntity

@Dao
Expand Down
Loading
Loading