Skip to content

Commit

Permalink
[FEAT/#45] AlarmAddEditScreen에 AlarmSnoozeBottomSheet 연동
Browse files Browse the repository at this point in the history
  • Loading branch information
DongChyeon committed Jan 19, 2025
1 parent c14383d commit ff07fb2
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.yapp.common.navigation.destination.OnboardingDestination
import com.yapp.common.navigation.destination.HomeDestination
import com.yapp.common.navigation.destination.TopLevelDestination

class OrbitNavigator(
val navController: NavHostController,
) {
val startDestination = OnboardingDestination.Route.route
val startDestination = HomeDestination.Route.route

private val currentDestination: NavDestination?
@Composable get() = navController
Expand Down
52 changes: 49 additions & 3 deletions core/ui/src/main/java/com/yapp/ui/component/OrbitBottomSheet.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package com.yapp.ui.component

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.SheetState
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -54,12 +61,51 @@ fun OrbitBottomSheet(
@Preview
@Composable
fun OrbitBottomSheetPreview() {
var isSheetOpen by rememberSaveable { mutableStateOf(false) }
var isSheetOpen by rememberSaveable { mutableStateOf(true) }
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val scope = rememberCoroutineScope()

OrbitTheme {
Button(
onClick = {
scope.launch {
sheetState.show()
}.invokeOnCompletion {
if (!isSheetOpen) {
isSheetOpen = true
}
}
},
) {
Text("Toggle Bottom Sheet")
}

OrbitBottomSheet(
isSheetOpen = true,
isSheetOpen = isSheetOpen,
sheetState = sheetState,
onDismissRequest = { isSheetOpen = !isSheetOpen },
content = {},
content = {
Box(
modifier = Modifier
.fillMaxWidth()
.height(600.dp),
contentAlignment = Alignment.Center,
) {
Button(
onClick = {
scope.launch {
sheetState.hide()
}.invokeOnCompletion {
if (isSheetOpen) {
isSheetOpen = false
}
}
},
) {
Text("Toggle Bottom Sheet")
}
}
},
)
}
}
27 changes: 15 additions & 12 deletions feature/home/src/main/java/com/yapp/alarm/AlarmAddEditContract.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import com.yapp.ui.base.UiState
sealed class AlarmAddEditContract {

data class State(
val timeState: AlarmTimeState = AlarmTimeState(), // 알람 시간 관련 상태
val daySelectionState: AlarmDaySelectionState = AlarmDaySelectionState(), // 요일 선택 상태
val holidayState: AlarmHolidayState = AlarmHolidayState(), // 휴일 관련 상태
val snoozeState: AlarmSnoozeState = AlarmSnoozeState(), // 스누즈 관련 상태
val timeState: AlarmTimeState = AlarmTimeState(),
val daySelectionState: AlarmDaySelectionState = AlarmDaySelectionState(),
val holidayState: AlarmHolidayState = AlarmHolidayState(),
val snoozeState: AlarmSnoozeState = AlarmSnoozeState(),
) : UiState

data class AlarmTimeState(
val currentAmPm: String = "오전",
val currentHour: Int = 6,
val currentHour: Int = 1,
val currentMinute: Int = 0,
val alarmMessage: String = "",
)
Expand All @@ -31,9 +31,12 @@ sealed class AlarmAddEditContract {
)

data class AlarmSnoozeState(
val isSnoozeEnabled: Boolean = true, // 스누즈 활성화 여부
val snoozeIntervalIndex: Int = 2, // 선택된 간격 인덱스
val snoozeCountIndex: Int = 1, // 선택된 횟수 인덱스
val isSnoozeEnabled: Boolean = true,
val snoozeIntervalIndex: Int = 2,
val snoozeCountIndex: Int = 1,
val isBottomSheetOpen: Boolean = false,
val snoozeIntervals: List<String> = listOf("1분", "3분", "5분", "10분", "15분"),
val snoozeCounts: List<String> = listOf("1회", "3회", "5회", "10회", "무한"),
)

sealed class Action {
Expand All @@ -44,10 +47,10 @@ sealed class AlarmAddEditContract {
data object ToggleWeekendsChecked : Action()
data class ToggleDaySelection(val day: AlarmDay) : Action()
data object ToggleDisableHolidayChecked : Action()
data object OpenSnoozeSettingBottomSheet : Action()
data object ToggleSnoozeEnabled : Action() // 스누즈 활성화 상태 토글
data class UpdateSnoozeInterval(val index: Int) : Action() // 간격 변경
data class UpdateSnoozeCount(val index: Int) : Action() // 횟수 변경
data object ToggleSnoozeSettingBottomSheetOpen : Action()
data object ToggleSnoozeEnabled : Action()
data class UpdateSnoozeInterval(val index: Int) : Action()
data class UpdateSnoozeCount(val index: Int) : Action()
}

sealed class SideEffect : com.yapp.ui.base.SideEffect {
Expand Down
50 changes: 47 additions & 3 deletions feature/home/src/main/java/com/yapp/alarm/AlarmAddEditScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
Expand All @@ -29,13 +32,15 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.yapp.alarm.component.AlarmCheckItem
import com.yapp.alarm.component.AlarmDayButton
import com.yapp.alarm.component.bottomsheet.AlarmSnoozeBottomSheet
import com.yapp.common.navigation.OrbitNavigator
import com.yapp.designsystem.theme.OrbitTheme
import com.yapp.ui.component.button.OrbitButton
import com.yapp.ui.component.switch.OrbitSwitch
import com.yapp.ui.component.timepicker.OrbitPicker
import com.yapp.ui.lifecycle.LaunchedEffectWithLifecycle
import feature.home.R
import kotlinx.coroutines.launch

@Composable
fun AlarmAddEditRoute(
Expand Down Expand Up @@ -68,12 +73,16 @@ fun AlarmAddEditRoute(
)
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AlarmAddEditScreen(
stateProvider: () -> AlarmAddEditContract.State,
eventDispatcher: (AlarmAddEditContract.Action) -> Unit,
) {
val state = stateProvider()
val snoozeState = state.snoozeState
val bottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val scope = rememberCoroutineScope()

Column(
modifier = Modifier.fillMaxSize(),
Expand Down Expand Up @@ -111,6 +120,32 @@ fun AlarmAddEditScreen(
.fillMaxWidth(),
)
}

AlarmSnoozeBottomSheet(
isSnoozeEnabled = snoozeState.isSnoozeEnabled,
snoozeIntervalIndex = snoozeState.snoozeIntervalIndex,
snoozeCountIndex = snoozeState.snoozeCountIndex,
snoozeIntervals = snoozeState.snoozeIntervals,
snoozeCounts = snoozeState.snoozeCounts,
onSnoozeToggle = { eventDispatcher(AlarmAddEditContract.Action.ToggleSnoozeEnabled) },
onIntervalSelected = { index -> eventDispatcher(AlarmAddEditContract.Action.UpdateSnoozeInterval(index)) },
onCountSelected = { index -> eventDispatcher(AlarmAddEditContract.Action.UpdateSnoozeCount(index)) },
onComplete = {
scope.launch {
bottomSheetState.hide()
}.invokeOnCompletion {
eventDispatcher(AlarmAddEditContract.Action.ToggleSnoozeSettingBottomSheetOpen)
}
},
isSheetOpen = snoozeState.isBottomSheetOpen,
onDismiss = {
scope.launch {
bottomSheetState.hide()
}.invokeOnCompletion {
eventDispatcher(AlarmAddEditContract.Action.ToggleSnoozeSettingBottomSheetOpen)
}
},
)
}

@Composable
Expand Down Expand Up @@ -174,10 +209,19 @@ private fun AlarmAddEditSettingsSection(
.padding(horizontal = 20.dp)
.background(OrbitTheme.colors.gray_700),
)

AlarmAddEditSettingItem(
label = "알람 미루기",
description = "5분, 무한",
onClick = { processAction(AlarmAddEditContract.Action.OpenSnoozeSettingBottomSheet) },
label = stringResource(id = R.string.alarm_add_edit_alarm_snooze),
description = if (state.snoozeState.isSnoozeEnabled) {
stringResource(
id = R.string.alarm_add_edit_alarm_selected_option,
state.snoozeState.snoozeIntervals[state.snoozeState.snoozeIntervalIndex],
state.snoozeState.snoozeCounts[state.snoozeState.snoozeCountIndex],
)
} else {
stringResource(id = R.string.alarm_add_edit_alarm_selected_option_none)
},
onClick = { processAction(AlarmAddEditContract.Action.ToggleSnoozeSettingBottomSheetOpen) },
)
Spacer(
modifier = Modifier.fillMaxWidth()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AlarmAddEditViewModel @Inject constructor() : BaseViewModel<AlarmAddEditCo
is AlarmAddEditContract.Action.ToggleSnoozeEnabled -> toggleSnoozeEnabled()
is AlarmAddEditContract.Action.UpdateSnoozeInterval -> updateSnoozeInterval(action.index)
is AlarmAddEditContract.Action.UpdateSnoozeCount -> updateSnoozeCount(action.index)
is AlarmAddEditContract.Action.OpenSnoozeSettingBottomSheet -> openSnoozeSettingBottomSheet()
is AlarmAddEditContract.Action.ToggleSnoozeSettingBottomSheetOpen -> toggleSnoozeSettingBottomSheet()
}
}
}
Expand Down Expand Up @@ -146,6 +146,13 @@ class AlarmAddEditViewModel @Inject constructor() : BaseViewModel<AlarmAddEditCo
}
}

private fun toggleSnoozeSettingBottomSheet() {
val newSnoozeState = currentState.snoozeState.copy(isBottomSheetOpen = !currentState.snoozeState.isBottomSheetOpen)
updateState {
copy(snoozeState = newSnoozeState)
}
}

private fun updateSnoozeInterval(index: Int) {
val newSnoozeState = currentState.snoozeState.copy(snoozeIntervalIndex = index)
updateState {
Expand All @@ -160,10 +167,6 @@ class AlarmAddEditViewModel @Inject constructor() : BaseViewModel<AlarmAddEditCo
}
}

private fun openSnoozeSettingBottomSheet() {
// TODO: open snooze setting bottom sheet
}

private fun getAlarmMessage(amPm: String, hour: Int, minute: Int, selectedDays: Set<AlarmDay>): String {
val now = java.time.LocalDateTime.now()
val alarmHour = convertTo24HourFormat(amPm, hour)
Expand Down
Loading

0 comments on commit ff07fb2

Please sign in to comment.