diff --git a/core/designsystem/src/main/res/drawable/ic_chevron_left.xml b/core/designsystem/src/main/res/drawable/ic_chevron_left.xml
new file mode 100644
index 00000000..e6bb3ca9
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_chevron_left.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_chevron_right.xml b/core/designsystem/src/main/res/drawable/ic_chevron_right.xml
new file mode 100644
index 00000000..24835127
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_chevron_right.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/designsystem/src/main/res/values/colors.xml b/core/designsystem/src/main/res/values/colors.xml
index f8c6127d..6e373029 100644
--- a/core/designsystem/src/main/res/values/colors.xml
+++ b/core/designsystem/src/main/res/values/colors.xml
@@ -7,4 +7,8 @@
#FF018786
#FF000000
#FFFFFFFF
-
\ No newline at end of file
+
+ #303F9F
+ #FCCA3E
+ #BEBEBE
+
diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml
index e7af56c5..3af6c6ee 100644
--- a/core/designsystem/src/main/res/values/strings.xml
+++ b/core/designsystem/src/main/res/values/strings.xml
@@ -3,4 +3,7 @@
네트워크 연결이 불안해요.\n잠시후 다시 이용해주세요.
이용에 불편을 드려 죄송합니다.\n잠시후 다시 이용해주세요.
알 수 없는 오류가 발생하였습니다.
+
+
+ Week mode
diff --git a/feature/home/build.gradle.kts b/feature/home/build.gradle.kts
index 56ba2c16..fe4c9cf0 100644
--- a/feature/home/build.gradle.kts
+++ b/feature/home/build.gradle.kts
@@ -14,5 +14,6 @@ dependencies {
libs.kotlinx.collections.immutable,
libs.androidx.core,
libs.timber,
+ libs.calendar.compose,
)
}
diff --git a/feature/home/src/main/kotlin/com/unifest/android/feature/home/Calendar.kt b/feature/home/src/main/kotlin/com/unifest/android/feature/home/Calendar.kt
new file mode 100644
index 00000000..fbeb2ca1
--- /dev/null
+++ b/feature/home/src/main/kotlin/com/unifest/android/feature/home/Calendar.kt
@@ -0,0 +1,358 @@
+package com.unifest.android.feature.home
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Checkbox
+import androidx.compose.material3.CheckboxDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateListOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
+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.graphics.painter.Painter
+import androidx.compose.ui.res.colorResource
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.Role
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.kizitonwose.calendar.compose.CalendarState
+import com.kizitonwose.calendar.compose.HorizontalCalendar
+import com.kizitonwose.calendar.compose.WeekCalendar
+import com.kizitonwose.calendar.compose.rememberCalendarState
+import com.kizitonwose.calendar.compose.weekcalendar.WeekCalendarState
+import com.kizitonwose.calendar.compose.weekcalendar.rememberWeekCalendarState
+import com.kizitonwose.calendar.core.DayPosition
+import com.kizitonwose.calendar.core.WeekDayPosition
+import com.kizitonwose.calendar.core.atStartOfMonth
+import com.kizitonwose.calendar.core.daysOfWeek
+import com.kizitonwose.calendar.core.nextMonth
+import com.kizitonwose.calendar.core.previousMonth
+import com.kizitonwose.calendar.core.yearMonth
+import com.unifest.android.core.designsystem.R
+import com.unifest.android.core.designsystem.theme.UnifestTheme
+import kotlinx.coroutines.launch
+import java.time.DayOfWeek
+import java.time.LocalDate
+import java.time.YearMonth
+
+@Composable
+fun Calendar(adjacentMonths: Long = 500) {
+ val currentDate = remember { LocalDate.now() }
+ val currentMonth = remember(currentDate) { currentDate.yearMonth }
+ val startMonth = remember(currentDate) { currentMonth.minusMonths(adjacentMonths) }
+ val endMonth = remember(currentDate) { currentMonth.plusMonths(adjacentMonths) }
+ val selections = remember { mutableStateListOf() }
+ val daysOfWeek = remember { daysOfWeek() }
+
+ var isWeekMode by remember { mutableStateOf(false) }
+ var isAnimating by remember { mutableStateOf(false) }
+ val coroutineScope = rememberCoroutineScope()
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(Color.White),
+ ) {
+ val monthState = rememberCalendarState(
+ startMonth = startMonth,
+ endMonth = endMonth,
+ firstVisibleMonth = currentMonth,
+ firstDayOfWeek = daysOfWeek.first(),
+ )
+ val weekState = rememberWeekCalendarState(
+ startDate = startMonth.atStartOfMonth(),
+ endDate = endMonth.atEndOfMonth(),
+ firstVisibleWeekDate = currentDate,
+ firstDayOfWeek = daysOfWeek.first(),
+ )
+ CalendarTitle(
+ isWeekMode = isWeekMode,
+ monthState = monthState,
+ weekState = weekState,
+ isAnimating = isAnimating,
+ )
+ CalendarHeader(daysOfWeek = daysOfWeek)
+ AnimatedVisibility(visible = !isWeekMode) {
+ HorizontalCalendar(
+ state = monthState,
+ dayContent = { day ->
+ val isSelectable = day.position == DayPosition.MonthDate
+ Day(
+ day.date,
+ isSelected = isSelectable && selections.contains(day.date),
+ isSelectable = isSelectable,
+ ) { clicked ->
+ if (selections.contains(clicked)) {
+ selections.remove(clicked)
+ } else {
+ selections.add(clicked)
+ }
+ }
+ },
+ )
+ }
+ AnimatedVisibility(visible = isWeekMode) {
+ WeekCalendar(
+ state = weekState,
+ dayContent = { day ->
+ val isSelectable = day.position == WeekDayPosition.RangeDate
+ Day(
+ day.date,
+ isSelected = isSelectable && selections.contains(day.date),
+ isSelectable = isSelectable,
+ ) { clicked ->
+ if (selections.contains(clicked)) {
+ selections.remove(clicked)
+ } else {
+ selections.add(clicked)
+ }
+ }
+ },
+ )
+ }
+ Spacer(modifier = Modifier.weight(1f))
+ WeekModeToggle(
+ modifier = Modifier.align(Alignment.CenterHorizontally),
+ isWeekMode = isWeekMode,
+ ) { weekMode ->
+ isAnimating = true
+ isWeekMode = weekMode
+ coroutineScope.launch {
+ if (weekMode) {
+ val targetDate = monthState.firstVisibleMonth.weekDays.last().last().date
+ weekState.scrollToWeek(targetDate)
+ weekState.animateScrollToWeek(targetDate) // Trigger a layout pass for title update
+ } else {
+ val targetMonth = weekState.firstVisibleWeek.days.first().date.yearMonth
+ monthState.scrollToMonth(targetMonth)
+ monthState.animateScrollToMonth(targetMonth) // Trigger a layout pass for title update
+ }
+ isAnimating = false
+ }
+ }
+ }
+}
+
+@Composable
+fun MonthAndWeekCalendarTitle(
+ isWeekMode: Boolean,
+ currentMonth: YearMonth,
+ monthState: CalendarState,
+ weekState: WeekCalendarState,
+) {
+ val coroutineScope = rememberCoroutineScope()
+ SimpleCalendarTitle(
+ modifier = Modifier.padding(vertical = 10.dp, horizontal = 8.dp),
+ currentMonth = currentMonth,
+ goToPrevious = {
+ coroutineScope.launch {
+ if (isWeekMode) {
+ val targetDate = weekState.firstVisibleWeek.days.first().date.minusDays(1)
+ weekState.animateScrollToWeek(targetDate)
+ } else {
+ val targetMonth = monthState.firstVisibleMonth.yearMonth.previousMonth
+ monthState.animateScrollToMonth(targetMonth)
+ }
+ }
+ },
+ goToNext = {
+ coroutineScope.launch {
+ if (isWeekMode) {
+ val targetDate = weekState.firstVisibleWeek.days.last().date.plusDays(1)
+ weekState.animateScrollToWeek(targetDate)
+ } else {
+ val targetMonth = monthState.firstVisibleMonth.yearMonth.nextMonth
+ monthState.animateScrollToMonth(targetMonth)
+ }
+ }
+ },
+ )
+}
+
+@Composable
+fun SimpleCalendarTitle(
+ modifier: Modifier,
+ currentMonth: YearMonth,
+ goToPrevious: () -> Unit,
+ goToNext: () -> Unit,
+) {
+ Row(
+ modifier = modifier.height(40.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ CalendarNavigationIcon(
+ icon = painterResource(id = R.drawable.ic_chevron_left),
+ contentDescription = "Previous",
+ onClick = goToPrevious,
+ )
+ Text(
+ modifier = Modifier.weight(1f),
+ text = currentMonth.displayText(),
+ fontSize = 22.sp,
+ textAlign = TextAlign.Center,
+ fontWeight = FontWeight.Medium,
+ )
+ CalendarNavigationIcon(
+ icon = painterResource(id = R.drawable.ic_chevron_right),
+ contentDescription = "Next",
+ onClick = goToNext,
+ )
+ }
+}
+
+@Composable
+private fun CalendarNavigationIcon(
+ icon: Painter,
+ contentDescription: String,
+ onClick: () -> Unit,
+) = Box(
+ modifier = Modifier
+ .fillMaxHeight()
+ .aspectRatio(1f)
+ .clip(shape = CircleShape)
+ .clickable(role = Role.Button, onClick = onClick),
+) {
+ Icon(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(4.dp)
+ .align(Alignment.Center),
+ painter = icon,
+ contentDescription = contentDescription,
+ )
+}
+
+@Composable
+private fun CalendarTitle(
+ isWeekMode: Boolean,
+ monthState: CalendarState,
+ weekState: WeekCalendarState,
+ isAnimating: Boolean,
+) {
+ val visibleMonth = rememberFirstVisibleMonthAfterScroll(monthState)
+ val visibleWeek = rememberFirstVisibleWeekAfterScroll(weekState)
+ val visibleWeekMonth = visibleWeek.days.first().date.yearMonth
+ // Track animation state to prevent updating the title too early before
+ // the correct value is available (after the animation).
+ val currentMonth = if (isWeekMode) {
+ if (isAnimating) visibleMonth.yearMonth else visibleWeekMonth
+ } else {
+ if (isAnimating) visibleWeekMonth else visibleMonth.yearMonth
+ }
+ MonthAndWeekCalendarTitle(
+ isWeekMode = isWeekMode,
+ currentMonth = currentMonth,
+ monthState = monthState,
+ weekState = weekState,
+ )
+}
+
+@Composable
+fun CalendarHeader(daysOfWeek: List) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth(),
+ ) {
+ for (dayOfWeek in daysOfWeek) {
+ Text(
+ modifier = Modifier.weight(1f),
+ textAlign = TextAlign.Center,
+ fontSize = 15.sp,
+ text = dayOfWeek.displayText(),
+ fontWeight = FontWeight.Medium,
+ )
+ }
+ }
+}
+
+@Composable
+fun Day(
+ day: LocalDate,
+ isSelected: Boolean,
+ isSelectable: Boolean,
+ onClick: (LocalDate) -> Unit,
+) {
+ Box(
+ modifier = Modifier
+ .aspectRatio(1f) // This is important for square-sizing!
+ .padding(6.dp)
+ .clip(CircleShape)
+ .background(color = if (isSelected) colorResource(R.color.example_1_selection_color) else Color.Transparent)
+ .clickable(
+ enabled = isSelectable,
+ showRipple = !isSelected,
+ onClick = { onClick(day) },
+ ),
+ contentAlignment = Alignment.Center,
+ ) {
+ val textColor = when {
+ isSelected -> Color.White
+ isSelectable -> Color.Unspecified
+ else -> colorResource(R.color.inactive_text_color)
+ }
+ Text(
+ text = day.dayOfMonth.toString(),
+ color = textColor,
+ fontSize = 14.sp,
+ )
+ }
+}
+
+@Composable
+fun WeekModeToggle(
+ modifier: Modifier,
+ isWeekMode: Boolean,
+ weekModeToggled: (isWeekMode: Boolean) -> Unit,
+) {
+ // We want the entire content to be clickable, not just the checkbox.
+ Row(
+ modifier = modifier
+ .padding(10.dp)
+ .clip(MaterialTheme.shapes.small)
+ .clickable { weekModeToggled(!isWeekMode) }
+ .padding(10.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(6.dp, Alignment.CenterHorizontally),
+ ) {
+ Checkbox(
+ checked = isWeekMode,
+ onCheckedChange = null, // Check is handled by parent.
+ colors = CheckboxDefaults.colors(checkedColor = colorResource(R.color.example_1_selection_color)),
+ )
+ Text(text = stringResource(R.string.week_mode))
+ }
+}
+
+@Preview
+@Composable
+private fun CalendarPreview() {
+ UnifestTheme {
+ Calendar()
+ }
+}
diff --git a/feature/home/src/main/kotlin/com/unifest/android/feature/home/HomeScreen.kt b/feature/home/src/main/kotlin/com/unifest/android/feature/home/HomeScreen.kt
index 66934ec2..c9260d54 100644
--- a/feature/home/src/main/kotlin/com/unifest/android/feature/home/HomeScreen.kt
+++ b/feature/home/src/main/kotlin/com/unifest/android/feature/home/HomeScreen.kt
@@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
-import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -31,7 +30,7 @@ internal fun HomeScreen(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
- Text("Home Screen")
+ Calendar()
}
}
diff --git a/feature/home/src/main/kotlin/com/unifest/android/feature/home/Utils.kt b/feature/home/src/main/kotlin/com/unifest/android/feature/home/Utils.kt
new file mode 100644
index 00000000..d9bd5582
--- /dev/null
+++ b/feature/home/src/main/kotlin/com/unifest/android/feature/home/Utils.kt
@@ -0,0 +1,161 @@
+package com.unifest.android.feature.home
+
+import androidx.compose.foundation.LocalIndication
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.snapshotFlow
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.composed
+import androidx.compose.ui.semantics.Role
+import com.kizitonwose.calendar.compose.CalendarLayoutInfo
+import com.kizitonwose.calendar.compose.CalendarState
+import com.kizitonwose.calendar.compose.weekcalendar.WeekCalendarState
+import com.kizitonwose.calendar.core.CalendarMonth
+import com.kizitonwose.calendar.core.Week
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterNotNull
+import java.time.DayOfWeek
+import java.time.Month
+import java.time.YearMonth
+import java.time.format.TextStyle
+import java.util.Locale
+
+fun Modifier.clickable(
+ enabled: Boolean = true,
+ showRipple: Boolean = true,
+ onClickLabel: String? = null,
+ role: Role? = null,
+ onClick: () -> Unit,
+): Modifier = composed {
+ clickable(
+ interactionSource = remember { MutableInteractionSource() },
+ indication = if (showRipple) LocalIndication.current else null,
+ enabled = enabled,
+ onClickLabel = onClickLabel,
+ role = role,
+ onClick = onClick,
+ )
+}
+
+/**
+ * Alternative way to find the first fully visible month in the layout.
+ *
+ * @see [rememberFirstVisibleMonthAfterScroll]
+ * @see [rememberFirstMostVisibleMonth]
+ */
+@Composable
+fun rememberFirstCompletelyVisibleMonth(state: CalendarState): CalendarMonth {
+ val visibleMonth = remember(state) { mutableStateOf(state.firstVisibleMonth) }
+ // Only take non-null values as null will be produced when the
+ // list is mid-scroll as no index will be completely visible.
+ LaunchedEffect(state) {
+ snapshotFlow { state.layoutInfo.completelyVisibleMonths.firstOrNull() }
+ .filterNotNull()
+ .collect { month -> visibleMonth.value = month }
+ }
+ return visibleMonth.value
+}
+
+/**
+ * Returns the first visible month in a paged calendar **after** scrolling stops.
+ *
+ * @see [rememberFirstCompletelyVisibleMonth]
+ * @see [rememberFirstMostVisibleMonth]
+ */
+@Composable
+fun rememberFirstVisibleMonthAfterScroll(state: CalendarState): CalendarMonth {
+ val visibleMonth = remember(state) { mutableStateOf(state.firstVisibleMonth) }
+ LaunchedEffect(state) {
+ snapshotFlow { state.isScrollInProgress }
+ .filter { scrolling -> !scrolling }
+ .collect { visibleMonth.value = state.firstVisibleMonth }
+ }
+ return visibleMonth.value
+}
+
+/**
+ * Find first visible week in a paged week calendar **after** scrolling stops.
+ */
+@Composable
+fun rememberFirstVisibleWeekAfterScroll(state: WeekCalendarState): Week {
+ val visibleWeek = remember(state) { mutableStateOf(state.firstVisibleWeek) }
+ LaunchedEffect(state) {
+ snapshotFlow { state.isScrollInProgress }
+ .filter { scrolling -> !scrolling }
+ .collect { visibleWeek.value = state.firstVisibleWeek }
+ }
+ return visibleWeek.value
+}
+
+/**
+ * Find the first month on the calendar visible up to the given [viewportPercent] size.
+ *
+ * @see [rememberFirstCompletelyVisibleMonth]
+ * @see [rememberFirstVisibleMonthAfterScroll]
+ */
+@Composable
+fun rememberFirstMostVisibleMonth(
+ state: CalendarState,
+ viewportPercent: Float = 50f,
+): CalendarMonth {
+ val visibleMonth = remember(state) { mutableStateOf(state.firstVisibleMonth) }
+ LaunchedEffect(state) {
+ snapshotFlow { state.layoutInfo.firstMostVisibleMonth(viewportPercent) }
+ .filterNotNull()
+ .collect { month -> visibleMonth.value = month }
+ }
+ return visibleMonth.value
+}
+
+private val CalendarLayoutInfo.completelyVisibleMonths: List
+ get() {
+ val visibleItemsInfo = this.visibleMonthsInfo.toMutableList()
+ return if (visibleItemsInfo.isEmpty()) {
+ emptyList()
+ } else {
+ val lastItem = visibleItemsInfo.last()
+ val viewportSize = this.viewportEndOffset + this.viewportStartOffset
+ if (lastItem.offset + lastItem.size > viewportSize) {
+ visibleItemsInfo.removeLast()
+ }
+ val firstItem = visibleItemsInfo.firstOrNull()
+ if (firstItem != null && firstItem.offset < this.viewportStartOffset) {
+ visibleItemsInfo.removeFirst()
+ }
+ visibleItemsInfo.map { it.month }
+ }
+ }
+
+private fun CalendarLayoutInfo.firstMostVisibleMonth(viewportPercent: Float = 50f): CalendarMonth? {
+ return if (visibleMonthsInfo.isEmpty()) {
+ null
+ } else {
+ val viewportSize = (viewportEndOffset + viewportStartOffset) * viewportPercent / 100f
+ visibleMonthsInfo.firstOrNull { itemInfo ->
+ if (itemInfo.offset < 0) {
+ itemInfo.offset + itemInfo.size >= viewportSize
+ } else {
+ itemInfo.size - itemInfo.offset >= viewportSize
+ }
+ }?.month
+ }
+}
+
+fun YearMonth.displayText(short: Boolean = false): String {
+ return "${this.year} ${this.month.displayText(short = short)}"
+}
+
+fun Month.displayText(short: Boolean = true): String {
+ val style = if (short) TextStyle.SHORT else TextStyle.FULL
+ return getDisplayName(style, Locale.KOREA)
+}
+
+fun DayOfWeek.displayText(uppercase: Boolean = false): String {
+ return getDisplayName(TextStyle.SHORT, Locale.KOREA).let { value ->
+ if (uppercase) value.uppercase(Locale.KOREA) else value
+ }
+}
diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainActivity.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainActivity.kt
index 7e194933..36a9aaa3 100644
--- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainActivity.kt
+++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainActivity.kt
@@ -3,14 +3,12 @@ package com.unifest.android.feature.main
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
-import androidx.activity.enableEdgeToEdge
import com.unifest.android.core.designsystem.theme.UnifestTheme
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
- enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
val navigator: MainNavController = rememberMainNavController()
diff --git a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt
index 053bb332..7c99271d 100644
--- a/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt
+++ b/feature/main/src/main/kotlin/com/unifest/android/feature/main/MainScreen.kt
@@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.selection.selectable
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
-import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
@@ -107,7 +106,7 @@ internal fun MainScreen(
)
},
snackbarHost = { SnackbarHost(snackBarHostState) },
- containerColor = MaterialTheme.colorScheme.background,
+ containerColor = Color.White,
)
}
@@ -119,7 +118,7 @@ private fun MainBottomBar(
onTabSelected: (MainTab) -> Unit,
) {
if (visible) {
- Box(modifier = Modifier.background(MaterialTheme.colorScheme.background)) {
+ Box(modifier = Modifier.background(Color.White)) {
Column {
HorizontalDivider(color = Color(0xFFEBEBEB))
Row(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a45e1074..e0fc3a04 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -45,12 +45,7 @@ compose-stable-marker = "1.0.3"
compose-investigator = "1.5.11-0.2.1"
landscapist = "2.3.2"
balloon = "1.6.4"
-
-junit = "4.13.2"
-androidx-junit = "1.1.5"
-espresso-core = "3.5.1"
-appcompat = "1.6.1"
-material = "1.11.0"
+calendar-compose = "2.5.0"
[libraries]
@@ -104,12 +99,7 @@ accompanist-webview = { group = "com.google.accompanist", name = "accompanist-we
compose-stable-marker = { group = "com.github.skydoves", name = "compose-stable-marker", version.ref = "compose-stable-marker" }
landscapist-coil = { group = "com.github.skydoves", name = "landscapist-coil", version.ref = "landscapist" }
ballon = { group = "com.github.skydoves", name = "balloon", version.ref = "balloon" }
-
-junit = { group = "junit", name = "junit", version.ref = "junit" }
-androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-junit" }
-androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espresso-core" }
-androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+calendar-compose = { group = "com.kizitonwose.calendar", name = "compose", version.ref = "calendar-compose"}
[plugins]