Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REFACTOR/#246] 달력 로직 대폭 수정 #248

Merged
merged 17 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import java.time.YearMonth
@Composable
fun CalendarTopAppBar(
date: YearMonth,
isWeekExpanded: Boolean,
isListExpanded: Boolean,
onListButtonClicked: () -> Unit,
onMonthNavigationButtonClicked: (Int) -> Unit,
Expand All @@ -59,28 +58,26 @@ fun CalendarTopAppBar(
modifier = Modifier.align(Alignment.Center),
verticalAlignment = Alignment.CenterVertically
) {
if(!isWeekExpanded || isListExpanded) {
Icon(
painter = painterResource(id = R.drawable.ic_calendar_previous),
contentDescription = stringResource(id = R.string.calendar_button_description_previous),
tint = TerningMain,
modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(-1) }
)
}

Text(
text = LocalDate.of(date.year, date.month, 1).getStringAsTitle(),
style = TerningTheme.typography.title2,
color = Black,
modifier = Modifier.padding(horizontal = 8.dp)
)
if(!isWeekExpanded || isListExpanded) {
Icon(
painter = painterResource(id = R.drawable.ic_calendar_next),
contentDescription = stringResource(id = R.string.calendar_button_description_next),
tint = TerningMain,
modifier = Modifier.noRippleClickable { onMonthNavigationButtonClicked(1) }
)
}

}
Box(
modifier = Modifier
Expand Down Expand Up @@ -109,8 +106,6 @@ fun CalendarTopBarPreview() {
CalendarTopAppBar(
date = YearMonth.now(),
isListExpanded = false,
isWeekExpanded = false
,
onListButtonClicked = {},
onMonthNavigationButtonClicked = {}
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.terning.feature.calendar.calendar

import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally
Expand All @@ -8,11 +9,10 @@ import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
Expand All @@ -27,12 +27,13 @@ import com.terning.core.designsystem.theme.Grey200
import com.terning.core.designsystem.theme.White
import com.terning.feature.calendar.calendar.component.ScreenTransition
import com.terning.feature.calendar.calendar.component.WeekDaysHeader
import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getLocalDateByPage
import com.terning.feature.calendar.calendar.model.CalendarModel.Companion.getYearMonthByPage
import com.terning.feature.calendar.calendar.model.CalendarUiState
import com.terning.feature.calendar.calendar.model.LocalPagerState
import com.terning.feature.calendar.list.CalendarListRoute
import com.terning.feature.calendar.month.CalendarMonthRoute
import com.terning.feature.calendar.week.CalendarWeekRoute
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import java.time.LocalDate

Expand All @@ -49,119 +50,119 @@ fun CalendarRoute(
modifier = modifier,
uiState = uiState,
navigateToAnnouncement = navigateToAnnouncement,
onClickNewDate = viewModel::onSelectNewDate,
updateSelectedDate = viewModel::updateSelectedDate,
updatePage = viewModel::updatePage,
disableListVisibility = { viewModel.updateListVisibility(false) },
disableWeekVisibility = { viewModel.updateSelectedDate(uiState.selectedDate) },
onClickListButton = {
viewModel.updateListVisibility(!uiState.isListEnabled)
if (uiState.isWeekEnabled) {
viewModel.updateWeekVisibility(false)
}
}
disableWeekVisibility = { viewModel.updateWeekVisibility(false) },
onClickListButton = { viewModel.updateListVisibility(!uiState.isListEnabled) }
)
}

@Composable
private fun CalendarScreen(
uiState: CalendarUiState,
navigateToAnnouncement: (Long) -> Unit,
onClickNewDate: (LocalDate) -> Unit,
updateSelectedDate: (LocalDate) -> Unit,
disableListVisibility: () -> Unit,
disableWeekVisibility: () -> Unit,
updatePage: (Int) -> Unit,
onClickListButton: () -> Unit,
modifier: Modifier = Modifier,
) {
val coroutineScope = rememberCoroutineScope()

val listState = rememberLazyListState(
initialFirstVisibleItemIndex = uiState.calendarModel.initialPage
val pagerState = rememberPagerState(
Copy link
Member

Choose a reason for hiding this comment

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

pagerState.... 신기방기...

initialPage = uiState.calendarModel.initialPage,
pageCount = { uiState.calendarModel.pageCount }
)

LaunchedEffect(key1 = listState) {
snapshotFlow { listState.firstVisibleItemIndex }
.distinctUntilChanged()
.collect {
updatePage(listState.firstVisibleItemIndex)
LaunchedEffect(key1 = pagerState, key2 = uiState.selectedDate) {
snapshotFlow { pagerState.currentPage }
.collect { current ->
val date = getLocalDateByPage(current)
val newDate = LocalDate.of(date.year, date.month, uiState.selectedDate.dayOfMonth)
updateSelectedDate(newDate)
}
}

Column(
modifier = modifier,
){
CalendarTopAppBar(
date = getYearMonthByPage(uiState.currentPage),
isListExpanded = uiState.isListEnabled,
isWeekExpanded = uiState.isWeekEnabled,
onListButtonClicked = onClickListButton,
onMonthNavigationButtonClicked = { direction ->
coroutineScope.launch {
listState.animateScrollToItem(
index = listState.firstVisibleItemIndex + direction,
)
CompositionLocalProvider(
LocalPagerState provides pagerState
Comment on lines +88 to +89
Copy link
Contributor

Choose a reason for hiding this comment

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

우와,..이것뭐예요....헐

Copy link
Member Author

Choose a reason for hiding this comment

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

특정 컴포저블의 하위 컴포저블에서 변수를 전역으로 사용할 수 있게끔 해주는 CompositionLocal입니다!
PagerState로 이전하면서 매 컴포저블마다 매개변수로 넣는 것 보다 그냥 CompositionLocal로 구현해봤습니다~

) {
Column(
modifier = modifier,
) {
CalendarTopAppBar(
date = getYearMonthByPage(pagerState.settledPage),
isListExpanded = uiState.isListEnabled,
onListButtonClicked = onClickListButton,
onMonthNavigationButtonClicked = { direction ->
coroutineScope.launch {
pagerState.animateScrollToPage(
page = pagerState.settledPage + direction,
animationSpec = tween(500)
)
}
}
}
)
ScreenTransition(
targetState = !uiState.isListEnabled,
transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith
slideOutHorizontally { fullWidth -> fullWidth },
transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith
slideOutHorizontally { fullWidth -> -fullWidth },
contentOne = {
Column(
modifier = Modifier
.fillMaxSize()
) {
WeekDaysHeader()
)
ScreenTransition(
targetState = !uiState.isListEnabled,
transitionOne = slideInHorizontally { fullWidth -> -fullWidth } togetherWith
slideOutHorizontally { fullWidth -> fullWidth },
transitionTwo = slideInHorizontally { fullWidth -> fullWidth } togetherWith
slideOutHorizontally { fullWidth -> -fullWidth },
contentOne = {
Column(
modifier = Modifier
.fillMaxSize()
) {
WeekDaysHeader()

HorizontalDivider(
thickness = 1.dp,
color = Grey200
)
HorizontalDivider(
thickness = 1.dp,
color = Grey200
)

ScreenTransition(
targetState = !uiState.isWeekEnabled,
transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith
slideOutVertically { fullHeight -> fullHeight },
transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith
slideOutVertically { fullHeight -> -fullHeight },
contentOne = {
CalendarMonthRoute(
listState = listState,
pages = uiState.calendarModel.pageCount,
selectedDate = uiState.selectedDate,
updateSelectedDate = updateSelectedDate,
modifier = Modifier
.fillMaxSize()
.background(White),
)
},
contentTwo = {
CalendarWeekRoute(
calendarUiState = uiState,
modifier = Modifier
.fillMaxSize(),
navigateUp = disableWeekVisibility,
navigateToAnnouncement = navigateToAnnouncement,
updateSelectedDate = updateSelectedDate
)
}
ScreenTransition(
targetState = !uiState.isWeekEnabled,
transitionOne = slideInVertically { fullHeight -> -fullHeight } togetherWith
slideOutVertically { fullHeight -> fullHeight },
transitionTwo = slideInVertically { fullHeight -> fullHeight } togetherWith
slideOutVertically { fullHeight -> -fullHeight },
contentOne = {
CalendarMonthRoute(
selectedDate = uiState.selectedDate,
updateSelectedDate = { newDate ->
if(!pagerState.isScrollInProgress)
onClickNewDate(newDate)
},
modifier = Modifier
.fillMaxSize()
.background(White),
)
},
contentTwo = {
CalendarWeekRoute(
calendarUiState = uiState,
modifier = Modifier
.fillMaxSize(),
navigateUp = disableWeekVisibility,
navigateToAnnouncement = navigateToAnnouncement,
updateSelectedDate = onClickNewDate
)
}
)
}
},
contentTwo = {
CalendarListRoute(
navigateToAnnouncement = navigateToAnnouncement,
navigateUp = disableListVisibility,
modifier = Modifier
.fillMaxSize()
)
}
},
contentTwo = {
CalendarListRoute(
listState = listState,
pages = uiState.calendarModel.pageCount,
navigateToAnnouncement = navigateToAnnouncement,
navigateUp = disableListVisibility,
modifier = Modifier
.fillMaxSize()
)
},
)
},
)
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,40 @@ class CalendarViewModel @Inject constructor() : ViewModel() {
private var _uiState: MutableStateFlow<CalendarUiState> = MutableStateFlow(CalendarUiState())
val uiState get() = _uiState.asStateFlow()

fun updateSelectedDate(date: LocalDate) = viewModelScope.launch {
if (_uiState.value.selectedDate != date) {
fun onSelectNewDate(selectedDate: LocalDate) = viewModelScope.launch {
if (_uiState.value.selectedDate == selectedDate) {
_uiState.update { currentState ->
currentState.copy(
selectedDate = date
isWeekEnabled = !_uiState.value.isWeekEnabled
)
}
updateWeekVisibility(true)
} else {
updateWeekVisibility(!_uiState.value.isWeekEnabled)
_uiState.update { currentState ->
currentState.copy(
selectedDate = selectedDate,
isWeekEnabled = true
)
}
}
}

fun updatePage(page: Int) = viewModelScope.launch {
fun updateSelectedDate(date: LocalDate) = viewModelScope.launch {
_uiState.update { currentState ->
currentState.copy(
currentPage = page
selectedDate = date
)
}
}

fun updateListVisibility(
visibility: Boolean
) {
fun updateListVisibility(visibility: Boolean) = viewModelScope.launch {
_uiState.update { currentState ->
currentState.copy(
isListEnabled = visibility
)
}
}

fun updateWeekVisibility(
visibility: Boolean
) {
fun updateWeekVisibility(visibility: Boolean) = viewModelScope.launch {
_uiState.update { currentState ->
currentState.copy(
isWeekEnabled = visibility
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package com.terning.feature.calendar.calendar.model

import androidx.compose.foundation.pager.PagerState
import androidx.compose.runtime.compositionLocalOf
import java.time.LocalDate

data class CalendarUiState(
val selectedDate: LocalDate = LocalDate.now(),
val calendarModel: CalendarModel = CalendarModel(),
val currentPage: Int = 0,
val isListEnabled: Boolean = false,
val isWeekEnabled: Boolean = false
)

val LocalPagerState = compositionLocalOf<PagerState> {
error("No PagerState provided")
}
Comment on lines +14 to +16
Copy link
Contributor

Choose a reason for hiding this comment

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

요 부분 하드코딩하신 이유가 따로 있으신가용?!

Copy link
Member Author

Choose a reason for hiding this comment

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

UI적으로 필요한 부분이 아니라 그냥 하드코딩으로 넣어놨습니다!
딱히 재사용되는 것도 아니라 리소스화할 필요성을 못느꼈는데 저런 부분도 리소스화해야 할까요??

Copy link
Contributor

Choose a reason for hiding this comment

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

UI 관련이 아니군요 딱콩 ㅎ ㅅ ㅎ

Loading
Loading