From 39659f74d1a36a361aea227462aa6f40dcc0d696 Mon Sep 17 00:00:00 2001 From: boris-xyz <62296097+014967@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:02:52 +0900 Subject: [PATCH 001/110] =?UTF-8?q?[feat]=20tabrow=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleScreen.kt | 10 +++ .../ui/schedule/component/ScheduleTabRow.kt | 83 +++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 8aa9b5e2..b636eb5e 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -48,6 +49,7 @@ import com.mashup.ui.attendance.platform.PlatformAttendanceActivity import com.mashup.ui.danggn.ShakeDanggnActivity import com.mashup.ui.main.MainViewModel import com.mashup.ui.main.model.MainPopupType +import com.mashup.ui.schedule.component.ScheduleTabRow import com.mashup.ui.schedule.detail.ScheduleDetailActivity import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem @@ -201,6 +203,8 @@ fun ScheduleScreen( mutableStateOf(scheduleState) } + var selectedTabIndex by remember { mutableIntStateOf(0) } + LaunchedEffect(scheduleState) { if (scheduleState is ScheduleState.Success) { cacheScheduleState = scheduleState @@ -220,6 +224,12 @@ fun ScheduleScreen( } } + ScheduleTabRow( + modifier= Modifier.fillMaxWidth(), + selectedTabIndex = selectedTabIndex, + updateSelectedTabIndex = {selectedTabIndex = it} + ) + HorizontalPager( modifier = modifier, state = horizontalPagerState, diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt new file mode 100644 index 00000000..3ed69fe8 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -0,0 +1,83 @@ +package com.mashup.ui.schedule.component + +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.colors.Gray950 +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Body3 + +@Composable +fun ScheduleTabRow( + modifier: Modifier = Modifier, + tabMenu: List = listOf("아번 주 일정", "전체 일정"), + selectedTabIndex: Int = 0, + updateSelectedTabIndex: (Int) -> Unit = {} +) { + TabRow( + modifier = modifier, + selectedTabIndex = selectedTabIndex, + containerColor = Color.Transparent, + indicator = { tabPositions -> + TabRowDefaults.Indicator( + color = Gray950, + modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) + ) + }, + tabs = { + tabMenu.forEachIndexed { index, a -> + Tab( + selected = index == selectedTabIndex, + onClick = { + updateSelectedTabIndex(index) + } + ) { + Text( + text = a, + style = Body3.copy( + fontWeight = if (index == selectedTabIndex) { + FontWeight.W700 + } else { + FontWeight.W400 + } + + ), + color = Gray950 + ) + Spacer( + modifier = Modifier.height(12.dp) + ) + } + } + } + ) +} + +@Preview +@Composable +private fun PreviewTabRow() { + MashUpTheme { + var selectedTabIndex by remember { mutableIntStateOf(0) } + + ScheduleTabRow( + selectedTabIndex = selectedTabIndex, + updateSelectedTabIndex = { + selectedTabIndex = it + } + ) + } +} From efdd38f2c1cc6edb92d705e089640420450e0f0b Mon Sep 17 00:00:00 2001 From: boris-xyz <62296097+014967@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:54:09 +0900 Subject: [PATCH 002/110] =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?UTF-8?q?=EB=A1=9C=EB=A7=8C=20=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleScreen.kt | 7 - .../ui/schedule/component/ScheduleTabRow.kt | 148 +++++++++++++----- 2 files changed, 113 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index b636eb5e..2496b9fe 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -49,7 +49,6 @@ import com.mashup.ui.attendance.platform.PlatformAttendanceActivity import com.mashup.ui.danggn.ShakeDanggnActivity import com.mashup.ui.main.MainViewModel import com.mashup.ui.main.model.MainPopupType -import com.mashup.ui.schedule.component.ScheduleTabRow import com.mashup.ui.schedule.detail.ScheduleDetailActivity import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem @@ -224,12 +223,6 @@ fun ScheduleScreen( } } - ScheduleTabRow( - modifier= Modifier.fillMaxWidth(), - selectedTabIndex = selectedTabIndex, - updateSelectedTabIndex = {selectedTabIndex = it} - ) - HorizontalPager( modifier = modifier, state = horizontalPagerState, diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt index 3ed69fe8..a606564b 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -1,70 +1,147 @@ package com.mashup.ui.schedule.component +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.animateDpAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Tab +import androidx.compose.material3.TabPosition import androidx.compose.material3.TabRow import androidx.compose.material3.TabRowDefaults -import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.debugInspectorInfo import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.mashup.core.ui.colors.Gray950 import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Body3 +/** + * 일정 탭을 표시하는 컴포저블입니다. + * @param modifier Modifier + * @param tabMenu List 탭 메뉴 리스트 + * @param selectedTabIndex Int 선택된 탭 인덱스 + * @param updateSelectedTabIndex (Int) -> Unit 선택된 탭 인덱스 업데이트 함수 + * + * 사용 예시 + * ``` + * val selectedTabIndex by remember { mutableIntStateOf(0) } + * + * ScheduleTabRow( + * modifier = Modifier.fillMaxWidth(), + * selectedTabIndex = selectedTabIndex, + * updateSelectedTabIndex = { selectedTabIndex = it } + * ) + * + * when(selectedTabIndex) { + * 0 -> { // 이번 주 일정 Contents } + * 1 -> { // 전체 일정 Contents } + * } + * ``` + */ @Composable fun ScheduleTabRow( modifier: Modifier = Modifier, - tabMenu: List = listOf("아번 주 일정", "전체 일정"), + tabMenu: List = listOf("이번 주 일정", "전체 일정"), selectedTabIndex: Int = 0, updateSelectedTabIndex: (Int) -> Unit = {} ) { - TabRow( - modifier = modifier, - selectedTabIndex = selectedTabIndex, - containerColor = Color.Transparent, - indicator = { tabPositions -> - TabRowDefaults.Indicator( - color = Gray950, - modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]) - ) - }, - tabs = { - tabMenu.forEachIndexed { index, a -> - Tab( - selected = index == selectedTabIndex, - onClick = { - updateSelectedTabIndex(index) - } - ) { - Text( - text = a, - style = Body3.copy( - fontWeight = if (index == selectedTabIndex) { - FontWeight.W700 - } else { - FontWeight.W400 - } - - ), - color = Gray950 - ) - Spacer( - modifier = Modifier.height(12.dp) + Column( + modifier = modifier + ) { + Spacer( + modifier = Modifier.height(26.dp) + ) + TabRow( + modifier = Modifier.fillMaxWidth(), + selectedTabIndex = selectedTabIndex, + containerColor = Color.Transparent, + indicator = { tabPositions -> + TabRowDefaults.Indicator( + color = Gray950, + modifier = Modifier.customTabIndicatorOffset( + tabPositions[selectedTabIndex], + tabWidth = 150.dp + ).clip( + RoundedCornerShape(20.dp) ) + ) + }, + tabs = { + tabMenu.forEachIndexed { index, a -> + Tab( + selected = index == selectedTabIndex, + onClick = { + updateSelectedTabIndex(index) + } + ) { + Text( + text = a, + style = Body3.copy( + fontWeight = if (index == selectedTabIndex) { + FontWeight.W700 + } else { + FontWeight.W400 + } + + ), + color = Gray950 + ) + Spacer( + modifier = Modifier.height(12.dp) + ) + } } } - } + ) + } +} + +fun Modifier.customTabIndicatorOffset( + currentTabPosition: TabPosition, + tabWidth: Dp +): Modifier = composed( + inspectorInfo = debugInspectorInfo { + name = "customTabIndicatorOffset" + value = currentTabPosition + } +) { + val currentTabWidth by animateDpAsState( + targetValue = tabWidth, + animationSpec = tween(durationMillis = 250, easing = FastOutSlowInEasing), + label = "" + ) + + val indicatorOffset by animateDpAsState( + targetValue = ((currentTabPosition.left + currentTabPosition.right - tabWidth) / 2), + animationSpec = tween(durationMillis = 250, easing = FastOutSlowInEasing), + label = "" ) + + fillMaxWidth() + .wrapContentSize(Alignment.BottomStart) // indicator 표시 위치 + .offset(x = indicatorOffset) + .width(currentTabWidth) } @Preview @@ -74,6 +151,7 @@ private fun PreviewTabRow() { var selectedTabIndex by remember { mutableIntStateOf(0) } ScheduleTabRow( + modifier = Modifier.fillMaxWidth().background(color = Color.White), selectedTabIndex = selectedTabIndex, updateSelectedTabIndex = { selectedTabIndex = it From 14e7eedadf91540a5599d0ce1a1732714a4863bf Mon Sep 17 00:00:00 2001 From: boris-xyz <62296097+014967@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:58:27 +0900 Subject: [PATCH 003/110] =?UTF-8?q?=ED=96=94=EC=9E=AC=20=EB=AF=B8=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20state=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 2496b9fe..8aa9b5e2 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -202,8 +201,6 @@ fun ScheduleScreen( mutableStateOf(scheduleState) } - var selectedTabIndex by remember { mutableIntStateOf(0) } - LaunchedEffect(scheduleState) { if (scheduleState is ScheduleState.Success) { cacheScheduleState = scheduleState From 9c2723529958ebae420a3226d940c882dc7c88dd Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 13:58:37 +0900 Subject: [PATCH 004/110] =?UTF-8?q?=ED=8F=B0=ED=8A=B8=20=ED=81=AC=EA=B8=B0?= =?UTF-8?q?=20=EB=B0=8F=20=EC=97=AC=EB=B0=B1=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/component/ScheduleTabRow.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt index a606564b..7fe8ff08 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.shape.RoundedCornerShape @@ -35,6 +36,7 @@ import androidx.compose.ui.unit.dp import com.mashup.core.ui.colors.Gray950 import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Body3 +import com.mashup.core.ui.typography.SubTitle1 /** * 일정 탭을 표시하는 컴포저블입니다. @@ -95,9 +97,12 @@ fun ScheduleTabRow( updateSelectedTabIndex(index) } ) { + Spacer( + modifier= Modifier.height(2.5.dp) + ) Text( text = a, - style = Body3.copy( + style = SubTitle1.copy( fontWeight = if (index == selectedTabIndex) { FontWeight.W700 } else { @@ -108,7 +113,7 @@ fun ScheduleTabRow( color = Gray950 ) Spacer( - modifier = Modifier.height(12.dp) + modifier = Modifier.height(14.5.dp) ) } } From 5434a95650b6c56766ea32d5a24f977583d4e09d Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 14:03:43 +0900 Subject: [PATCH 005/110] =?UTF-8?q?spotless=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mashup/ui/schedule/component/ScheduleTabRow.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt index 7fe8ff08..7f066b78 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -9,7 +9,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.shape.RoundedCornerShape @@ -35,7 +34,6 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.mashup.core.ui.colors.Gray950 import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.core.ui.typography.Body3 import com.mashup.core.ui.typography.SubTitle1 /** @@ -98,7 +96,7 @@ fun ScheduleTabRow( } ) { Spacer( - modifier= Modifier.height(2.5.dp) + modifier = Modifier.height(2.5.dp) ) Text( text = a, From 39e08c135bcf63fdf2ed920ef4d5772ad179e392 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 14:29:55 +0900 Subject: [PATCH 006/110] =?UTF-8?q?empty=20=EC=8A=A4=EC=BC=80=EC=A5=B4=20U?= =?UTF-8?q?I=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/schedule/item/EmptyScheduleItem.kt | 55 ++++++++++++++++++ .../main/res/drawable/img_empty_schdule.png | Bin 0 -> 271418 bytes .../com/mashup/core/ui/widget/MashUpButton.kt | 6 +- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt create mode 100644 core/common/src/main/res/drawable/img_empty_schdule.png diff --git a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt new file mode 100644 index 00000000..4cedc458 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt @@ -0,0 +1,55 @@ +package com.mashup.ui.schedule.item + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Header2 +import com.mashup.core.ui.widget.MashUpButton +import com.mashup.core.common.R as CommonR + +@Composable +fun EmptyScheduleItem( + modifier: Modifier = Modifier, + onClickMashongButton: () -> Unit = {}, +) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(17.dp), + ) { + Image( + painter = painterResource(id = CommonR.drawable.img_empty_schdule), + contentDescription = null, + modifier = + Modifier + .width(284.dp) + .height(256.dp), + ) + + Text( + text = "이번주는 자유다..!", + style = Header2, + color = Color(0xFF412491), + ) + MashUpButton(text = "매숑이 밥주러 가기", buttonHeight = 48.dp, onClick = onClickMashongButton) + } +} + +@Preview +@Composable +private fun PreviewEmptyScheduleItem() { + MashUpTheme { + EmptyScheduleItem() + } +} diff --git a/core/common/src/main/res/drawable/img_empty_schdule.png b/core/common/src/main/res/drawable/img_empty_schdule.png new file mode 100644 index 0000000000000000000000000000000000000000..5e70c6c85e29fe8a63e4e656f1b86118160fc9f2 GIT binary patch literal 271418 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%0D+GOt@jus-}zS{r1* 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%0DOn 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
    px{TO!huH% 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

    jqPA=nH( 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

    pV2EBoj8LAjz-K6BqDCI8^8(KN1Z4tHYC2 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�DBw99;k0=QLo?rIO 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�PEXOxnA}lbW1YIM$R=b?clkz-Cat)Rg1O;3V*_ArxgrXP94CHJ-St`^d2xkHRUx|HuINiWfuSHLN- z$wHXDI@kWIMgA!=pcq6%1VDwSti`l*0qdmmW}TwsDL)=V;U5( z`S~JLDtCCw@i@Vx6sTCQu0K+Z4=D?PR-`+z>PBFtEmqSjIvF3a>7`?MO zipSAr6sI@imbzaw)CQYL#@2SPHoFjSgS|8+=JMEkwOu%dJ~0)qC7wLGS=MboDvI)O zEkx3i5v0t>O;dPPO5y8a7Z)3=F}dX-sH2RHY`@>_dCCk0Pl0sC&+t76&B-0}{!}&H zmQa(@vj>?l5~NUj;n?-%y;IRwy{}swH(3R>D>yKElO^6fT$IooL|(!*glR4d`x1p@ zn}y@P_URW`S8J*utRnjZmKxY5No-?P{^un>`H|@~(=?B6ME)eLpPqVWxF2#|cF%Nw zIg>aIT<(JqtU`;wkRC=kOMRsf%M5@)=tNG;hP76wn!aR&Q?qW~tlJ!&ge>ki+OKO) z6<1EZ-z>8JM5)ZRCq7!FsuUy*A*eK@*K&5b^m)u~sF{_Di|GG-hx!i< z1vo066^#TqJ;g*gCIVSN1`W#aFb(>6={;~*Y@xDUvH!~8aaeOh=hh~p^PxinsOhfI ziHKzd69j!^^OE?#Y=dH2f@A~2{{4-~H!bcl8w|C?Jj@gzN|dcOf6;4zi~llQrpXbn zRX+I4iU4~HgeID-I?6Aq?GwK$Vnb`{TDlpAe>lf7!F_pYt_1OX@xaO<1(UC$uQ#o1 zo`*C=;Ido~Ln|DAuU+Otn)A6BGP+ypcxHPmU3tX$UzZ83+Ad&`kCn97s1~(jzBI~^bYi>s8g?1X zAlOuwmX{o!X2)i;B?#x8Cb8^mLF&86;SjGR18Zg+w3#U`)TmxIv)m6^oQrr+!dYdO z0lS+{EN(+}cR^z&bA*^y@VOI_-_eJW_42h%Ez^4`BbK%!X@>7No$j*W2p0r4Wz?ut z=S#eC%%PEH+RnO_8+&ixobZ)-y_{4_PnU^idz-?&mzUGiuD3#-*Hqn9vE)xZDTvo6 zypbMofn1XuHbmg)ld{Q@KJY5syH+REv)LuMWdf4Cw6AqzqdT^uAYegcNG3g zQh5T&vw!rw>q7#cE420PHBSCq3F?xiN5pBV;3zQQy+(kf}g*=54tE z`jt~4qC-oYbs4wIdT8BhJ4jb4GfiKS%qvuTWI5Xde6q3se6q3G3X|)p2bEPtCT-ZN zdjHK;hLSWIJwB~Ji5$6-+E4RcDTe#=26ipStk)lxSt5ft%ZDB#lMw1%(Vg#8Z<+(E zadpP$37GKjwx{wunM$2uzmmK!PS7ZeFHvhI^&p2mcljsfY`1&5-iTMzYi-%QwhC8p znL9?3Y?kM56l(;{c2f3J+7!xZ*>JeJSlD;FKW*>ng%pn2<5VZx{4b4ECi}Da=R7cmfaXU1o^*sd=#@Xd!%T@c>RqJ-`34Z4TEs$ zfQWy92#3shFv4A&3qmy@95hXZfmWR2<2|KSl|oA?QGxUo@OMkmErhd5E7;7gTUkaf zxWW=vU((kPE0cyX)aYv-d^7zU959DJ=)TOwv??`4D&$0{|D_IQF7`_4)7HX)-=Ir| zWlK82A0$g;r-{PagA7iSz9Kl3^jXpKS=A!@-G{@n0hQ+GeD(l^oT+hrFdv9q)%x)a z!7lpMS1w%LF@Xwo$&6I6dH)kTjnZcS^0Tjhns%zqXmR275ipCH#xRz znbq9$$FtK3iR-Y}UQVn3rArK+tadJ}R#b{biomZKwUo9XT)~K*2?hA#%T4v6g8Y`8 zkw^sYWp7_k zRjrV&`oAAhyzKYYH)@QM>XMx_NWA6%_>eE|apo`U(@~`BOv{YWc2m5_%uOcMv)LQn ztT0MFlGYz7#BC%iwPuI#;BDYlY;!K}T z;bK$uC|TyUbp#A!g0GiBvyLI1(&SW5Vh-jEl^I`i)OOu#vIq&r#Q`izO?e!2% zgSBr@jQ+)Z)3$K%G^`!a=k8@~YI$(S?Bq|W0zN^E$tiD{%zLn!Qe^vNxzoJ+1VS=9FU3YO3ng=W{5hTewUx*A|) zgg6B*<|7UQg$jd*#29Td$@e(_+7sM+Bk~7SKZm{-rhjK1OUjqi66wEERHZeQ%xTa< zc2a2K+TT%6AtD&`ow-6erF~2v&vI(Z`S&Fo}M7$Kh!H79@_(MK1z!Rj~ zF~h3<akRDiE%-^g3UZ={vn|quPYQUG4=Gg zfmbpE;8w%0)2eHSz#xpBB@VZb^h|9gv73{kLoThSlp(S?E$NBVyZLeLhg~FI$3XTA z1~6fPsRw{i_u~{|j=K!3L1ysEq%10*NF44b8$LmJ9U^GCd1tE5Gym zwz^ESFe$kZ)jfxMT0Y6m;)k>?v?#?Hj&2=D97x@HS9G~utk924K0lCjoG~7tDZQ)J zG^z%xJ*Ibyot$+1p^~%K7K&DTjRE1%lHPKqInbNRlqS>Vc$9D_Ptr~{rgup!z=JJGRl}CBj8jU=>iHEnyvp9 z_py}MeGuT!y#&S-?B=JKqPXm@*-FR)e;$vQwobO3_N*oii%wdp6WHsK6m(5<5zJk< z{zd%Jq=^@1Zltijz-|q0$};3lZ>#7h;J6u}bcC})CPCF2_Gt~sE$^avOkfRVFZ3zT z^7;2emwOy0S?a`Q$rW=Dio|xrMBVvd(0TJ9XWYQg+4k38iQz1vxQ+Y0MpNxXLH+@p zD1q2)#oebTgx4;vUyyI)m6nEn=;&?5^-M%=;M&fT9jJI(h(0CVxaaT6|dJdRS3U0Q+E_=5!v9D&)_=oFgGfzbi zN#>Hbq#3m#&LXSOn%l>blk%?us}8wL1}5>vuoBIjHDa;iDfZTk#iSzH$^4%AlZ6J#VuJsdu`eHmo{tfdz2>*~=Y)2!H?>;|b_i>C4_5xt-tRgjiZG zIyyoXC2tAi1w{izfBV!_lo;!J)S~=*A8{oOXJx_>c47lZBoqbV1WoXyrD`W?>>u&Y zLnq~5l83)RBA%OmCqP!JFYVcHOj@%@bGGwi4#%Qfj}*BB)Xy4{@D)Ch;uH@dtAN-g zcZ=VUyD!`r056pR=etpt^X0MvFL>)q-QGLu>yndYFW7OBMuBN>0d51|^QGc&+?I&5 z;Qtn_@wVuz8E4f!m{%VJcjB*IV`q$&DPT5vugxIRV zBjOh}x~dhw?Cgo$4)?2DgH3a$_p9^5SYWrY%O(mx=cU|Dx=q5V>us1h-Jks|R)|jO zD(^qs0^RYJLXR}-G18*_Y`*&;@y#^UBFIr&8{VvXxM*k4Vfk-}p0#gTJ3Nr!0F1Qa zQTj*E%eoU1HF*FA?Kve0LBgJ#Fg&US&j*}fK%Ks|4c_w_AV%puth0csyp zIEx=KF|+n`nZt)eNy8Ld@Be@--$!W`OBPx0gm`=kzFBp!fW_meEuDFO42N>8EEaX} zpC|idz;M^t9*DHQ{sOh0G)RS(#r|VAi|^L`&4d}rzKQ*W=9NsCP|;zIzkC&UPd*q% z&|YF(9>r^2W?0EyU243cdNc;VaQUm+pV77-n(8RQ0U5H7K99#1pB9-2enL&S{edEk z-VWkfP?Ummf5%B%V${i`{138$_Vh=+vw={Ol`#Gnb?G1M;ZL7WHne_Hw#LWnjN8lv z1dox@?)<>&uvw!hx*)HW&DS>|iSu4}>_3U<`eTkl1W-L{wG5Jl}RGo%O+x`g{`;SKg;Resy%XwS2p%^8YT% z9(YZgF!EduhO5XsmYlO*@f7v8^m#q!&>;o&Y+s?q3Xq8qIy35b>m$y`MkjBYyQ10C zocIsPh53Vy=J_aH>#xMVxqrF!e_B3#DV~4n;}Cs#x4vF<+@nK@`x&jo3k^8NLR^Y8 zAP$*;jtUSBAhPoI7FIAp+smDBa9&rGug0GJ$5XXu;^x*)${$Bz?DvCQB=h-?b6&|2 z2d2u)#7@lbmD@FdCC?);vvH9Em>sr*R|0r-of&Jms)pHq-l{@0*ap~%+OB) zBjQ`m8zcHGIEqfhW7ZF2T2sPvopLOy6_E8#q7lY$8~!$704{_4*{iQEE<$Ao8ZSP0 zrY$wd3(*J|V>*4t29WKWy;V^earIRzx*u9OVc3SFxRTt~Vc(ALU8v1YGPZg!5&paE zaI+A6`O{9g>xb2ovUD zbOXb#9m65tOHo60Xy>q*f7m=+PDx?(Rd4wEze^%6 zcvFBa^m|Li1I%u7XWcm=pJe`vohBC-ky&fI1Gx-FkDhYsptYv{KzGofAdIB|L>#-c zmi-vF?*62dmiNg~_^(zD9`wo^s#Y0qaW!!4x+UpOkH?^&<=dUj(I}QKE;k@c&MtOf zvlaM2pGZLpoO{y9AEeqrmxf&8?~fMA!h=vYtHF$(ZGUaXO>x=KL+SJ1B#^Q0?i+?h zu7mFpu^}+Dxt1eDSS|pENwapg4Z3dnO|%PDE26s|xQ2q(^O~o6$#Rgk+o~HMlXRPH zoKhf~2c(h!03-qcfB*s(WUJj5&Bv#+v9#v*Eh0&@qQlP@CKc#XvMBR{yaL}QFaKnL zubk>sz%|B9haF6!q(Pzh$JZtC342@Z%=2CHx{|Xxkj~9a|G)1mW3h-n(^P1QtvaqK zQZCeY{~xmv*R1f^t2K*iBs@P#fXh8VWG8T-F4 zde1nInjZPd=R9L92H-_8Ij@0>A1K_CN>7hPhgly{zufN>aD!u>J4B6UEi<#aswtZ? z(yT_Fow-7%KIw_xIohV=L1H|XvJy?UU3~%oClkH@yN6Wq=JfNgth-DREpA8s%|T5L z{@#}CshBD@)T6-oO-K(he^G@vT_#+7ll$?-*-jhCV;MPs3-9+@H@I0}jxi7dOqp4W zxhlO^)wg4|Sq+h#{_h>a)h8ackUOUhhOv` z)Pk@{NLcJz3H*i9AB0&D#;7@dw^J^L6a7@q`k3&EM}v$u0KZHLz!zxwxMBgSrcf~6 z@$EwG@%uAgdiBYgSja$JTqDhEA*9M3e;gF8YM%AfI9|J8$zr2uW!(0ZCh0d%5Jor{YgR>ygfmQVRX z9%@ziry!|lX1T)FzN51vqif49Tj*gqu-OCAjJ^tIBFp8mv9HT~a!?NRKQ-$-9VXY6 zusNhwD?WwJwBc7m&RGh}E7UG+I>D+|yipxKZxa6DVXoHTR0G#tI4zdlf*+ABAU1o1 zpi|E)3j1A}oMlU~I`WM4RBo>kAByxdIFhLgyxpdExBm3T)2n{PU-%&YWY<=XPHeNP z%=Ewc(a50|KmMmZu9+AFV{Nt<=%k3Df?1Yu%#(|UUpsrHwZp+XQO+z-j`Vqjfqb7B znw+7s)DPsrN{4?P3NJ zGN{#iwvnsH5U@LxFX(&PB%oLkhQ2fFP4Sl(7Ymq>ldlAOKre?#UgqBo6THa;V~9Bc z#S^w9&Gr7tcJQN@A<{vq6~CoIZ3ZD^$ zcFzY0rq*|CJG)l z%X;wFdl|mxUx7QwUp$Ui)|5#Ohz8F0$bzf&8vjyFP)j2fYt3k}z|GjH5Ex5z<9%%k zqSN^WW?^g&q8q5F`-dk!zSN)aZK86qU&5{y8hfb~eK*e1Vr>8h35Du=wFp=CyzzRxJgJcd%&c`wq&%Oxv_ucMqT(TxDmILd z&jDXZOePXd(>MS40}F3kUg6-wR@ylJZ_1H-U3KDJtJdVZ6R9jJTF~ck5CRC>rf5#T z0C}&CbFpaVIs?mFx-pMobQ5=dAHEbr?9hIqszLSmV_RSOFg>H+KUgy^vRpm>v|`nk*m zWj+4b-^&-<*JWKge1_n$!7DWM3{xS&tDQCfwX`NiT(V}7HKPEW9a2cGGIQW&-L>3O z5k0bI66)ntn@u8Ie zZsM;it_=>x7`xvJpV?Vl)N~Qoe)owVm-UN=+R#x=$vw1Ca-ANLg z3SJlNLgO?6EU~n5Psv0WXUV zO$w3?tZP)aKAO4dfbZ}+tgCLLaiPFo52-kxN+B5En)aJHhA+igl+k*;QKij5gyq=T0Mi^;z>RJyyF>F2P&`4M_&TfS3|? zwM!jd4*r-9evg!?mGL_VLnsZMkR7?3CP90ppBfFV$y7sKGSNBasQURoVjQ$!`>cfV zf`fD?uebevrTTo5A|si^KYqNN0++g$+Aixh}_dk86oP2mmUl{)n7nJpKI$Gg5* z)u6NWZ?}=kX+g6-@rmDtXfWO*%?pi(>5U zq;galOM9QqVt!!t2-*mVW`#42WoLaW~Tb+2;YG2k(+^PiD_| zQ@12Vt0#uAJfMK@n7|1kE2Ul73f0e*M_gvmMlCF_3HdnwJ^Z>H1vy%TX`)oLSG0H` zCwJuqu_;je^>&+FEh9<%Jlb=!tRhNSfeZpM^%MGoWJ^laUtF+G^Js&8;g~; z?IPpRoD=RJREsm#lNvv`J1ls+X?(tb#0FV*D32yzXhDG}cis-8FA;O|Zd1%g-rc@5 z*+Aqz9ZRo44CkJCHXp_!Erbo7%hBhYoGtm0gukwD)+T$V0-@nGb5_L5+W`g?Z}Fz> z&OOANgahUEePA&Aj`ptnE&_sqh_LtPM0KMO_TJpk(#!R=suMVmqlS=Z-3yE z+Q26Rlq1YOq|&}roz2&8$^?Uta29rM>$RRLh1-eUShNgxs|)02j+TthQy+|cT_np! zqJ3W!@E&4f)Vd*q0xpYz?Y1S6=en{r zYImY~hB~bf)LQf!pf|{U8D1QlJ?$!_NI_xIr=z0MX6J-qSa4lRrnwLO)k9KvTST%9 zjOoPY%^Zo%wsHEG&TiN169+E~?Y{-I{y4}FzO+oXIKbqq z90yjX4V>rqqr@(^iO?f{tUdYT|LVdRJZqiy?O%i*+03s^`{TJAonse)nZp{tTGPK< z^Ui+xq#%&zcfbx#@SwTK^kv*ibAy`AUWJ&5&n?IOvPCqtgZ0Qh^$CD0X0EMiKlPJ23IR`W=l+#~4!g`7w*mi!qsOK>ql`UUvF5){qwdpK}zV z2HT29>M={Hzv^0zx9b<<@@7ZSAkgaDzXef3+3m(X!DvjQS1_J4P0E{6hUbVG8*gMnvSwNsLA}DkaNL=1- zKJ!xMy|i8ZMPJ5j-2EnjG$isnVDLGyH7EbZ|FjWnJQ-4(O;OAO29*B){v%s(3YFlg V7$ELe%JcTm<)oEAR7#oz{Xf>03P%6{ literal 0 HcmV?d00001 diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt index 1851f688..0d2c28d6 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt @@ -58,15 +58,17 @@ enum class ButtonStyle(val backgroundColor: Color, val textColor: Color) { fun MashUpButton( modifier: Modifier = Modifier, buttonStyle: ButtonStyle = ButtonStyle.PRIMARY, + buttonHeight : Dp = 52.dp, + buttonWidth : Dp = 256.dp, text: String, onClick: () -> Unit, isEnabled: Boolean = true, - showLoading: Boolean = false + showLoading: Boolean = false, ) { Box( modifier = modifier .clip(RoundedCornerShape(12.dp)) - .height(52.dp) + .height(buttonHeight) .background(if (isEnabled) buttonStyle.backgroundColor else ButtonStyle.DISABLE.backgroundColor) .padding(horizontal = 20.dp) .clickable( From c0c6c49cb2baff1856f0196a42bb4a21107839b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Wed, 26 Jun 2024 16:01:04 +0900 Subject: [PATCH 007/110] =?UTF-8?q?=F0=9F=A7=B8=20EventDetail=20=EB=AA=A8?= =?UTF-8?q?=EB=8D=B8=EC=9D=84=20sealed=20class=EB=A1=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/detail/ScheduleDetailAdapter.kt | 49 ++++---- .../detail/ScheduleDetailViewModel.kt | 114 ++---------------- .../mashup/ui/schedule/model/EventDetail.kt | 84 ++++++------- .../ui/schedule/model/EventDetailMapper.kt | 88 ++++++++++++++ .../layout/item_event_timeline_content.xml | 10 +- .../res/layout/item_event_timeline_header.xml | 8 +- 6 files changed, 168 insertions(+), 185 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt index 2bdf73f5..86449b44 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt @@ -76,8 +76,10 @@ class EventDetailAdapter( private val binding: ItemEventTimelineHeaderBinding? = DataBindingUtil.bind(itemView) fun bind(item: EventDetail) { + if (item !is EventDetail.Header) return + binding?.model = item - if (item.header?.eventId == 1) { + if (item.eventId == 1) { binding?.line?.visibility = View.GONE } } @@ -94,6 +96,7 @@ class EventDetailAdapter( DataBindingUtil.bind(itemView) fun bind(item: EventDetail) { + if (item !is EventDetail.Content) return binding?.model = item } } @@ -107,17 +110,17 @@ class EventDetailAdapter( } fun bind(item: EventDetail, copyToClipboard: (String) -> Unit) { - item.location?.let { location -> - composeView.setContent { - MashUpTheme { - ScheduleDetailLocationContent( - detailAddress = location.detailAddress.orEmpty(), - roadAddress = location.roadAddress.orEmpty(), - latitude = location.latitude, - longitude = location.longitude, - copyToClipboard = copyToClipboard - ) - } + if (item !is EventDetail.Location) return + + composeView.setContent { + MashUpTheme { + ScheduleDetailLocationContent( + detailAddress = item.detailAddress.orEmpty(), + roadAddress = item.roadAddress.orEmpty(), + latitude = item.latitude, + longitude = item.longitude, + copyToClipboard = copyToClipboard + ) } } } @@ -132,16 +135,16 @@ class EventDetailAdapter( } fun bind(item: EventDetail) { - item.info?.let { info -> - composeView.setContent { - MashUpTheme { - ScheduleDetailInfoContent( - title = info.title, - date = info.date, - time = info.time, - modifier = Modifier.padding(top = 24.dp) - ) - } + if (item !is EventDetail.Info) return + + composeView.setContent { + MashUpTheme { + ScheduleDetailInfoContent( + title = item.title, + date = item.date, + time = item.formattedTime, + modifier = Modifier.padding(top = 24.dp) + ) } } } @@ -157,7 +160,7 @@ object EventComparator : DiffUtil.ItemCallback() { oldItem: EventDetail, newItem: EventDetail ): Boolean { - return oldItem.id == newItem.id + return oldItem.index == newItem.index } override fun areContentsTheSame( diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt index 91927b61..e33440db 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt @@ -3,17 +3,9 @@ package com.mashup.ui.schedule.detail import androidx.lifecycle.SavedStateHandle import com.mashup.constant.EXTRA_SCHEDULE_ID import com.mashup.core.common.base.BaseViewModel -import com.mashup.core.common.extensions.getTimeFormat -import com.mashup.data.dto.ContentResponse -import com.mashup.data.dto.EventResponse -import com.mashup.data.dto.ScheduleResponse import com.mashup.data.repository.ScheduleRepository -import com.mashup.ui.schedule.model.Body import com.mashup.ui.schedule.model.EventDetail -import com.mashup.ui.schedule.model.EventDetailType -import com.mashup.ui.schedule.model.Header -import com.mashup.ui.schedule.model.Info -import com.mashup.ui.schedule.model.Location +import com.mashup.ui.schedule.model.EventDetailMapper import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -22,6 +14,7 @@ import javax.inject.Inject @HiltViewModel class ScheduleDetailViewModel @Inject constructor( private val scheduleRepository: ScheduleRepository, + private val eventMapper: EventDetailMapper, savedStateHandle: SavedStateHandle ) : BaseViewModel() { private val scheduleId = @@ -41,16 +34,14 @@ class ScheduleDetailViewModel @Inject constructor( _scheduleState.emit(ScheduleState.Loading) scheduleRepository.getSchedule(scheduleId) .onSuccess { response -> - _scheduleState.emit( - ScheduleState.Success( - getEventDetailList( - title = response.name, - date = response.getDate(), - eventList = response.eventList, - location = response.location - ) - ) + val eventList = eventMapper.getEventDetailList( + title = response.name, + date = response.getDate(), + eventList = response.eventList, + location = response.location, ) + + _scheduleState.emit(ScheduleState.Success(eventList)) } .onFailure { code -> handleErrorCode(code) @@ -63,93 +54,6 @@ class ScheduleDetailViewModel @Inject constructor( _scheduleState.emit(ScheduleState.Error(code)) } } - - private fun getEventDetailList( - title: String, - date: String, - eventList: List, - location: ScheduleResponse.Location? - ): List { - var itemId = 0 - val eventDetailList = mutableListOf() - - val startAt = eventList.first().startedAt.getTimeFormat() - val endedAt = eventList.last().endedAt.getTimeFormat() - eventDetailList.add(mapToInfoModel(itemId++, title, date, "$startAt - $endedAt")) - - if (location?.detailAddress != null) { // 위치 정보가 있는 경우(온라인이면 placeName이 Zoom으로 내려옴) - eventDetailList.add(mapToLocationModel(itemId++, location)) - } - - eventList.forEachIndexed { eventIndex, event -> - eventDetailList.add(mapToHeaderModel(itemId++, eventIndex, event)) - - event.contentList.forEachIndexed { contentIndex, content -> - eventDetailList.add(mapToContentModel(itemId++, contentIndex, content)) - } - } - - return eventDetailList - } - - private fun mapToHeaderModel(itemId: Int, eventIndex: Int, event: EventResponse): EventDetail { - return EventDetail( - id = itemId, - type = EventDetailType.HEADER, - header = Header( - eventId = eventIndex + 1, - startedAt = event.startedAt, - endedAt = event.endedAt - ) - ) - } - - private fun mapToContentModel( - itemId: Int, - contentIndex: Int, - content: ContentResponse - ): EventDetail { - return EventDetail( - id = itemId, - type = EventDetailType.CONTENT, - body = Body( - contentId = "${contentIndex + 1}", - title = content.title, - content = content.content.orEmpty(), - startedAt = content.startedAt - ) - ) - } - - private fun mapToLocationModel(itemId: Int, location: ScheduleResponse.Location): EventDetail { - return EventDetail( - id = itemId, - type = EventDetailType.LOCATION, - location = Location( - detailAddress = location.detailAddress.orEmpty(), - roadAddress = location.roadAddress.orEmpty(), - latitude = location.latitude, - longitude = location.longitude - ) - ) - } - - private fun mapToInfoModel( - itemId: Int, - title: String, - date: String, - time: String - ): EventDetail { - return EventDetail( - id = itemId, - type = EventDetailType.INFO, - info = Info( - title = title, - date = date, - time = time - ) - ) - } } sealed interface ScheduleState { diff --git a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt index a5a29344..919a80ab 100644 --- a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt +++ b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt @@ -1,59 +1,47 @@ package com.mashup.ui.schedule.model -import java.text.SimpleDateFormat +import com.mashup.core.common.extensions.getTimeFormat import java.util.Date -import java.util.Locale -data class EventDetail( - val id: Int, +sealed class EventDetail( + open val index: Int, val type: EventDetailType, - val header: Header? = null, - val body: Body? = null, - val location: Location? = null, - val info: Info? = null -) - -data class Header( - val eventId: Int, - val startedAt: Date, - val endedAt: Date ) { - fun getHeader() = "${eventId}부" - fun getTimeStampStr(): String { - return try { - val timeLineFormat = SimpleDateFormat("a hh:mm", Locale.ENGLISH) - "${timeLineFormat.format(startedAt)} - ${timeLineFormat.format(endedAt)}" - } catch (ignore: Exception) { - "??:?? - ??:??" - } + data class Header( + override val index: Int, + val eventId: Int, + val startedAt: Date, + val endedAt: Date + ) : EventDetail(index, EventDetailType.HEADER) { + val title = "${eventId}부" + val formattedTime = "${startedAt.getTimeFormat()} - ${endedAt.getTimeFormat()}" } -} -data class Body( - val contentId: String, - val title: String, - val content: String, - val startedAt: Date -) { - fun getTimeStampStr(): String { - return try { - val timeLineFormat = SimpleDateFormat("a hh:mm", Locale.ENGLISH) - timeLineFormat.format(startedAt) - } catch (ignore: Exception) { - "??:??" - } + data class Content( + override val index: Int, + val contentId: String, + val title: String, + val content: String, + val startedAt: Date + ) : EventDetail(index, EventDetailType.CONTENT) { + val formattedTime = startedAt.getTimeFormat() } -} -data class Location( - val detailAddress: String?, - val roadAddress: String?, - val latitude: Double?, - val longitude: Double? -) + data class Location( + override val index: Int, + val detailAddress: String?, + val roadAddress: String?, + val latitude: Double?, + val longitude: Double? + ) : EventDetail(index, EventDetailType.LOCATION) -data class Info( - val title: String, - val date: String, - val time: String -) + data class Info( + override val index: Int, + val title: String, + val date: String, + val startedAt: Date, + val endedAt: Date, + ) : EventDetail(index, EventDetailType.INFO) { + val formattedTime = "${startedAt.getTimeFormat()} - ${endedAt.getTimeFormat()}" + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt b/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt new file mode 100644 index 00000000..de0b4718 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt @@ -0,0 +1,88 @@ +package com.mashup.ui.schedule.model + +import com.mashup.data.dto.ContentResponse +import com.mashup.data.dto.EventResponse +import com.mashup.data.dto.ScheduleResponse +import java.util.Date +import javax.inject.Inject + +class EventDetailMapper @Inject constructor() { + fun getEventDetailList( + title: String, + date: String, + eventList: List, + location: ScheduleResponse.Location? + ): List { + val eventDetailList = mutableListOf() + var index = 0 + + val infoModel = mapToInfoModel(index++, title, date, eventList.first().startedAt, eventList.last().endedAt) + eventDetailList.add(infoModel) + + if (location?.detailAddress != null) { // 위치 정보가 있는 경우(온라인이면 placeName이 Zoom으로 내려옴) + val locationModel = mapToLocationModel(index++, location) + eventDetailList.add(locationModel) + } + + eventList.forEachIndexed { eventIndex, event -> + val headerModel = mapToHeaderModel(index++, eventIndex, event) + eventDetailList.add(headerModel) + + event.contentList.forEachIndexed { contentIndex, content -> + val contentModel = mapToContentModel(index++, contentIndex, content) + eventDetailList.add(contentModel) + } + } + + return eventDetailList + } + + private fun mapToHeaderModel(index: Int, eventIndex: Int, event: EventResponse): EventDetail { + return EventDetail.Header( + index = index, + eventId = eventIndex + 1, + startedAt = event.startedAt, + endedAt = event.endedAt, + ) + } + + private fun mapToContentModel( + index: Int, + contentIndex: Int, + content: ContentResponse + ): EventDetail { + return EventDetail.Content( + index = index, + contentId = "${contentIndex + 1}", + title = content.title, + content = content.content.orEmpty(), + startedAt = content.startedAt, + ) + } + + private fun mapToLocationModel(index: Int, location: ScheduleResponse.Location): EventDetail { + return EventDetail.Location( + index = index, + detailAddress = location.detailAddress.orEmpty(), + roadAddress = location.roadAddress.orEmpty(), + latitude = location.latitude, + longitude = location.longitude + ) + } + + private fun mapToInfoModel( + index: Int, + title: String, + date: String, + startedAt: Date, + endedAt: Date, + ): EventDetail { + return EventDetail.Info( + index = index, + title = title, + date = date, + startedAt = startedAt, + endedAt = endedAt, + ) + } +} diff --git a/app/src/main/res/layout/item_event_timeline_content.xml b/app/src/main/res/layout/item_event_timeline_content.xml index 7d936230..65db7015 100644 --- a/app/src/main/res/layout/item_event_timeline_content.xml +++ b/app/src/main/res/layout/item_event_timeline_content.xml @@ -7,7 +7,7 @@ + type="com.mashup.ui.schedule.model.EventDetail.Content" /> + type="com.mashup.ui.schedule.model.EventDetail.Header" /> @@ -43,12 +43,12 @@ android:layout_height="match_parent" android:background="@drawable/icon_circle" android:backgroundTint="@color/brand100" - android:drawableLeft="@drawable/ic_clock" + android:drawableStart="@drawable/ic_clock" android:drawablePadding="5dp" android:gravity="center" android:paddingStart="8dp" android:paddingEnd="8dp" - android:text="@{model.header.getTimeStampStr()}" + android:text="@{model.formattedTime}" android:textAppearance="@style/TextAppearance.Mashup.Caption1_13_M" android:textColor="@color/brand500" tool:text="AM 11:00 - PM 2:00" /> From 82762971d00c4af16a9c2b550780e30914a62988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Wed, 26 Jun 2024 16:52:35 +0900 Subject: [PATCH 008/110] =?UTF-8?q?=F0=9F=A7=B8=20ScheduleDetailContentIte?= =?UTF-8?q?m=20=EC=BB=B4=ED=8F=AC=EC=A0=80=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/detail/ScheduleDetailAdapter.kt | 35 ++++---- .../composable/ScheduleDetailContentItem.kt | 89 +++++++++++++++++++ ...foContent.kt => ScheduleDetailInfoItem.kt} | 6 +- ...ntent.kt => ScheduleDetailLocationItem.kt} | 6 +- 4 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt rename app/src/main/java/com/mashup/ui/schedule/detail/composable/{ScheduleDetailInfoContent.kt => ScheduleDetailInfoItem.kt} (91%) rename app/src/main/java/com/mashup/ui/schedule/detail/composable/{ScheduleDetailLocationContent.kt => ScheduleDetailLocationItem.kt} (97%) diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt index 86449b44..d7e6255e 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt @@ -13,10 +13,10 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.databinding.ItemEventTimelineContentBinding import com.mashup.databinding.ItemEventTimelineHeaderBinding -import com.mashup.ui.schedule.detail.composable.ScheduleDetailInfoContent -import com.mashup.ui.schedule.detail.composable.ScheduleDetailLocationContent +import com.mashup.ui.schedule.detail.composable.ScheduleDetailContentItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailInfoItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailLocationItem import com.mashup.ui.schedule.model.EventDetail import com.mashup.ui.schedule.model.EventDetailType @@ -35,7 +35,7 @@ class EventDetailAdapter( HeaderViewHolder(parent) } EventDetailType.CONTENT.num -> { - ContentViewHolder(parent) + ContentViewHolder(ComposeView(parent.context)) } EventDetailType.LOCATION.num -> { LocationViewHolder(ComposeView(parent.context)) @@ -85,19 +85,22 @@ class EventDetailAdapter( } } - class ContentViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder( - ItemEventTimelineContentBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ).root - ) { - private val binding: ItemEventTimelineContentBinding? = - DataBindingUtil.bind(itemView) + class ContentViewHolder(private val composeView: ComposeView) : + RecyclerView.ViewHolder(composeView) { fun bind(item: EventDetail) { if (item !is EventDetail.Content) return - binding?.model = item + + composeView.setContent { + MashUpTheme { + ScheduleDetailContentItem( + contentId = item.contentId, + title = item.title, + content = item.content, + time = item.formattedTime, + ) + } + } } } @@ -114,7 +117,7 @@ class EventDetailAdapter( composeView.setContent { MashUpTheme { - ScheduleDetailLocationContent( + ScheduleDetailLocationItem( detailAddress = item.detailAddress.orEmpty(), roadAddress = item.roadAddress.orEmpty(), latitude = item.latitude, @@ -139,7 +142,7 @@ class EventDetailAdapter( composeView.setContent { MashUpTheme { - ScheduleDetailInfoContent( + ScheduleDetailInfoItem( title = item.title, date = item.date, time = item.formattedTime, diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt new file mode 100644 index 00000000..7e36bde8 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt @@ -0,0 +1,89 @@ +package com.mashup.ui.schedule.detail.composable + +import androidx.compose.foundation.background +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.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.colors.Gray100 +import com.mashup.core.ui.colors.Gray400 +import com.mashup.core.ui.colors.Gray600 +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Body4 +import com.mashup.core.ui.typography.Caption1 +import com.mashup.core.ui.typography.Caption2 +import com.mashup.core.ui.typography.SubTitle2 + +@Composable +fun ScheduleDetailContentItem( + contentId: String, + title: String, + content: String, + time: String, +) { + Column(modifier = Modifier.padding(vertical = 8.dp)) { + Row(verticalAlignment = Alignment.CenterVertically) { + Box( + modifier = Modifier + .size(20.dp) + .clip(CircleShape) + .background(Gray100), + contentAlignment = Alignment.Center, + ) { + Text( + text = contentId, + style = Caption2, + color = Gray600, + ) + } + + Text( + text = title, + style = SubTitle2, + modifier = Modifier + .weight(1f) + .padding(horizontal = 8.dp) + ) + + Text( + text = time, + style = Caption1, + color = Gray400, + ) + } + + if (content.isNotEmpty()) { + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = content, + style = Body4, + color = Gray600, + modifier = Modifier.padding(start = 28.dp) + ) + } + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewScheduleDetailContentItem() { + MashUpTheme { + ScheduleDetailContentItem( + contentId = "1", + title = "안드로이드 팀 세미나", + content = "Android Crew", + time = "AM 11:00" + ) + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoContent.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoItem.kt similarity index 91% rename from app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoContent.kt rename to app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoItem.kt index 728f8df8..7e7ddaa1 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoContent.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailInfoItem.kt @@ -13,7 +13,7 @@ import com.mashup.core.ui.typography.Header1 import com.mashup.core.common.R as CR @Composable -fun ScheduleDetailInfoContent( +fun ScheduleDetailInfoItem( title: String, date: String, time: String, @@ -33,9 +33,9 @@ fun ScheduleDetailInfoContent( @Preview @Composable -fun PreviewScheduleDetailInfoContent() { +fun PreviewScheduleDetailInfoItem() { MashUpTheme { - ScheduleDetailInfoContent( + ScheduleDetailInfoItem( title = "1차 정기 세미나", date = "3월 27일", time = "오후 3:00 - 오전 7:00" diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationContent.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationItem.kt similarity index 97% rename from app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationContent.kt rename to app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationItem.kt index 84b38ebf..dedb249c 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationContent.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailLocationItem.kt @@ -41,7 +41,7 @@ import com.mashup.core.common.R as CR @OptIn(ExperimentalNaverMapApi::class) @Composable -fun ScheduleDetailLocationContent( +fun ScheduleDetailLocationItem( detailAddress: String, roadAddress: String, latitude: Double?, @@ -140,9 +140,9 @@ fun ScheduleDetailLocationContent( @Preview @Composable -fun PreviewScheduleDetailLocationContent() { +fun PreviewScheduleDetailLocationItem() { MashUpTheme { - ScheduleDetailLocationContent( + ScheduleDetailLocationItem( detailAddress = "알파돔타워", roadAddress = "경기도 성남시 분당구 판교역로 152", latitude = 37.532600, From 79ed36e1602c20d7af77739125be1608fde7be2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Wed, 26 Jun 2024 17:41:10 +0900 Subject: [PATCH 009/110] =?UTF-8?q?=F0=9F=A7=B8=20ScheduleDetailHeaderItem?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EC=A0=80=EB=B8=94=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/detail/ScheduleDetailAdapter.kt | 24 +++-- .../composable/ScheduleDetailHeaderItem.kt | 87 +++++++++++++++++++ 2 files changed, 98 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt index d7e6255e..434d7741 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt @@ -13,8 +13,8 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.databinding.ItemEventTimelineHeaderBinding import com.mashup.ui.schedule.detail.composable.ScheduleDetailContentItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailHeaderItem import com.mashup.ui.schedule.detail.composable.ScheduleDetailInfoItem import com.mashup.ui.schedule.detail.composable.ScheduleDetailLocationItem import com.mashup.ui.schedule.model.EventDetail @@ -32,7 +32,7 @@ class EventDetailAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { return when (viewType) { EventDetailType.HEADER.num -> { - HeaderViewHolder(parent) + HeaderViewHolder(ComposeView(parent.context)) } EventDetailType.CONTENT.num -> { ContentViewHolder(ComposeView(parent.context)) @@ -66,21 +66,19 @@ class EventDetailAdapter( } } - class HeaderViewHolder(parent: ViewGroup) : RecyclerView.ViewHolder( - ItemEventTimelineHeaderBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ).root - ) { - private val binding: ItemEventTimelineHeaderBinding? = DataBindingUtil.bind(itemView) + class HeaderViewHolder(private val composeView: ComposeView) : RecyclerView.ViewHolder(composeView) { fun bind(item: EventDetail) { if (item !is EventDetail.Header) return - binding?.model = item - if (item.eventId == 1) { - binding?.line?.visibility = View.GONE + composeView.setContent { + MashUpTheme { + ScheduleDetailHeaderItem( + isFirstEvent = item.eventId == 1, + title = item.title, + time = item.formattedTime, + ) + } } } } diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt new file mode 100644 index 00000000..a3613dd2 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt @@ -0,0 +1,87 @@ +package com.mashup.ui.schedule.detail.composable + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.Divider +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.common.R +import com.mashup.core.ui.colors.Brand100 +import com.mashup.core.ui.colors.Brand500 +import com.mashup.core.ui.colors.Gray100 +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Caption1 +import com.mashup.core.ui.typography.Header2 + +@Composable +fun ScheduleDetailHeaderItem( + isFirstEvent: Boolean, + title: String, + time: String, +) { + Column { + if (isFirstEvent.not()) { + Spacer(modifier = Modifier.height(20.dp)) + Divider(color = Gray100, thickness = 1.dp) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp, bottom = 12.dp), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text(text = title, style = Header2) + + Row( + modifier = Modifier + .clip(CircleShape) + .background(Brand100) + .padding(horizontal = 8.dp, vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Image( + painter = painterResource(id = R.drawable.ic_clock), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + + Spacer(modifier = Modifier.width(4.dp)) + + Text( + text = time, + style = Caption1, + color = Brand500, + ) + } + } + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewScheduleDetailHeaderItem() { + MashUpTheme { + ScheduleDetailHeaderItem( + isFirstEvent = false, + title = "1부", + time = "10:00 - 11:00", + ) + } +} From b5d7a21035d6b3b3fb01f93d1427270ddbafb3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Thu, 27 Jun 2024 14:08:46 +0900 Subject: [PATCH 010/110] =?UTF-8?q?=F0=9F=A7=B8=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=20=EC=83=81=EC=84=B8=20=ED=99=94=EB=A9=B4=20RecyclerV?= =?UTF-8?q?iew=EB=A5=BC=20LazyColumn=EC=9C=BC=EB=A1=9C=20=EA=B5=90?= =?UTF-8?q?=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ScheduleDetailAdapter 및 ViewHolder들 삭제 - ScheduleDetailScreen 생성 --- .../schedule/detail/ScheduleDetailActivity.kt | 39 ++-- .../schedule/detail/ScheduleDetailAdapter.kt | 173 ------------------ .../schedule/detail/ScheduleDetailScreen.kt | 141 ++++++++++++++ .../detail/ScheduleDetailViewModel.kt | 5 +- .../detail/composable/ScheduleInfoText.kt | 4 +- .../mashup/ui/schedule/model/EventDetail.kt | 4 +- .../res/layout/activity_schedule_detail.xml | 35 +--- .../layout/item_event_timeline_content.xml | 73 -------- .../res/layout/item_event_timeline_header.xml | 59 ------ 9 files changed, 175 insertions(+), 358 deletions(-) delete mode 100644 app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt create mode 100644 app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt delete mode 100644 app/src/main/res/layout/item_event_timeline_content.xml delete mode 100644 app/src/main/res/layout/item_event_timeline_header.xml diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt index 11ffa21b..7eaa8905 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt @@ -5,11 +5,15 @@ import android.content.ClipboardManager import android.content.Context import android.content.Intent import androidx.activity.viewModels +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_SCHEDULE_ID import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND +import com.mashup.core.ui.theme.MashUpTheme import com.mashup.databinding.ActivityScheduleDetailBinding +import com.mashup.ui.attendance.platform.PlatformAttendanceActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest @@ -19,14 +23,20 @@ class ScheduleDetailActivity : BaseActivity() { private val viewModel: ScheduleDetailViewModel by viewModels() - private val eventDetailAdapter by lazy { - EventDetailAdapter(copyToClipboard = ::copyToClipboard) - } - override fun initViews() { - initButton() - viewBinding.rvEvent.apply { - adapter = eventDetailAdapter + super.initViews() + + viewBinding.composeView.setContent { + val state by viewModel.scheduleState.collectAsState() + + MashUpTheme { + ScheduleDetailScreen( + state = state, + copyToClipboard = ::copyToClipboard, + moveToPlatformAttendance = ::moveToPlatformAttendance, + onBackPressed = { finish() }, + ) + } } } @@ -38,15 +48,17 @@ class ScheduleDetailActivity : BaseActivity() { ScheduleState.Loading -> { showLoading() } + is ScheduleState.Success -> { hideLoading() - eventDetailAdapter.submitList(state.eventDetailList) } + is ScheduleState.Error -> { hideLoading() handleCommonError(state.code) handleScheduleDetailErrorCode(state) } + else -> { hideLoading() } @@ -67,12 +79,6 @@ class ScheduleDetailActivity : BaseActivity() { codeMessage?.run { showToast(this) } } - private fun initButton() { - viewBinding.btnReturn.setOnClickListener { - onBackPressed() - } - } - private fun copyToClipboard(text: String) { (getSystemService(CLIPBOARD_SERVICE) as? ClipboardManager)?.let { clipboardManager -> val clip = ClipData.newPlainText("location", text) @@ -80,6 +86,11 @@ class ScheduleDetailActivity : BaseActivity() { } } + private fun moveToPlatformAttendance() { + val intent = PlatformAttendanceActivity.newIntent(this, viewModel.scheduleId) + startActivity(intent) + } + companion object { fun newIntent(context: Context, scheduleId: Int) = Intent(context, ScheduleDetailActivity::class.java).apply { diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt deleted file mode 100644 index 434d7741..00000000 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailAdapter.kt +++ /dev/null @@ -1,173 +0,0 @@ -package com.mashup.ui.schedule.detail - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.compose.foundation.layout.padding -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.ViewCompositionStrategy -import androidx.compose.ui.unit.dp -import androidx.databinding.DataBindingUtil -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ListAdapter -import androidx.recyclerview.widget.RecyclerView -import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.ui.schedule.detail.composable.ScheduleDetailContentItem -import com.mashup.ui.schedule.detail.composable.ScheduleDetailHeaderItem -import com.mashup.ui.schedule.detail.composable.ScheduleDetailInfoItem -import com.mashup.ui.schedule.detail.composable.ScheduleDetailLocationItem -import com.mashup.ui.schedule.model.EventDetail -import com.mashup.ui.schedule.model.EventDetailType - -class EventDetailAdapter( - private val copyToClipboard: (String) -> Unit -) : - ListAdapter(EventComparator) { - - override fun getItemViewType(position: Int): Int { - return getItem(position).type.num - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - return when (viewType) { - EventDetailType.HEADER.num -> { - HeaderViewHolder(ComposeView(parent.context)) - } - EventDetailType.CONTENT.num -> { - ContentViewHolder(ComposeView(parent.context)) - } - EventDetailType.LOCATION.num -> { - LocationViewHolder(ComposeView(parent.context)) - } - EventDetailType.INFO.num -> { - InfoViewHolder(ComposeView(parent.context)) - } - else -> { - InfoViewHolder(ComposeView(parent.context)) - } - } - } - - override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - when (holder) { - is HeaderViewHolder -> { - holder.bind(getItem(position)) - } - is ContentViewHolder -> { - holder.bind(getItem(position)) - } - is LocationViewHolder -> { - holder.bind(getItem(position), copyToClipboard) - } - is InfoViewHolder -> { - holder.bind(getItem(position)) - } - } - } - - class HeaderViewHolder(private val composeView: ComposeView) : RecyclerView.ViewHolder(composeView) { - - fun bind(item: EventDetail) { - if (item !is EventDetail.Header) return - - composeView.setContent { - MashUpTheme { - ScheduleDetailHeaderItem( - isFirstEvent = item.eventId == 1, - title = item.title, - time = item.formattedTime, - ) - } - } - } - } - - class ContentViewHolder(private val composeView: ComposeView) : - RecyclerView.ViewHolder(composeView) { - - fun bind(item: EventDetail) { - if (item !is EventDetail.Content) return - - composeView.setContent { - MashUpTheme { - ScheduleDetailContentItem( - contentId = item.contentId, - title = item.title, - content = item.content, - time = item.formattedTime, - ) - } - } - } - } - - class LocationViewHolder(private val composeView: ComposeView) : - RecyclerView.ViewHolder(composeView) { - init { - composeView.setViewCompositionStrategy( - ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool // (Default) - ) - } - - fun bind(item: EventDetail, copyToClipboard: (String) -> Unit) { - if (item !is EventDetail.Location) return - - composeView.setContent { - MashUpTheme { - ScheduleDetailLocationItem( - detailAddress = item.detailAddress.orEmpty(), - roadAddress = item.roadAddress.orEmpty(), - latitude = item.latitude, - longitude = item.longitude, - copyToClipboard = copyToClipboard - ) - } - } - } - } - - class InfoViewHolder(private val composeView: ComposeView) : - RecyclerView.ViewHolder(composeView) { - init { - composeView.setViewCompositionStrategy( - ViewCompositionStrategy.DisposeOnDetachedFromWindowOrReleasedFromPool // (Default) - ) - } - - fun bind(item: EventDetail) { - if (item !is EventDetail.Info) return - - composeView.setContent { - MashUpTheme { - ScheduleDetailInfoItem( - title = item.title, - date = item.date, - time = item.formattedTime, - modifier = Modifier.padding(top = 24.dp) - ) - } - } - } - } - - interface OnItemEventListener { - fun onExitEventClick() - } -} - -object EventComparator : DiffUtil.ItemCallback() { - override fun areItemsTheSame( - oldItem: EventDetail, - newItem: EventDetail - ): Boolean { - return oldItem.index == newItem.index - } - - override fun areContentsTheSame( - oldItem: EventDetail, - newItem: EventDetail - ): Boolean { - return oldItem == newItem - } -} diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt new file mode 100644 index 00000000..65bd2f10 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt @@ -0,0 +1,141 @@ +package com.mashup.ui.schedule.detail + +import androidx.compose.foundation.LocalOverscrollConfiguration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.widget.ButtonStyle +import com.mashup.core.ui.widget.MashUpButton +import com.mashup.core.ui.widget.MashUpToolbar +import com.mashup.ui.schedule.detail.composable.ScheduleDetailContentItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailHeaderItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailInfoItem +import com.mashup.ui.schedule.detail.composable.ScheduleDetailLocationItem +import com.mashup.ui.schedule.model.EventDetail + +@Composable +fun ScheduleDetailScreen( + state: ScheduleState, + copyToClipboard: (String) -> Unit, + moveToPlatformAttendance: () -> Unit, + onBackPressed: () -> Unit, +) { + Box(modifier = Modifier.fillMaxSize()) { + Column { + MashUpToolbar( + title = "상세 스케쥴", + showBackButton = true, + onClickBackButton = onBackPressed + ) + + when (state) { + is ScheduleState.Empty -> {} + is ScheduleState.Success -> EventDetailList(state.eventDetailList, copyToClipboard) + else -> {} + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .height(140.dp) + .background( + brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + Color.White + ) + ) + ) + .align(Alignment.BottomCenter) + ) + + MashUpButton( + text = "플랫폼 출석현황 보러가기", + onClick = moveToPlatformAttendance, + modifier = Modifier + .fillMaxWidth() + .padding(start = 20.dp, bottom = 28.dp, end = 20.dp) + .align(Alignment.BottomCenter), + buttonStyle = ButtonStyle.INVERSE, + ) + } +} + +@Composable +fun EventDetailList(eventDetailList: List, copyToClipboard: (String) -> Unit) { + CompositionLocalProvider( + LocalOverscrollConfiguration provides null + ) { + LazyColumn( + modifier = Modifier + .padding(start = 20.dp, bottom = 60.dp, end = 20.dp) + ) { + itemsIndexed(eventDetailList) { _, item -> + when (item) { + is EventDetail.Info -> { + ScheduleDetailInfoItem( + title = item.title, + date = item.date, + time = item.title, + ) + } + + is EventDetail.Location -> { + ScheduleDetailLocationItem( + detailAddress = item.detailAddress, + roadAddress = item.roadAddress, + latitude = item.latitude, + longitude = item.longitude, + copyToClipboard = copyToClipboard, + ) + } + + is EventDetail.Header -> { + ScheduleDetailHeaderItem( + isFirstEvent = item.eventId == 1, + title = item.title, + time = item.formattedTime, + ) + } + + is EventDetail.Content -> { + ScheduleDetailContentItem( + contentId = item.contentId, + title = item.title, + content = item.content, + time = item.formattedTime, + ) + } + } + } + + item { + Spacer(modifier = Modifier.height(28.dp)) + } + } + } +} + +@Preview +@Composable +fun PreviewScheduleDetailScreen() { + MashUpTheme { + ScheduleDetailScreen( + state = ScheduleState.Empty, + copyToClipboard = {}, + moveToPlatformAttendance = {}, + onBackPressed = {} + ) + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt index e33440db..4841e3d2 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt @@ -17,10 +17,7 @@ class ScheduleDetailViewModel @Inject constructor( private val eventMapper: EventDetailMapper, savedStateHandle: SavedStateHandle ) : BaseViewModel() { - private val scheduleId = - checkNotNull( - savedStateHandle.get(EXTRA_SCHEDULE_ID) - ) + val scheduleId = checkNotNull(savedStateHandle.get(EXTRA_SCHEDULE_ID)) private val _scheduleState = MutableStateFlow(ScheduleState.Empty) val scheduleState: StateFlow = _scheduleState diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleInfoText.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleInfoText.kt index 033bb9e2..f5dda445 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleInfoText.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleInfoText.kt @@ -17,7 +17,7 @@ import androidx.compose.ui.unit.dp import com.mashup.core.ui.colors.Gray300 import com.mashup.core.ui.colors.Gray700 import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.core.ui.typography.Body3 +import com.mashup.core.ui.typography.Body4 import com.mashup.core.common.R as CR @Composable @@ -39,7 +39,7 @@ fun ScheduleInfoText( Spacer(modifier = Modifier.width(4.dp)) - Text(text = info, style = Body3, color = Gray700) + Text(text = info, style = Body4, color = Gray700) } } diff --git a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt index 919a80ab..2648ef45 100644 --- a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt +++ b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt @@ -29,8 +29,8 @@ sealed class EventDetail( data class Location( override val index: Int, - val detailAddress: String?, - val roadAddress: String?, + val detailAddress: String, + val roadAddress: String, val latitude: Double?, val longitude: Double? ) : EventDetail(index, EventDetailType.LOCATION) diff --git a/app/src/main/res/layout/activity_schedule_detail.xml b/app/src/main/res/layout/activity_schedule_detail.xml index a72893a3..b54c29ba 100644 --- a/app/src/main/res/layout/activity_schedule_detail.xml +++ b/app/src/main/res/layout/activity_schedule_detail.xml @@ -1,35 +1,8 @@ - + - - - - - - + android:layout_height="match_parent" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_event_timeline_content.xml b/app/src/main/res/layout/item_event_timeline_content.xml deleted file mode 100644 index 65db7015..00000000 --- a/app/src/main/res/layout/item_event_timeline_content.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/item_event_timeline_header.xml b/app/src/main/res/layout/item_event_timeline_header.xml deleted file mode 100644 index 603c2ba4..00000000 --- a/app/src/main/res/layout/item_event_timeline_header.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - From bee76599f3871e63e1b0d4d624df0c589c58f450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Thu, 27 Jun 2024 16:49:48 +0900 Subject: [PATCH 011/110] =?UTF-8?q?=F0=9F=A7=B8=20=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=A4=84=20=EC=83=81=EC=84=B8=20=ED=99=94=EB=A9=B4=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=EC=83=89=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt | 3 +++ app/src/main/res/layout/activity_schedule_detail.xml | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt index 7eaa8905..3e97005d 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt @@ -10,7 +10,9 @@ import androidx.compose.runtime.getValue import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_SCHEDULE_ID +import com.mashup.core.common.R as CR import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND +import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.ui.theme.MashUpTheme import com.mashup.databinding.ActivityScheduleDetailBinding import com.mashup.ui.attendance.platform.PlatformAttendanceActivity @@ -26,6 +28,7 @@ class ScheduleDetailActivity : BaseActivity() { override fun initViews() { super.initViews() + setStatusBarColorRes(CR.color.white) viewBinding.composeView.setContent { val state by viewModel.scheduleState.collectAsState() diff --git a/app/src/main/res/layout/activity_schedule_detail.xml b/app/src/main/res/layout/activity_schedule_detail.xml index b54c29ba..3ae97818 100644 --- a/app/src/main/res/layout/activity_schedule_detail.xml +++ b/app/src/main/res/layout/activity_schedule_detail.xml @@ -4,5 +4,6 @@ + android:layout_height="match_parent" + android:background="@color/white" /> \ No newline at end of file From 37d367a0821e297c3000a2fa04ea3c091a0145b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Thu, 27 Jun 2024 17:05:47 +0900 Subject: [PATCH 012/110] =?UTF-8?q?=F0=9F=A7=B8=20=EC=99=80=EC=9D=BC?= =?UTF-8?q?=EB=93=9C=EC=B9=B4=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt index 65bd2f10..d37a4979 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt @@ -2,7 +2,13 @@ package com.mashup.ui.schedule.detail import androidx.compose.foundation.LocalOverscrollConfiguration import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +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.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.runtime.Composable From b4c24da92356ea77c050eb11a558708df3fcc53b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= <21200203@mobmail.shinhan.com> Date: Thu, 27 Jun 2024 17:18:09 +0900 Subject: [PATCH 013/110] =?UTF-8?q?=F0=9F=A7=B8=20Lint=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/schedule/detail/ScheduleDetailActivity.kt | 4 ++-- .../ui/schedule/detail/ScheduleDetailScreen.kt | 12 ++++++------ .../ui/schedule/detail/ScheduleDetailViewModel.kt | 2 +- .../detail/composable/ScheduleDetailContentItem.kt | 8 ++++---- .../detail/composable/ScheduleDetailHeaderItem.kt | 8 ++++---- .../java/com/mashup/ui/schedule/model/EventDetail.kt | 4 ++-- .../mashup/ui/schedule/model/EventDetailMapper.kt | 8 ++++---- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt index 3e97005d..d1eac1eb 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailActivity.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.getValue import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_SCHEDULE_ID -import com.mashup.core.common.R as CR import com.mashup.core.common.constant.SCHEDULE_NOT_FOUND import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.ui.theme.MashUpTheme @@ -18,6 +17,7 @@ import com.mashup.databinding.ActivityScheduleDetailBinding import com.mashup.ui.attendance.platform.PlatformAttendanceActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest +import com.mashup.core.common.R as CR @AndroidEntryPoint class ScheduleDetailActivity : BaseActivity() { @@ -37,7 +37,7 @@ class ScheduleDetailActivity : BaseActivity() { state = state, copyToClipboard = ::copyToClipboard, moveToPlatformAttendance = ::moveToPlatformAttendance, - onBackPressed = { finish() }, + onBackPressed = { finish() } ) } } diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt index d37a4979..59db9907 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailScreen.kt @@ -34,7 +34,7 @@ fun ScheduleDetailScreen( state: ScheduleState, copyToClipboard: (String) -> Unit, moveToPlatformAttendance: () -> Unit, - onBackPressed: () -> Unit, + onBackPressed: () -> Unit ) { Box(modifier = Modifier.fillMaxSize()) { Column { @@ -73,7 +73,7 @@ fun ScheduleDetailScreen( .fillMaxWidth() .padding(start = 20.dp, bottom = 28.dp, end = 20.dp) .align(Alignment.BottomCenter), - buttonStyle = ButtonStyle.INVERSE, + buttonStyle = ButtonStyle.INVERSE ) } } @@ -93,7 +93,7 @@ fun EventDetailList(eventDetailList: List, copyToClipboard: (String ScheduleDetailInfoItem( title = item.title, date = item.date, - time = item.title, + time = item.title ) } @@ -103,7 +103,7 @@ fun EventDetailList(eventDetailList: List, copyToClipboard: (String roadAddress = item.roadAddress, latitude = item.latitude, longitude = item.longitude, - copyToClipboard = copyToClipboard, + copyToClipboard = copyToClipboard ) } @@ -111,7 +111,7 @@ fun EventDetailList(eventDetailList: List, copyToClipboard: (String ScheduleDetailHeaderItem( isFirstEvent = item.eventId == 1, title = item.title, - time = item.formattedTime, + time = item.formattedTime ) } @@ -120,7 +120,7 @@ fun EventDetailList(eventDetailList: List, copyToClipboard: (String contentId = item.contentId, title = item.title, content = item.content, - time = item.formattedTime, + time = item.formattedTime ) } } diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt index 4841e3d2..f074d0ff 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/ScheduleDetailViewModel.kt @@ -35,7 +35,7 @@ class ScheduleDetailViewModel @Inject constructor( title = response.name, date = response.getDate(), eventList = response.eventList, - location = response.location, + location = response.location ) _scheduleState.emit(ScheduleState.Success(eventList)) diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt index 7e36bde8..99223626 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailContentItem.kt @@ -30,7 +30,7 @@ fun ScheduleDetailContentItem( contentId: String, title: String, content: String, - time: String, + time: String ) { Column(modifier = Modifier.padding(vertical = 8.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { @@ -39,12 +39,12 @@ fun ScheduleDetailContentItem( .size(20.dp) .clip(CircleShape) .background(Gray100), - contentAlignment = Alignment.Center, + contentAlignment = Alignment.Center ) { Text( text = contentId, style = Caption2, - color = Gray600, + color = Gray600 ) } @@ -59,7 +59,7 @@ fun ScheduleDetailContentItem( Text( text = time, style = Caption1, - color = Gray400, + color = Gray400 ) } diff --git a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt index a3613dd2..503dcd45 100644 --- a/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/detail/composable/ScheduleDetailHeaderItem.kt @@ -33,7 +33,7 @@ import com.mashup.core.ui.typography.Header2 fun ScheduleDetailHeaderItem( isFirstEvent: Boolean, title: String, - time: String, + time: String ) { Column { if (isFirstEvent.not()) { @@ -54,7 +54,7 @@ fun ScheduleDetailHeaderItem( .clip(CircleShape) .background(Brand100) .padding(horizontal = 8.dp, vertical = 4.dp), - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = Alignment.CenterVertically ) { Image( painter = painterResource(id = R.drawable.ic_clock), @@ -67,7 +67,7 @@ fun ScheduleDetailHeaderItem( Text( text = time, style = Caption1, - color = Brand500, + color = Brand500 ) } } @@ -81,7 +81,7 @@ fun PreviewScheduleDetailHeaderItem() { ScheduleDetailHeaderItem( isFirstEvent = false, title = "1부", - time = "10:00 - 11:00", + time = "10:00 - 11:00" ) } } diff --git a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt index 2648ef45..d6237fee 100644 --- a/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt +++ b/app/src/main/java/com/mashup/ui/schedule/model/EventDetail.kt @@ -5,7 +5,7 @@ import java.util.Date sealed class EventDetail( open val index: Int, - val type: EventDetailType, + val type: EventDetailType ) { data class Header( override val index: Int, @@ -40,7 +40,7 @@ sealed class EventDetail( val title: String, val date: String, val startedAt: Date, - val endedAt: Date, + val endedAt: Date ) : EventDetail(index, EventDetailType.INFO) { val formattedTime = "${startedAt.getTimeFormat()} - ${endedAt.getTimeFormat()}" } diff --git a/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt b/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt index de0b4718..be290dfa 100644 --- a/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt +++ b/app/src/main/java/com/mashup/ui/schedule/model/EventDetailMapper.kt @@ -42,7 +42,7 @@ class EventDetailMapper @Inject constructor() { index = index, eventId = eventIndex + 1, startedAt = event.startedAt, - endedAt = event.endedAt, + endedAt = event.endedAt ) } @@ -56,7 +56,7 @@ class EventDetailMapper @Inject constructor() { contentId = "${contentIndex + 1}", title = content.title, content = content.content.orEmpty(), - startedAt = content.startedAt, + startedAt = content.startedAt ) } @@ -75,14 +75,14 @@ class EventDetailMapper @Inject constructor() { title: String, date: String, startedAt: Date, - endedAt: Date, + endedAt: Date ): EventDetail { return EventDetail.Info( index = index, title = title, date = date, startedAt = startedAt, - endedAt = endedAt, + endedAt = endedAt ) } } From c15f4bfb42960e8de90aa2a8a28d96e6199dae80 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 15:45:26 +0900 Subject: [PATCH 014/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20MashUpGradient?= =?UTF-8?q?=20Button=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/schedule/item/EmptyScheduleItem.kt | 20 ++++- .../com/mashup/core/ui/widget/MashUpButton.kt | 87 ++++++++++--------- .../core/ui/widget/MashUpGradientButton.kt | 61 +++++++++++++ 3 files changed, 125 insertions(+), 43 deletions(-) create mode 100644 core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt index 4cedc458..b3b474ad 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt @@ -1,7 +1,9 @@ package com.mashup.ui.schedule.item import androidx.compose.foundation.Image +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.height import androidx.compose.foundation.layout.width @@ -15,7 +17,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Header2 -import com.mashup.core.ui.widget.MashUpButton +import com.mashup.core.ui.widget.MashUpGradientButton import com.mashup.core.common.R as CommonR @Composable @@ -42,7 +44,15 @@ fun EmptyScheduleItem( style = Header2, color = Color(0xFF412491), ) - MashUpButton(text = "매숑이 밥주러 가기", buttonHeight = 48.dp, onClick = onClickMashongButton) + MashUpGradientButton( + modifier = Modifier.width(256.dp).height(48.dp), + text = "매숑이 밥주러 가기", + onClick = onClickMashongButton, + gradientColors = listOf( + Color(0xFFB398FE), + Color(0xFF47BBF1), + ), + ) } } @@ -50,6 +60,10 @@ fun EmptyScheduleItem( @Composable private fun PreviewEmptyScheduleItem() { MashUpTheme { - EmptyScheduleItem() + Box( + modifier =Modifier.background(color= Color.White) + ){ + EmptyScheduleItem() + } } } diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt index 0d2c28d6..dd8428ca 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt @@ -46,60 +46,64 @@ import com.mashup.core.ui.colors.White import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Body1 -enum class ButtonStyle(val backgroundColor: Color, val textColor: Color) { +enum class ButtonStyle( + val backgroundColor: Color, + val textColor: Color, +) { PRIMARY(backgroundColor = Brand500, textColor = White), INVERSE(backgroundColor = Brand100, textColor = Brand500), DISABLE(backgroundColor = Brand300, textColor = White), DARK(backgroundColor = Gray800, textColor = White), - DEFAULT(backgroundColor = Gray100, textColor = Gray600) + DEFAULT(backgroundColor = Gray100, textColor = Gray600), } @Composable fun MashUpButton( modifier: Modifier = Modifier, buttonStyle: ButtonStyle = ButtonStyle.PRIMARY, - buttonHeight : Dp = 52.dp, - buttonWidth : Dp = 256.dp, text: String, onClick: () -> Unit, isEnabled: Boolean = true, showLoading: Boolean = false, ) { Box( - modifier = modifier - .clip(RoundedCornerShape(12.dp)) - .height(buttonHeight) - .background(if (isEnabled) buttonStyle.backgroundColor else ButtonStyle.DISABLE.backgroundColor) - .padding(horizontal = 20.dp) - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - enabled = isEnabled || showLoading, - onClick = onClick - ), - contentAlignment = Alignment.Center + modifier = + modifier + .clip(RoundedCornerShape(12.dp)) + .height(52.dp) + .background(if (isEnabled) buttonStyle.backgroundColor else ButtonStyle.DISABLE.backgroundColor) + .padding(horizontal = 20.dp) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + enabled = isEnabled || showLoading, + onClick = onClick, + ), + contentAlignment = Alignment.Center, ) { Row( horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { AnimatedVisibility( visible = showLoading, enter = fadeIn(), - exit = fadeOut() + exit = fadeOut(), ) { ButtonCircularProgressbar( - modifier = Modifier - .padding(end = 8.dp) - .size(20.dp) + modifier = + Modifier + .padding(end = 8.dp) + .size(20.dp), ) } Text( text = text, - style = Body1.copy( - color = buttonStyle.textColor - ) + style = + Body1.copy( + color = buttonStyle.textColor, + ), ) } } @@ -111,17 +115,19 @@ fun ButtonCircularProgressbar( progressBarWidth: Dp = 3.dp, progressBarColor: Color = Color(0xFFFFFFFF), backgroundProgressBarColor: Color = Color(0x80FFFFFF), - progressDuration: Int = 500 + progressDuration: Int = 500, ) { val infiniteTransition = rememberInfiniteTransition() val angle by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 360f, - animationSpec = infiniteRepeatable( - animation = keyframes { - durationMillis = progressDuration - } - ) + animationSpec = + infiniteRepeatable( + animation = + keyframes { + durationMillis = progressDuration + }, + ), ) Canvas(modifier = modifier.fillMaxSize()) { @@ -132,7 +138,7 @@ fun ButtonCircularProgressbar( drawCircle( color = backgroundProgressBarColor, radius = radius, - style = Stroke(width = progressBarWidth.toPx()) + style = Stroke(width = progressBarWidth.toPx()), ) // ProgressBar(Arc) @@ -143,10 +149,11 @@ fun ButtonCircularProgressbar( useCenter = false, topLeft = size.center - Offset(radius, radius), size = Size(radius * 2, radius * 2), - style = Stroke( - width = progressBarWidth.toPx(), - cap = StrokeCap.Round - ) + style = + Stroke( + width = progressBarWidth.toPx(), + cap = StrokeCap.Round, + ), ) } } @@ -157,7 +164,7 @@ fun PrevButtonCircularProgressbar() { MashUpTheme { Box { ButtonCircularProgressbar( - modifier = Modifier.size(20.dp) + modifier = Modifier.size(20.dp), ) } } @@ -173,21 +180,21 @@ fun PrevMashUpButton() { buttonStyle = ButtonStyle.PRIMARY, text = "다음", onClick = {}, - showLoading = true + showLoading = true, ) MashUpButton( modifier = Modifier.padding(16.dp), buttonStyle = ButtonStyle.PRIMARY, text = "다음", - onClick = {} + onClick = {}, ) MashUpButton( modifier = Modifier.padding(16.dp), buttonStyle = ButtonStyle.DEFAULT, text = "다음", - onClick = {} + onClick = {}, ) MashUpButton( @@ -195,7 +202,7 @@ fun PrevMashUpButton() { buttonStyle = ButtonStyle.PRIMARY, text = "다음", onClick = {}, - isEnabled = false + isEnabled = false, ) } } diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt new file mode 100644 index 00000000..566d1183 --- /dev/null +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt @@ -0,0 +1,61 @@ +package com.mashup.core.ui.widget + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.typography.Body3 + +@Composable +fun MashUpGradientButton( + modifier: Modifier = Modifier, + text: String = "", + onClick: () -> Unit = {}, + isEnabled: Boolean = true, + gradientColors: List = listOf(), +) { + Box( + modifier = + modifier + .clip(RoundedCornerShape(12.dp)) + .background( + brush = + Brush.linearGradient( + colors = gradientColors, + ), + ).padding(horizontal = 20.dp) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + enabled = isEnabled, + onClick = onClick, + ), + contentAlignment = Alignment.Center, + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Text( + text = text, + style = + Body3.copy( + color = Color.White, + ), + ) + } + } +} From 0330d79a165bc8c542d7ed071d9578af854c8324 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 18:43:33 +0900 Subject: [PATCH 015/110] =?UTF-8?q?=F0=9F=9B=A0refactor=20:=20apply=20lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/schedule/component/ScheduleTabRow.kt | 18 ++-- .../ui/schedule/item/EmptyScheduleItem.kt | 25 +++--- .../com/mashup/core/ui/widget/MashUpButton.kt | 85 +++++++++---------- .../core/ui/widget/MashUpGradientButton.kt | 43 +++++----- 4 files changed, 85 insertions(+), 86 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt index 7f066b78..2fc4434c 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -79,12 +79,14 @@ fun ScheduleTabRow( indicator = { tabPositions -> TabRowDefaults.Indicator( color = Gray950, - modifier = Modifier.customTabIndicatorOffset( - tabPositions[selectedTabIndex], - tabWidth = 150.dp - ).clip( - RoundedCornerShape(20.dp) - ) + modifier = Modifier + .customTabIndicatorOffset( + tabPositions[selectedTabIndex], + tabWidth = 150.dp + ) + .clip( + RoundedCornerShape(20.dp) + ) ) }, tabs = { @@ -154,7 +156,9 @@ private fun PreviewTabRow() { var selectedTabIndex by remember { mutableIntStateOf(0) } ScheduleTabRow( - modifier = Modifier.fillMaxWidth().background(color = Color.White), + modifier = Modifier + .fillMaxWidth() + .background(color = Color.White), selectedTabIndex = selectedTabIndex, updateSelectedTabIndex = { selectedTabIndex = it diff --git a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt index b3b474ad..5a585552 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt @@ -23,35 +23,36 @@ import com.mashup.core.common.R as CommonR @Composable fun EmptyScheduleItem( modifier: Modifier = Modifier, - onClickMashongButton: () -> Unit = {}, + onClickMashongButton: () -> Unit = {} ) { Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(17.dp), + verticalArrangement = Arrangement.spacedBy(17.dp) ) { Image( painter = painterResource(id = CommonR.drawable.img_empty_schdule), contentDescription = null, - modifier = - Modifier - .width(284.dp) - .height(256.dp), + modifier = Modifier + .width(284.dp) + .height(256.dp) ) Text( text = "이번주는 자유다..!", style = Header2, - color = Color(0xFF412491), + color = Color(0xFF412491) ) MashUpGradientButton( - modifier = Modifier.width(256.dp).height(48.dp), + modifier = Modifier + .width(256.dp) + .height(48.dp), text = "매숑이 밥주러 가기", onClick = onClickMashongButton, gradientColors = listOf( Color(0xFFB398FE), - Color(0xFF47BBF1), - ), + Color(0xFF47BBF1) + ) ) } } @@ -61,8 +62,8 @@ fun EmptyScheduleItem( private fun PreviewEmptyScheduleItem() { MashUpTheme { Box( - modifier =Modifier.background(color= Color.White) - ){ + modifier = Modifier.background(color = Color.White) + ) { EmptyScheduleItem() } } diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt index dd8428ca..ba7213b7 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpButton.kt @@ -48,13 +48,13 @@ import com.mashup.core.ui.typography.Body1 enum class ButtonStyle( val backgroundColor: Color, - val textColor: Color, + val textColor: Color ) { PRIMARY(backgroundColor = Brand500, textColor = White), INVERSE(backgroundColor = Brand100, textColor = Brand500), DISABLE(backgroundColor = Brand300, textColor = White), DARK(backgroundColor = Gray800, textColor = White), - DEFAULT(backgroundColor = Gray100, textColor = Gray600), + DEFAULT(backgroundColor = Gray100, textColor = Gray600) } @Composable @@ -64,46 +64,43 @@ fun MashUpButton( text: String, onClick: () -> Unit, isEnabled: Boolean = true, - showLoading: Boolean = false, + showLoading: Boolean = false ) { Box( - modifier = - modifier - .clip(RoundedCornerShape(12.dp)) - .height(52.dp) - .background(if (isEnabled) buttonStyle.backgroundColor else ButtonStyle.DISABLE.backgroundColor) - .padding(horizontal = 20.dp) - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - enabled = isEnabled || showLoading, - onClick = onClick, - ), - contentAlignment = Alignment.Center, + modifier = modifier + .clip(RoundedCornerShape(12.dp)) + .height(52.dp) + .background(if (isEnabled) buttonStyle.backgroundColor else ButtonStyle.DISABLE.backgroundColor) + .padding(horizontal = 20.dp) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + enabled = isEnabled || showLoading, + onClick = onClick + ), + contentAlignment = Alignment.Center ) { Row( horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = Alignment.CenterVertically ) { AnimatedVisibility( visible = showLoading, enter = fadeIn(), - exit = fadeOut(), + exit = fadeOut() ) { ButtonCircularProgressbar( - modifier = - Modifier - .padding(end = 8.dp) - .size(20.dp), + modifier = Modifier + .padding(end = 8.dp) + .size(20.dp) ) } Text( text = text, - style = - Body1.copy( - color = buttonStyle.textColor, - ), + style = Body1.copy( + color = buttonStyle.textColor + ) ) } } @@ -115,19 +112,18 @@ fun ButtonCircularProgressbar( progressBarWidth: Dp = 3.dp, progressBarColor: Color = Color(0xFFFFFFFF), backgroundProgressBarColor: Color = Color(0x80FFFFFF), - progressDuration: Int = 500, + progressDuration: Int = 500 ) { val infiniteTransition = rememberInfiniteTransition() val angle by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 360f, - animationSpec = - infiniteRepeatable( - animation = - keyframes { - durationMillis = progressDuration - }, - ), + animationSpec = infiniteRepeatable( + animation = + keyframes { + durationMillis = progressDuration + } + ) ) Canvas(modifier = modifier.fillMaxSize()) { @@ -138,7 +134,7 @@ fun ButtonCircularProgressbar( drawCircle( color = backgroundProgressBarColor, radius = radius, - style = Stroke(width = progressBarWidth.toPx()), + style = Stroke(width = progressBarWidth.toPx()) ) // ProgressBar(Arc) @@ -149,11 +145,10 @@ fun ButtonCircularProgressbar( useCenter = false, topLeft = size.center - Offset(radius, radius), size = Size(radius * 2, radius * 2), - style = - Stroke( - width = progressBarWidth.toPx(), - cap = StrokeCap.Round, - ), + style = Stroke( + width = progressBarWidth.toPx(), + cap = StrokeCap.Round + ) ) } } @@ -164,7 +159,7 @@ fun PrevButtonCircularProgressbar() { MashUpTheme { Box { ButtonCircularProgressbar( - modifier = Modifier.size(20.dp), + modifier = Modifier.size(20.dp) ) } } @@ -180,21 +175,21 @@ fun PrevMashUpButton() { buttonStyle = ButtonStyle.PRIMARY, text = "다음", onClick = {}, - showLoading = true, + showLoading = true ) MashUpButton( modifier = Modifier.padding(16.dp), buttonStyle = ButtonStyle.PRIMARY, text = "다음", - onClick = {}, + onClick = {} ) MashUpButton( modifier = Modifier.padding(16.dp), buttonStyle = ButtonStyle.DEFAULT, text = "다음", - onClick = {}, + onClick = {} ) MashUpButton( @@ -202,7 +197,7 @@ fun PrevMashUpButton() { buttonStyle = ButtonStyle.PRIMARY, text = "다음", onClick = {}, - isEnabled = false, + isEnabled = false ) } } diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt index 566d1183..1c498c7e 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt @@ -25,36 +25,35 @@ fun MashUpGradientButton( text: String = "", onClick: () -> Unit = {}, isEnabled: Boolean = true, - gradientColors: List = listOf(), + gradientColors: List = listOf() ) { Box( - modifier = - modifier - .clip(RoundedCornerShape(12.dp)) - .background( - brush = - Brush.linearGradient( - colors = gradientColors, - ), - ).padding(horizontal = 20.dp) - .clickable( - indication = null, - interactionSource = remember { MutableInteractionSource() }, - enabled = isEnabled, - onClick = onClick, - ), - contentAlignment = Alignment.Center, + modifier = modifier + .clip(RoundedCornerShape(12.dp)) + .background( + brush = + Brush.linearGradient( + colors = gradientColors + ) + ) + .padding(horizontal = 20.dp) + .clickable( + indication = null, + interactionSource = remember { MutableInteractionSource() }, + enabled = isEnabled, + onClick = onClick + ), + contentAlignment = Alignment.Center ) { Row( horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, + verticalAlignment = Alignment.CenterVertically ) { Text( text = text, - style = - Body3.copy( - color = Color.White, - ), + style = Body3.copy( + color = Color.White + ) ) } } From 991391d95dc69cab894ec4b9dd0985e93040d6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sat, 29 Jun 2024 19:26:11 +0900 Subject: [PATCH 016/110] =?UTF-8?q?=F0=9F=A7=B8=20HtmlText=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EC=A0=80=EB=B8=94=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20?= =?UTF-8?q?ScheduleTopbar=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleScreen.kt | 96 +++++++++---------- app/src/main/res/values/strings.xml | 6 +- core/common/src/main/res/drawable/ic_more.xml | 24 +++++ .../mashup/core/ui/widget/MashUpHtmlText.kt | 40 ++++++++ 4 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 core/common/src/main/res/drawable/ic_more.xml create mode 100644 core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 8aa9b5e2..4fdc28fb 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -1,7 +1,6 @@ package com.mashup.ui.schedule import android.content.Context -import androidx.appcompat.widget.AppCompatTextView import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -9,9 +8,12 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.rememberPagerState @@ -27,7 +29,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue 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 @@ -35,26 +36,26 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.mashup.R import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM +import com.mashup.core.common.R as CR import com.mashup.core.common.extensions.fromHtml import com.mashup.core.ui.colors.Brand500 +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.widget.MashUpHtmlText import com.mashup.ui.attendance.platform.PlatformAttendanceActivity -import com.mashup.ui.danggn.ShakeDanggnActivity import com.mashup.ui.main.MainViewModel -import com.mashup.ui.main.model.MainPopupType import com.mashup.ui.schedule.detail.ScheduleDetailActivity import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem import com.mashup.ui.schedule.item.ScheduleViewPagerSuccessItem import com.mashup.ui.schedule.model.ScheduleCard import com.mashup.util.AnalyticsManager -import com.mashup.util.debounce import kotlin.math.abs import kotlin.math.absoluteValue @@ -113,52 +114,15 @@ fun ScheduleRoute( Column( modifier = modifier ) { - Row( - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 24.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - AndroidView( - factory = { context -> - AppCompatTextView( - context - ).apply { - setTextAppearance( - com.mashup.core.common.R.style.TextAppearance_Mashup_Header1_24_B - ) - text = title - } - }, - update = { view -> - view.text = title - } - ) - if (title.isNotEmpty()) { - val coroutineScope = rememberCoroutineScope() - Image( - modifier = Modifier.clickable { - debounce(500L, scope = coroutineScope, destinationFunction = { - mainViewModel.disablePopup(MainPopupType.DANGGN) - }) - context.startActivity( - ShakeDanggnActivity.newIntent(context) - ) - }, - painter = painterResource( - id = com.mashup.core.common.R.drawable.img_carrot_button - ), - contentDescription = null - ) - } - } + ScheduleTopbar(title) when (state) { is ScheduleState.Error -> {} is ScheduleState.Empty -> {} else -> { ScheduleScreen( - modifier = Modifier.fillMaxSize().verticalScroll(scrollState), + modifier = Modifier + .fillMaxSize() + .verticalScroll(scrollState), scheduleState = state, onClickScheduleInformation = { scheduleId: Int -> AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) @@ -290,6 +254,7 @@ fun ScheduleScreen( else -> {} } } + fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String { return when (scheduleTitleState) { ScheduleTitleState.Empty -> { @@ -299,10 +264,45 @@ fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String getString(R.string.end_schedule, scheduleTitleState.generatedNumber) } is ScheduleTitleState.DateCount -> { - getString(R.string.event_list_title, scheduleTitleState.dataCount).fromHtml().toString() + getString(R.string.event_list_title, scheduleTitleState.dataCount) } is ScheduleTitleState.SchedulePreparing -> { getString(R.string.preparing_attendance) } } } + +@Composable +fun ScheduleTopbar(title: String) { + Row( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 24.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + MashUpHtmlText( + content = title.fromHtml(), + modifier = Modifier.weight(1f, false), + textAppearance = CR.style.TextAppearance_Mashup_Header1_24_B, + ) + Spacer(modifier = Modifier.width(8.dp)) + Image( + painter = painterResource(id = CR.drawable.ic_more), + contentDescription = null, + modifier = Modifier + .size(20.dp) + .clickable { + // TODO: 메뉴 화면으로 이동, 당근 Popup Disable 처리 + }, + ) + } +} + +@Preview +@Composable +fun PreviewScheduleTopbar() { + MashUpTheme { + ScheduleTopbar(title = "다음 세미나 준비 중이에요.\n조금만 기다려주세요.") + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cc2787a2..11b8c39a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,10 +44,10 @@ 다시시도 돌아가기 - 일정 준비 중이에요.\n조금만 기다려주세요! - %d기 모든 활동이\n종료되었어요. + 조금만 기다려주세요!]]> + 종료되었어요.]]> %s님의\n출석을 기다리고 있어요!]]> - 열심히 일정을 준비하고 있어요\n조금만 기다려 주세요! + D-? 등록된 일정이 없어요 매시업 크루들의 출석현황이 궁금하다면? diff --git a/core/common/src/main/res/drawable/ic_more.xml b/core/common/src/main/res/drawable/ic_more.xml new file mode 100644 index 00000000..bc35f209 --- /dev/null +++ b/core/common/src/main/res/drawable/ic_more.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt new file mode 100644 index 00000000..a3133517 --- /dev/null +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt @@ -0,0 +1,40 @@ +package com.mashup.core.ui.widget + +import android.text.Spanned +import androidx.annotation.StyleRes +import androidx.appcompat.widget.AppCompatTextView +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidView + +/** + * MashUpHtmlText.kt + * + * Created by Minji Jeong on 2024/06/29 + * Copyright © 2024 MashUp All rights reserved. + */ + +@Composable +fun MashUpHtmlText( + content: Spanned, + modifier: Modifier = Modifier, + @StyleRes textAppearance: Int? = null +) { + AndroidView( + factory = { context -> + AppCompatTextView( + context + ).apply { + if (textAppearance != null) { + setTextAppearance(textAppearance) + } + text = content + includeFontPadding = false + } + }, + modifier = modifier, + update = { view -> + view.text = content + }, + ) +} From 50221ca4290cca43050fd22e9351fcca3f5bbda7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sat, 29 Jun 2024 20:19:06 +0900 Subject: [PATCH 017/110] =?UTF-8?q?=F0=9F=A7=B8=20Schedule=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=20Tab=20=EC=B6=94=EA=B0=80=20(=EC=9D=B4?= =?UTF-8?q?=EB=B2=88=20=EC=A3=BC=20=EC=9D=BC=EC=A0=95=20/=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EC=9D=BC=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ScheduleRoute, ScheduleScreen 파일 분리 - StatueBar 생상 White로 변경 --- .../com/mashup/ui/mypage/MyPageFragment.kt | 7 + .../mashup/ui/schedule/ScheduleFragment.kt | 3 + .../com/mashup/ui/schedule/ScheduleRoute.kt | 209 ++++++++++++++++++ .../com/mashup/ui/schedule/ScheduleScreen.kt | 182 --------------- .../ui/schedule/component/ScheduleTabRow.kt | 3 - 5 files changed, 219 insertions(+), 185 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt diff --git a/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt b/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt index a4310bba..5b154dd8 100644 --- a/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt +++ b/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt @@ -9,6 +9,8 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels import com.mashup.R import com.mashup.base.BaseFragment +import com.mashup.core.common.R as CR +import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.databinding.FragmentMyPageBinding import com.mashup.feature.mypage.profile.model.ProfileCardData import com.mashup.ui.setting.SettingActivity @@ -62,10 +64,15 @@ class MyPageFragment : BaseFragment() { override fun initViews() { super.initViews() + initStatusBar() initSwipeRefresh() initRecyclerView() } + private fun initStatusBar() { + requireActivity().setStatusBarColorRes(CR.color.gray50) + } + private fun initSwipeRefresh() { viewBinding.layoutSwipe.apply { setOnRefreshListener { viewModel.getMyPageData() } diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt index 1af862c7..4ddcd242 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt @@ -7,6 +7,8 @@ import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import com.mashup.R import com.mashup.base.BaseFragment +import com.mashup.core.common.R as CR +import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.ui.theme.MashUpTheme import com.mashup.databinding.FragmentScheduleBinding import com.mashup.ui.main.MainViewModel @@ -27,6 +29,7 @@ class ScheduleFragment : BaseFragment() { override fun initViews() { super.initViews() + requireActivity().setStatusBarColorRes(CR.color.white) viewBinding.cvSchedule.setContent { MashUpTheme { ScheduleRoute( diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt new file mode 100644 index 00000000..c364b559 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -0,0 +1,209 @@ +package com.mashup.ui.schedule + +import android.content.Context +import androidx.compose.foundation.Image +import androidx.compose.foundation.LocalOverscrollConfiguration +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.Row +import androidx.compose.foundation.layout.Spacer +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.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.pullrefresh.PullRefreshIndicator +import androidx.compose.material.pullrefresh.pullRefresh +import androidx.compose.material.pullrefresh.rememberPullRefreshState +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.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle +import com.mashup.R +import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL +import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM +import com.mashup.core.common.R as CR +import com.mashup.core.common.extensions.fromHtml +import com.mashup.core.ui.colors.Brand500 +import com.mashup.core.ui.colors.Gray50 +import com.mashup.core.ui.colors.White +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.widget.MashUpHtmlText +import com.mashup.ui.attendance.platform.PlatformAttendanceActivity +import com.mashup.ui.main.MainViewModel +import com.mashup.ui.schedule.component.ScheduleTabRow +import com.mashup.ui.schedule.detail.ScheduleDetailActivity +import com.mashup.util.AnalyticsManager + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun ScheduleRoute( + mainViewModel: MainViewModel, + viewModel: ScheduleViewModel, + modifier: Modifier = Modifier +) { + val context = LocalContext.current + + var title by remember { mutableStateOf("") } + + var isRefreshing by remember { mutableStateOf(false) } + val pullRefreshState = rememberPullRefreshState( + refreshing = isRefreshing, + onRefresh = { + isRefreshing = true + viewModel.getScheduleList() // refresh api + } + ) + + val lifecycle = LocalLifecycleOwner.current + LaunchedEffect(Unit) { + lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + mainViewModel.onAttendance.collect { + viewModel.getScheduleList() + } + } + } + + val scheduleState by viewModel.scheduleState.collectAsState() + LaunchedEffect(scheduleState) { + when (val state = scheduleState) { + is ScheduleState.Loading -> {} + is ScheduleState.Empty -> { isRefreshing = false } + is ScheduleState.Success -> { + isRefreshing = false + title = context.setUiOfScheduleTitle(state.scheduleTitleState) + } + is ScheduleState.Error -> { isRefreshing = false } + } + } + + var selectedTabIndex by remember { mutableStateOf(0) } + CompositionLocalProvider( + LocalOverscrollConfiguration provides null + ) { + Box(modifier = modifier.pullRefresh(pullRefreshState).background(White)) { + LazyColumn(modifier = modifier) { + item { + ScheduleTopbar(title) + Spacer(modifier = Modifier.height(26.dp)) + } + + stickyHeader { + ScheduleTabRow( + modifier = Modifier.background(White), + selectedTabIndex = selectedTabIndex, + updateSelectedTabIndex = { index -> + selectedTabIndex = index + } + ) + } + + item { + when (scheduleState) { + is ScheduleState.Error -> {} + is ScheduleState.Empty -> {} + else -> { + ScheduleScreen( + modifier = Modifier.fillMaxSize().background(Gray50).padding(bottom = 300.dp), + scheduleState = scheduleState, + onClickScheduleInformation = { scheduleId: Int -> + AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) + context.startActivity( + ScheduleDetailActivity.newIntent(context, scheduleId) + ) + }, + onClickAttendance = { scheduleId: Int -> + AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_STATUS_CONFIRM) + context.startActivity( + PlatformAttendanceActivity.newIntent(context, scheduleId) + ) + }, + refreshState = isRefreshing + + ) + } + } + } + } + + PullRefreshIndicator( + modifier = Modifier.align(Alignment.TopCenter), + scale = true, + contentColor = Brand500, + refreshing = isRefreshing, + state = pullRefreshState + ) + } + } +} + +fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String { + return when (scheduleTitleState) { + ScheduleTitleState.Empty -> { + getString(R.string.empty_schedule) + } + is ScheduleTitleState.End -> { + getString(R.string.end_schedule, scheduleTitleState.generatedNumber) + } + is ScheduleTitleState.DateCount -> { + getString(R.string.event_list_title, scheduleTitleState.dataCount) + } + is ScheduleTitleState.SchedulePreparing -> { + getString(R.string.preparing_attendance) + } + } +} + +@Composable +fun ScheduleTopbar(title: String) { + Row( + modifier = Modifier + .padding(horizontal = 20.dp) + .padding(top = 24.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + ) { + MashUpHtmlText( + content = title.fromHtml(), + modifier = Modifier.weight(1f, false), + textAppearance = CR.style.TextAppearance_Mashup_Header1_24_B, + ) + Spacer(modifier = Modifier.width(8.dp)) + Image( + painter = painterResource(id = CR.drawable.ic_more), + contentDescription = null, + modifier = Modifier + .size(20.dp) + .clickable { + // TODO: 메뉴 화면으로 이동, 당근 Popup Disable 처리 + }, + ) + } +} + +@Preview +@Composable +fun PreviewScheduleTopbar() { + MashUpTheme { + ScheduleTopbar(title = "다음 세미나 준비 중이에요.\n조금만 기다려주세요.") + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 4fdc28fb..750b4dc2 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -1,31 +1,13 @@ package com.mashup.ui.schedule -import android.content.Context -import androidx.compose.foundation.Image -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.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PageSize import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.pullrefresh.PullRefreshIndicator -import androidx.compose.material.pullrefresh.pullRefresh -import androidx.compose.material.pullrefresh.rememberPullRefreshState import androidx.compose.runtime.Composable 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 @@ -33,126 +15,14 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.repeatOnLifecycle -import com.mashup.R -import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL -import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM -import com.mashup.core.common.R as CR -import com.mashup.core.common.extensions.fromHtml -import com.mashup.core.ui.colors.Brand500 -import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.core.ui.widget.MashUpHtmlText -import com.mashup.ui.attendance.platform.PlatformAttendanceActivity -import com.mashup.ui.main.MainViewModel -import com.mashup.ui.schedule.detail.ScheduleDetailActivity import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem import com.mashup.ui.schedule.item.ScheduleViewPagerSuccessItem import com.mashup.ui.schedule.model.ScheduleCard -import com.mashup.util.AnalyticsManager import kotlin.math.abs import kotlin.math.absoluteValue -@OptIn(ExperimentalMaterialApi::class) -@Composable -fun ScheduleRoute( - mainViewModel: MainViewModel, - viewModel: ScheduleViewModel, - modifier: Modifier = Modifier -) { - var isRefreshing by remember { mutableStateOf(false) } - - val pullRefreshState = rememberPullRefreshState( - refreshing = isRefreshing, - onRefresh = { - isRefreshing = true - // refresh api - viewModel.getScheduleList() - } - ) - val context = LocalContext.current - - val state by viewModel.scheduleState.collectAsState() - - var title by remember { mutableStateOf("") } - - val lifecycle = LocalLifecycleOwner.current - - LaunchedEffect(Unit) { - lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { - mainViewModel.onAttendance.collect { - viewModel.getScheduleList() - } - } - } - - LaunchedEffect(state) { - when (state) { - is ScheduleState.Loading -> {} - is ScheduleState.Empty -> { isRefreshing = false } - is ScheduleState.Success -> { - isRefreshing = false - title = context.setUiOfScheduleTitle( - (state as ScheduleState.Success).scheduleTitleState - ) - } - is ScheduleState.Error -> { isRefreshing = false } - } - } - - val scrollState = rememberScrollState() - - Box( - modifier = modifier.pullRefresh(pullRefreshState) - ) { - Column( - modifier = modifier - ) { - ScheduleTopbar(title) - when (state) { - is ScheduleState.Error -> {} - is ScheduleState.Empty -> {} - else -> { - ScheduleScreen( - modifier = Modifier - .fillMaxSize() - .verticalScroll(scrollState), - scheduleState = state, - onClickScheduleInformation = { scheduleId: Int -> - AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) - context.startActivity( - ScheduleDetailActivity.newIntent(context, scheduleId) - ) - }, - onClickAttendance = { scheduleId: Int -> - AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_STATUS_CONFIRM) - context.startActivity( - PlatformAttendanceActivity.newIntent(context, scheduleId) - ) - }, - refreshState = isRefreshing - - ) - } - } - } - - PullRefreshIndicator( - modifier = Modifier.align(Alignment.TopCenter), - scale = true, - contentColor = Brand500, - refreshing = isRefreshing, - state = pullRefreshState - ) - } -} - @Composable fun ScheduleScreen( scheduleState: ScheduleState, @@ -254,55 +124,3 @@ fun ScheduleScreen( else -> {} } } - -fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String { - return when (scheduleTitleState) { - ScheduleTitleState.Empty -> { - getString(R.string.empty_schedule) - } - is ScheduleTitleState.End -> { - getString(R.string.end_schedule, scheduleTitleState.generatedNumber) - } - is ScheduleTitleState.DateCount -> { - getString(R.string.event_list_title, scheduleTitleState.dataCount) - } - is ScheduleTitleState.SchedulePreparing -> { - getString(R.string.preparing_attendance) - } - } -} - -@Composable -fun ScheduleTopbar(title: String) { - Row( - modifier = Modifier - .padding(horizontal = 20.dp) - .padding(top = 24.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - ) { - MashUpHtmlText( - content = title.fromHtml(), - modifier = Modifier.weight(1f, false), - textAppearance = CR.style.TextAppearance_Mashup_Header1_24_B, - ) - Spacer(modifier = Modifier.width(8.dp)) - Image( - painter = painterResource(id = CR.drawable.ic_more), - contentDescription = null, - modifier = Modifier - .size(20.dp) - .clickable { - // TODO: 메뉴 화면으로 이동, 당근 Popup Disable 처리 - }, - ) - } -} - -@Preview -@Composable -fun PreviewScheduleTopbar() { - MashUpTheme { - ScheduleTopbar(title = "다음 세미나 준비 중이에요.\n조금만 기다려주세요.") - } -} diff --git a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt index 7f066b78..22398778 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/ScheduleTabRow.kt @@ -69,9 +69,6 @@ fun ScheduleTabRow( Column( modifier = modifier ) { - Spacer( - modifier = Modifier.height(26.dp) - ) TabRow( modifier = Modifier.fillMaxWidth(), selectedTabIndex = selectedTabIndex, From 0337f98df5ea53dd3fe0d645cbf7d93872addd7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sat, 29 Jun 2024 20:20:09 +0900 Subject: [PATCH 018/110] =?UTF-8?q?=F0=9F=A7=B8=20SpotlessApply?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/mashup/ui/mypage/MyPageFragment.kt | 2 +- .../java/com/mashup/ui/schedule/ScheduleFragment.kt | 2 +- .../main/java/com/mashup/ui/schedule/ScheduleRoute.kt | 11 +++++------ .../java/com/mashup/core/ui/widget/MashUpHtmlText.kt | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt b/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt index 5b154dd8..5cb2878a 100644 --- a/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt +++ b/app/src/main/java/com/mashup/ui/mypage/MyPageFragment.kt @@ -9,13 +9,13 @@ import androidx.core.content.ContextCompat import androidx.fragment.app.viewModels import com.mashup.R import com.mashup.base.BaseFragment -import com.mashup.core.common.R as CR import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.databinding.FragmentMyPageBinding import com.mashup.feature.mypage.profile.model.ProfileCardData import com.mashup.ui.setting.SettingActivity import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.flow.collectLatest +import com.mashup.core.common.R as CR @AndroidEntryPoint class MyPageFragment : BaseFragment() { diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt index 4ddcd242..a0864d9b 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleFragment.kt @@ -7,12 +7,12 @@ import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels import com.mashup.R import com.mashup.base.BaseFragment -import com.mashup.core.common.R as CR import com.mashup.core.common.extensions.setStatusBarColorRes import com.mashup.core.ui.theme.MashUpTheme import com.mashup.databinding.FragmentScheduleBinding import com.mashup.ui.main.MainViewModel import dagger.hilt.android.AndroidEntryPoint +import com.mashup.core.common.R as CR @AndroidEntryPoint class ScheduleFragment : BaseFragment() { diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index c364b559..bb11758f 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -30,7 +30,6 @@ import androidx.compose.runtime.remember 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.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource @@ -41,7 +40,6 @@ import androidx.lifecycle.repeatOnLifecycle import com.mashup.R import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM -import com.mashup.core.common.R as CR import com.mashup.core.common.extensions.fromHtml import com.mashup.core.ui.colors.Brand500 import com.mashup.core.ui.colors.Gray50 @@ -53,6 +51,7 @@ import com.mashup.ui.main.MainViewModel import com.mashup.ui.schedule.component.ScheduleTabRow import com.mashup.ui.schedule.detail.ScheduleDetailActivity import com.mashup.util.AnalyticsManager +import com.mashup.core.common.R as CR @OptIn(ExperimentalMaterialApi::class) @Composable @@ -123,7 +122,7 @@ fun ScheduleRoute( is ScheduleState.Empty -> {} else -> { ScheduleScreen( - modifier = Modifier.fillMaxSize().background(Gray50).padding(bottom = 300.dp), + modifier = Modifier.fillMaxSize().background(Gray50), scheduleState = scheduleState, onClickScheduleInformation = { scheduleId: Int -> AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) @@ -180,12 +179,12 @@ fun ScheduleTopbar(title: String) { .padding(horizontal = 20.dp) .padding(top = 24.dp) .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, + horizontalArrangement = Arrangement.SpaceBetween ) { MashUpHtmlText( content = title.fromHtml(), modifier = Modifier.weight(1f, false), - textAppearance = CR.style.TextAppearance_Mashup_Header1_24_B, + textAppearance = CR.style.TextAppearance_Mashup_Header1_24_B ) Spacer(modifier = Modifier.width(8.dp)) Image( @@ -195,7 +194,7 @@ fun ScheduleTopbar(title: String) { .size(20.dp) .clickable { // TODO: 메뉴 화면으로 이동, 당근 Popup Disable 처리 - }, + } ) } } diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt index a3133517..65d7992e 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpHtmlText.kt @@ -35,6 +35,6 @@ fun MashUpHtmlText( modifier = modifier, update = { view -> view.text = content - }, + } ) } From 81bc7768d8e50eb9220b34ea20779513475d4d9f Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 20:26:00 +0900 Subject: [PATCH 019/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20MashupPlatformBa?= =?UTF-8?q?dge=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/ui/widget/MashupPlatformBadge.kt | 122 ++++++++++++++++++ core/ui/src/main/res/drawable/ic_platform.xml | 11 ++ core/ui/src/main/res/drawable/ic_semina.xml | 16 +++ 3 files changed, 149 insertions(+) create mode 100644 core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt create mode 100644 core/ui/src/main/res/drawable/ic_platform.xml create mode 100644 core/ui/src/main/res/drawable/ic_semina.xml diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt new file mode 100644 index 00000000..242ef2bb --- /dev/null +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt @@ -0,0 +1,122 @@ +package com.mashup.core.ui.widget + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.R +import com.mashup.core.ui.typography.Body3 + +@Composable +fun MashupPlatformBadge( + platform: String, + modifier: Modifier = Modifier, +) { + val convertedPlatform = platform.convertCamelCase() + + + Row( + modifier = modifier + .background( + color = platform.getColor(), + shape = RoundedCornerShape(100.dp) + ) + .padding(horizontal = 10.dp, vertical = 6.5.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Image( + modifier = Modifier.size(12.dp), + painter = painterResource(id = platform.getIcon()), + contentDescription = null, + ) + Spacer( + modifier = Modifier.width(4.dp) + ) + Text( + text = platform.convertCamelCase().name, + style = Body3, + color = Color.White + ) + } +} + + +private fun String.getIcon(): Int { + return when (this) { + "ALL" -> R.drawable.ic_semina + else -> R.drawable.ic_platform + } + +} + +enum class PlatformType { + Semina, Design, Spring, Ios, Android, Web, Node +} + + +private fun String.getColor(): Color { + return when (this) { + "ALL" -> Color(0xFF7CD5FF) + else -> Color(0xFF8A61FF) + } +} + +private fun String.convertCamelCase(): PlatformType { + return when (this) { + "ALL" -> PlatformType.Semina + "DESIGN" -> PlatformType.Design + "SPRING" -> PlatformType.Spring + "IOS" -> PlatformType.Ios + "ANDROID" -> PlatformType.Android + "WEB" -> PlatformType.Web + "NODE" -> PlatformType.Node + else -> PlatformType.Semina + } +} + + +@Preview +@Composable +private fun PreviewMashUpPlatformBadge() { + Column { + MashupPlatformBadge( + platform = "ALL" + ) + MashupPlatformBadge( + platform = "DESIGN" + ) + MashupPlatformBadge( + platform = "SPRING" + ) + MashupPlatformBadge( + platform = "IOS" + ) + MashupPlatformBadge( + platform = "ANDROID" + ) + MashupPlatformBadge( + platform = "WEB" + ) + MashupPlatformBadge( + platform = "NODE" + ) + + } + +} \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_platform.xml b/core/ui/src/main/res/drawable/ic_platform.xml new file mode 100644 index 00000000..cf524524 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_platform.xml @@ -0,0 +1,11 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_semina.xml b/core/ui/src/main/res/drawable/ic_semina.xml new file mode 100644 index 00000000..e45ae499 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_semina.xml @@ -0,0 +1,16 @@ + + + + From 0b306cad8fe3d547a1dbf8acedb3bf162f09f671 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 21:52:15 +0900 Subject: [PATCH 020/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20PlatformSchedule?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=84=B8=EB=AF=B8=EB=82=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/data/dto/ScheduleResponse.kt | 2 + .../mashup/ui/schedule/ViewEventTimeline.kt | 42 ++-- .../mashup/ui/schedule/item/CardInfoItem.kt | 35 ++- .../item/SchedeuleViewPagerInProgressItem.kt | 23 +- .../item/ScheduleViewPagerEmptySchedule.kt | 2 +- .../item/ScheduleViewPagerSuccessItem.kt | 199 ++++++++++++------ .../mashup/ui/schedule/util/ScheduleColor.kt | 58 +++++ app/src/main/res/values/strings.xml | 2 +- .../common/src/main/res/drawable/ic_clock.xml | 27 +-- .../src/main/res/drawable/ic_mappin.xml | 12 +- 10 files changed, 268 insertions(+), 134 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt diff --git a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt index 8d1a97e5..d9ab0a7b 100644 --- a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt +++ b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt @@ -9,6 +9,8 @@ import java.util.Locale @JsonClass(generateAdapter = true) data class ScheduleResponse( + @field:Json(name="scheduleType") + val scheduleType: String, @field:Json(name = "scheduleId") val scheduleId: Int, @field:Json(name = "dateCount") diff --git a/app/src/main/java/com/mashup/ui/schedule/ViewEventTimeline.kt b/app/src/main/java/com/mashup/ui/schedule/ViewEventTimeline.kt index 0632363e..40d2c435 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ViewEventTimeline.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ViewEventTimeline.kt @@ -3,10 +3,13 @@ package com.mashup.ui.schedule import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.material3.Divider import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -21,6 +24,7 @@ import com.mashup.core.ui.colors.Gray500 import com.mashup.core.ui.colors.Gray600 import com.mashup.core.ui.colors.Gray800 import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Body5 import com.mashup.core.ui.typography.Caption2 import com.mashup.core.ui.typography.SubTitle3 @@ -39,29 +43,33 @@ fun ViewEventTimeline( val (divider, attendanceImage, attendanceCaption, attendanceTime, attendanceStatus) = createRefs() Image( - modifier = Modifier.size(20.dp).constrainAs(attendanceImage) { - start.linkTo(parent.start) - top.linkTo(parent.top) - bottom.linkTo(attendanceStatus.bottom) - }, + modifier = Modifier + .size(20.dp) + .constrainAs(attendanceImage) { + start.linkTo(parent.start) + top.linkTo(parent.top) + bottom.linkTo(attendanceStatus.bottom) + }, painter = painterResource(id = image), contentDescription = null ) Text( modifier = Modifier.constrainAs(attendanceCaption) { - top.linkTo(parent.top) + top.linkTo(attendanceImage.top) + bottom.linkTo(attendanceImage.bottom, margin = 3.dp) start.linkTo(attendanceImage.end, 8.dp) }, text = caption, - style = Caption2, + style = Body5, color = Gray600 ) Text( modifier = Modifier.constrainAs(attendanceStatus) { - top.linkTo(attendanceCaption.bottom, 2.dp) - start.linkTo(attendanceCaption.start) + top.linkTo(attendanceCaption.top) + bottom.linkTo(attendanceCaption.bottom) + start.linkTo(attendanceCaption.end, 7.dp) }, text = stringResource(status), style = SubTitle3.copy( @@ -79,18 +87,22 @@ fun ViewEventTimeline( color = Gray500 ) if (isFinal.not()) { - Divider( + Row( modifier = Modifier.constrainAs(divider) { start.linkTo(attendanceImage.start) end.linkTo(attendanceImage.end) - top.linkTo(attendanceStatus.bottom, 2.dp) + top.linkTo(attendanceStatus.bottom, 6.dp) height = Dimension.value(16.dp) width = Dimension.value(1.dp) }, - thickness = 1.dp, - color = Gray200 - - ) + verticalAlignment = Alignment.CenterVertically + ) { + Divider( + modifier = Modifier.height(12.dp), + thickness = 1.dp, + color = Gray200 + ) + } } } } diff --git a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt index d0d0eb4e..74aca476 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt @@ -27,14 +27,18 @@ import com.mashup.core.ui.colors.Gray300 import com.mashup.core.ui.colors.Gray400 import com.mashup.core.ui.colors.Gray600 import com.mashup.core.ui.colors.Gray700 +import com.mashup.core.ui.colors.Gray800 import com.mashup.core.ui.colors.Gray900 import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Body3 +import com.mashup.core.ui.typography.Body4 +import com.mashup.core.ui.typography.Body5 import com.mashup.core.ui.typography.Header1 +import com.mashup.core.ui.widget.MashupPlatformBadge @Composable fun CardInfoItem( - dDay: String, + platform: String, title: String, calendar: String, timeLine: String, @@ -42,19 +46,7 @@ fun CardInfoItem( modifier: Modifier = Modifier ) { Column(modifier = modifier) { - Box( - modifier = Modifier.background( - color = Gray100, - shape = RoundedCornerShape(100.dp) - ).padding(horizontal = 10.dp, vertical = 3.5.dp), - contentAlignment = Alignment.Center - ) { - Text( - style = Body3, - text = dDay, - color = Gray600 - ) - } + MashupPlatformBadge(platform = platform) Spacer( modifier = Modifier.height(10.dp) ) @@ -82,9 +74,9 @@ fun CardInfoItem( ) Text( - style = Body3, + style = Body4, text = calendar, - color = Gray700 + color = Gray800 ) } @@ -101,8 +93,8 @@ fun CardInfoItem( ) Text( text = timeLine, - style = Body3, - color = Gray700 + style = Body4, + color = Gray800 ) } @@ -121,9 +113,9 @@ fun CardInfoItem( ) Text( - style = Body3, + style = Body4, text = location, - color = Gray700 + color = Gray800 ) } } @@ -131,13 +123,14 @@ fun CardInfoItem( } } + @Preview @Composable private fun PreviewCardInfoItem() { MashUpTheme { CardInfoItem( modifier = Modifier.background(color = Color.White), - dDay = "D+13", + platform = "ALL", title = "스케쥴 테스트", calendar = "02월 05일", timeLine = "오후 01:00 - 오후 01:10", diff --git a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt index cd5bbcae..aa2d746f 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt @@ -35,7 +35,6 @@ import androidx.core.content.res.ResourcesCompat import androidx.core.text.HtmlCompat import com.mashup.R import com.mashup.core.ui.colors.Brand100 -import com.mashup.core.ui.colors.Gray100 import com.mashup.core.ui.colors.Gray50 import com.mashup.core.ui.colors.Gray700 import com.mashup.core.ui.theme.MashUpTheme @@ -43,6 +42,8 @@ import com.mashup.core.ui.typography.Body1 import com.mashup.data.dto.ScheduleResponse import com.mashup.databinding.LayoutAttendanceCoachMarkBindingImpl import com.mashup.ui.schedule.model.ScheduleCard +import com.mashup.ui.schedule.util.getBackgroundColor +import com.mashup.ui.schedule.util.getBorderColor import java.util.Date @Composable @@ -53,14 +54,15 @@ fun ScheduleViewPagerInProgressItem( onClickAttendance: (Int) -> Unit = {} ) { Column( - modifier = modifier.fillMaxWidth().wrapContentHeight().background( - color = Color.White, + modifier = modifier.fillMaxWidth().wrapContentHeight() .background( + color = data.scheduleResponse.scheduleType.getBackgroundColor(), shape = RoundedCornerShape(20.dp) - ).border( - width = 1.dp, - color = Gray100, - shape = RoundedCornerShape(20.dp) - ).clip(RoundedCornerShape(20.dp)) + ) + .border( + width = 1.dp, + color = data.scheduleResponse.scheduleType.getBorderColor(), + shape = RoundedCornerShape(20.dp) + ).clip(RoundedCornerShape(20.dp)) .clickable { onClickScheduleInformation(data.scheduleResponse.scheduleId) }.padding(20.dp), @@ -68,7 +70,7 @@ fun ScheduleViewPagerInProgressItem( ) { CardInfoItem( modifier = Modifier.fillMaxWidth().wrapContentHeight(), - dDay = data.scheduleResponse.getDDay(), + platform = data.scheduleResponse.scheduleType, title = data.scheduleResponse.name, calendar = data.scheduleResponse.getDate(), timeLine = data.scheduleResponse.getTimeLine(), @@ -182,7 +184,8 @@ private fun PreviewScheduleViewPagerEmptySchedule() { longitude = 0.0, roadAddress = null, detailAddress = null - ) + ), + scheduleType = "" ), attendanceInfo = null ) diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt index a4b32ce6..8d6fd550 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt @@ -47,7 +47,7 @@ fun ScheduleViewPagerEmptyItem( ) { CardInfoItem( modifier = Modifier.fillMaxWidth().wrapContentHeight(), - dDay = data.scheduleResponse?.getDDay() ?: "?", + platform = data.scheduleResponse?.scheduleType ?: "", title = data.scheduleResponse?.name ?: "", calendar = data.scheduleResponse?.getDate() ?: "-", timeLine = data.scheduleResponse?.getTimeLine() ?: "-", diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt index 07c783a2..a4199348 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt @@ -11,6 +11,7 @@ import androidx.appcompat.widget.AppCompatTextView import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -21,12 +22,17 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Divider import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember 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.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString @@ -34,20 +40,32 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.max +import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.content.res.ResourcesCompat import androidx.core.text.HtmlCompat import com.mashup.R -import com.mashup.core.ui.colors.Brand100 -import com.mashup.core.ui.colors.Gray100 -import com.mashup.core.ui.colors.Gray50 +import com.mashup.core.ui.colors.Brand200 import com.mashup.core.ui.colors.Gray700 +import com.mashup.core.ui.colors.Gray900 import com.mashup.core.ui.typography.Body1 +import com.mashup.core.ui.typography.Body5 +import com.mashup.core.ui.typography.SubTitle2 +import com.mashup.core.ui.widget.PlatformType import com.mashup.data.dto.EventResponse import com.mashup.ui.schedule.ViewEventTimeline import com.mashup.ui.schedule.model.ScheduleCard +import com.mashup.ui.schedule.util.convertCamelCase +import com.mashup.ui.schedule.util.getBackgroundColor +import com.mashup.ui.schedule.util.getBorderColor +import com.mashup.ui.schedule.util.getButtonBackgroundColor +import com.mashup.ui.schedule.util.getButtonTextColor +import com.mashup.ui.schedule.util.getEventTimelineBackgroundColor import com.mashup.ui.schedule.util.onBindAttendanceImage import com.mashup.ui.schedule.util.onBindAttendanceStatus import com.mashup.ui.schedule.util.onBindAttendanceTime @@ -61,20 +79,22 @@ fun ScheduleViewPagerSuccessItem( ) { val context = LocalContext.current val listState = rememberLazyListState() + val textColor by remember { mutableStateOf(data.scheduleResponse.scheduleType.getButtonTextColor()) } Column( modifier = modifier .fillMaxWidth() .wrapContentHeight() .background( - color = Color.White, + color = data.scheduleResponse.scheduleType.getBackgroundColor(), shape = RoundedCornerShape(20.dp) ) .border( width = 1.dp, - color = Gray100, + color = data.scheduleResponse.scheduleType.getBorderColor(), shape = RoundedCornerShape(20.dp) - ).clip(RoundedCornerShape(20.dp)) + ) + .clip(RoundedCornerShape(20.dp)) .clickable { onClickScheduleInformation(data.scheduleResponse.scheduleId) } @@ -85,86 +105,129 @@ fun ScheduleViewPagerSuccessItem( modifier = Modifier .fillMaxWidth() .wrapContentHeight(), - dDay = data.scheduleResponse.getDDay(), + platform = data.scheduleResponse.scheduleType, title = data.scheduleResponse.name, calendar = data.scheduleResponse.getDate(), timeLine = data.scheduleResponse.getTimeLine(), location = data.scheduleResponse.location?.detailAddress ?: "" ) - Spacer(modifier = Modifier.height(16.dp)) - LazyColumn( - state = listState, - modifier = Modifier - .background(color = Gray50, shape = RoundedCornerShape(16.dp)) - .height(220.dp) - .padding(top = 16.dp, start = 20.dp, end = 20.dp) - ) { - itemsIndexed(data.scheduleResponse.eventList, key = { _: Int, item: EventResponse -> - item.eventId - }) { index: Int, _: EventResponse -> - Column { - if (index == 0) { - val spannableString = SpannableStringBuilder( - String.format( - context.resources.getString( - R.string.event_list_card_title - ), - data.attendanceInfo.memberName - ) - ).toString() - Text( - text = HtmlCompat.fromHtml( - spannableString, - HtmlCompat.FROM_HTML_MODE_COMPACT - ).toAnnotatedString(), - color = Gray700, - style = Body1 - ) + if (data.scheduleResponse.scheduleType.convertCamelCase() == PlatformType.Semina) { + Spacer(modifier = Modifier.height(12.dp)) + LazyColumn( + state = listState, + modifier = Modifier + .background( + color = data.scheduleResponse.scheduleType.getEventTimelineBackgroundColor(), + shape = RoundedCornerShape(16.dp) + ) + .height(176.dp) + .padding(top = 16.dp, start = 20.dp, end = 20.dp), + ) { + itemsIndexed(data.scheduleResponse.eventList, key = { _: Int, item: EventResponse -> + item.eventId + }) { index: Int, _: EventResponse -> + Column { + if (index == 0) { + val spannableString = SpannableStringBuilder( + String.format( + context.resources.getString( + R.string.event_list_card_title + ), + data.attendanceInfo.memberName + ) + ).toString() + + Text( + text = HtmlCompat.fromHtml( + spannableString, + HtmlCompat.FROM_HTML_MODE_COMPACT + ).toAnnotatedString(), + color = Gray700, + style = Body1 + ) - Spacer( - modifier = Modifier.height(16.dp) + Spacer( + modifier = Modifier.height(16.dp) + ) + } + ViewEventTimeline( + modifier = Modifier.fillMaxWidth(), + caption = stringResource(id = R.string.attendance_caption, index + 1), + time = onBindAttendanceTime(data.attendanceInfo.getAttendanceAt(index)), + status = onBindAttendanceStatus( + data.attendanceInfo.getAttendanceStatus(index) + ), + image = onBindAttendanceImage( + data.attendanceInfo.getAttendanceStatus(index) + ) ) } + Spacer( + modifier= Modifier.height(6.dp) + ) + } + item { + val status = data.attendanceInfo.getFinalAttendance() ViewEventTimeline( modifier = Modifier.fillMaxWidth(), - caption = stringResource(id = R.string.attendance_caption, index + 1), - time = onBindAttendanceTime(data.attendanceInfo.getAttendanceAt(index)), - status = onBindAttendanceStatus( - data.attendanceInfo.getAttendanceStatus(index) - ), - image = onBindAttendanceImage( - data.attendanceInfo.getAttendanceStatus(index) - ) + caption = stringResource(id = R.string.attendance_final), + status = onBindAttendanceStatus(status, isFinal = true), + image = onBindAttendanceImage(status, isFinal = true), + isFinal = true ) } - } - item { - val status = data.attendanceInfo.getFinalAttendance() - ViewEventTimeline( - modifier = Modifier.fillMaxWidth(), - caption = stringResource(id = R.string.attendance_final), - status = onBindAttendanceStatus(status, isFinal = true), - image = onBindAttendanceImage(status, isFinal = true), - isFinal = true - ) - } - item { - Spacer(modifier = Modifier.height(20.dp)) + item { + Spacer(modifier = Modifier.height(20.dp)) + } } + Spacer( + modifier = Modifier.height(12.dp) + ) + } else { + Spacer(modifier = Modifier.height(18.dp)) + Divider( + modifier = Modifier.fillMaxWidth(), + color = Brand200, + ) + Spacer( + modifier = Modifier.height(18.dp) + ) + Text( + modifier = Modifier.fillMaxWidth(), + text = "공지", + textAlign = TextAlign.Left, + style = SubTitle2.copy( + lineHeight = 19.09.sp + ), + color = Gray900 + ) + Spacer( + modifier = Modifier.height(6.dp) + ) + Text( + text = "가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카", + maxLines = 5, + style = Body5.copy( + lineHeight = 20.sp + ), + color = Gray700, + overflow = TextOverflow.Ellipsis + ) + Spacer( + modifier = Modifier.height(40.dp) + ) } - Spacer( - modifier = Modifier.height(12.dp) - ) + AndroidView( modifier = Modifier .fillMaxWidth() .height(48.dp) .background( - color = Brand100, + color = data.scheduleResponse.scheduleType.getButtonBackgroundColor(), shape = RoundedCornerShape(16.dp) ), factory = { context -> @@ -175,11 +238,7 @@ fun ScheduleViewPagerSuccessItem( ) gravity = Gravity.CENTER setTextColor( - ResourcesCompat.getColor( - resources, - com.mashup.core.common.R.color.brand500, - null - ) + textColor.toArgb() ) setPadding(12, 0, 0, 0) setOnClickListener { @@ -190,6 +249,7 @@ fun ScheduleViewPagerSuccessItem( ) } } + fun Spanned.toAnnotatedString(): AnnotatedString = buildAnnotatedString { val spanned = this@toAnnotatedString append(spanned.toString()) @@ -206,11 +266,13 @@ fun Spanned.toAnnotatedString(): AnnotatedString = buildAnnotatedString { end ) } + is UnderlineSpan -> addStyle( SpanStyle(textDecoration = TextDecoration.Underline), start, end ) + is ForegroundColorSpan -> addStyle( SpanStyle(color = Color(span.foregroundColor)), start, @@ -219,3 +281,4 @@ fun Spanned.toAnnotatedString(): AnnotatedString = buildAnnotatedString { } } } + diff --git a/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt b/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt new file mode 100644 index 00000000..c5246687 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt @@ -0,0 +1,58 @@ +package com.mashup.ui.schedule.util + +import androidx.compose.ui.graphics.Color +import com.mashup.core.ui.widget.PlatformType + + +fun String.getEventTimelineBackgroundColor(): Color { + return when (this) { + "ALL" -> Color(0xFFE1F2FA) + else -> Color(0xFFF5F1FF) + } +} + +fun String.getButtonBackgroundColor(): Color { + return when (this) { + "ALL" -> Color(0xFFC2EBFF) + else -> Color(0xFFE7DEFF) + } +} + +fun String.getBackgroundColor(): Color { + return when (this) { + "ALL" -> Color(0xFFECF9FF) + else -> Color(0xFFF5F1FF) + } +} + +fun String.getBorderColor(): Color { + return when (this) { + "ALL" -> Color(0xFFE1F2FA) + else -> Color(0xFFE7DEFF).copy( + alpha = 0.3f + ) + } +} + +fun String.getButtonTextColor(): Color { + return when (this) { + "ALL" -> Color(0xFF358CB6) + else -> Color(0xFF6A36FF) + } + +} + + +fun String.convertCamelCase(): PlatformType { + return when (this) { + "ALL" -> PlatformType.Semina + "DESIGN" -> PlatformType.Design + "SPRING" -> PlatformType.Spring + "IOS" -> PlatformType.Ios + "ANDROID" -> PlatformType.Android + "WEB" -> PlatformType.Web + "NODE" -> PlatformType.Node + else -> PlatformType.Semina + } +} + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cc2787a2..bd92c682 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -30,7 +30,7 @@ 출석 결석 지각 - 플랫폼별 출석현황 보러가기 + 상세 스케줄 보러가기 로그아웃 회원탈퇴 매시업을 잊지말아죠... diff --git a/core/common/src/main/res/drawable/ic_clock.xml b/core/common/src/main/res/drawable/ic_clock.xml index cf58d00a..1e15c2e2 100644 --- a/core/common/src/main/res/drawable/ic_clock.xml +++ b/core/common/src/main/res/drawable/ic_clock.xml @@ -1,14 +1,17 @@ - - + android:width="20dp" + android:height="20dp" + android:viewportWidth="20" + android:viewportHeight="20"> + + diff --git a/core/common/src/main/res/drawable/ic_mappin.xml b/core/common/src/main/res/drawable/ic_mappin.xml index e4a6a5cb..a2852d3a 100644 --- a/core/common/src/main/res/drawable/ic_mappin.xml +++ b/core/common/src/main/res/drawable/ic_mappin.xml @@ -1,14 +1,14 @@ + android:width="21dp" + android:height="21dp" + android:viewportWidth="21" + android:viewportHeight="21"> From 76eb92e9a684dda0da7fe7b38950fbe37c00f765 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 21:53:32 +0900 Subject: [PATCH 021/110] =?UTF-8?q?=F0=9F=9B=A0refactor=20:=20remove=20new?= =?UTF-8?q?=20line?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/mashup/core/ui/widget/MashUpGradientButton.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt index 1c498c7e..5c4edf04 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashUpGradientButton.kt @@ -31,8 +31,7 @@ fun MashUpGradientButton( modifier = modifier .clip(RoundedCornerShape(12.dp)) .background( - brush = - Brush.linearGradient( + brush = Brush.linearGradient( colors = gradientColors ) ) From 7af71b48583a83bff3aaf7ff05ca5294f61c65c5 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 22:08:12 +0900 Subject: [PATCH 022/110] =?UTF-8?q?=F0=9F=9B=A0=20=EB=A6=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/data/dto/ScheduleResponse.kt | 4 +- .../mashup/ui/schedule/item/CardInfoItem.kt | 9 --- .../item/SchedeuleViewPagerInProgressItem.kt | 55 ++++++++++++------- .../item/ScheduleViewPagerSuccessItem.kt | 14 ++--- .../mashup/ui/schedule/util/ScheduleColor.kt | 8 +-- .../core/ui/widget/MashupPlatformBadge.kt | 50 ++--------------- 6 files changed, 49 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt index d9ab0a7b..5ec60f23 100644 --- a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt +++ b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt @@ -9,7 +9,7 @@ import java.util.Locale @JsonClass(generateAdapter = true) data class ScheduleResponse( - @field:Json(name="scheduleType") + @field:Json(name = "scheduleType") val scheduleType: String, @field:Json(name = "scheduleId") val scheduleId: Int, @@ -56,9 +56,11 @@ data class ScheduleResponse( dateCount == 0 -> { "D-Day" } + dateCount > 0 -> { "D-$dateCount" } + else -> { "D+${-dateCount}" } diff --git a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt index 74aca476..824596c3 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt @@ -3,14 +3,11 @@ package com.mashup.ui.schedule.item import androidx.compose.foundation.Image 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.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -22,17 +19,12 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mashup.core.common.R -import com.mashup.core.ui.colors.Gray100 import com.mashup.core.ui.colors.Gray300 import com.mashup.core.ui.colors.Gray400 -import com.mashup.core.ui.colors.Gray600 -import com.mashup.core.ui.colors.Gray700 import com.mashup.core.ui.colors.Gray800 import com.mashup.core.ui.colors.Gray900 import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.core.ui.typography.Body3 import com.mashup.core.ui.typography.Body4 -import com.mashup.core.ui.typography.Body5 import com.mashup.core.ui.typography.Header1 import com.mashup.core.ui.widget.MashupPlatformBadge @@ -123,7 +115,6 @@ fun CardInfoItem( } } - @Preview @Composable private fun PreviewCardInfoItem() { diff --git a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt index aa2d746f..3147a9d3 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.Composable 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.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -54,22 +53,29 @@ fun ScheduleViewPagerInProgressItem( onClickAttendance: (Int) -> Unit = {} ) { Column( - modifier = modifier.fillMaxWidth().wrapContentHeight() .background( - color = data.scheduleResponse.scheduleType.getBackgroundColor(), - shape = RoundedCornerShape(20.dp) - ) + modifier = modifier + .fillMaxWidth() + .wrapContentHeight() + .background( + color = data.scheduleResponse.scheduleType.getBackgroundColor(), + shape = RoundedCornerShape(20.dp) + ) .border( width = 1.dp, color = data.scheduleResponse.scheduleType.getBorderColor(), shape = RoundedCornerShape(20.dp) - ).clip(RoundedCornerShape(20.dp)) + ) + .clip(RoundedCornerShape(20.dp)) .clickable { onClickScheduleInformation(data.scheduleResponse.scheduleId) - }.padding(20.dp), + } + .padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { CardInfoItem( - modifier = Modifier.fillMaxWidth().wrapContentHeight(), + modifier = Modifier + .fillMaxWidth() + .wrapContentHeight(), platform = data.scheduleResponse.scheduleType, title = data.scheduleResponse.name, calendar = data.scheduleResponse.getDate(), @@ -82,8 +88,11 @@ fun ScheduleViewPagerInProgressItem( val (coachMark, button, schedule) = createRefs() Column( - modifier = Modifier.background(color = Gray50, shape = RoundedCornerShape(16.dp)) - .height(220.dp).padding(top = 16.dp, bottom = 20.dp, start = 20.dp, end = 20.dp).fillMaxWidth() + modifier = Modifier + .background(color = Gray50, shape = RoundedCornerShape(16.dp)) + .height(220.dp) + .padding(top = 16.dp, bottom = 20.dp, start = 20.dp, end = 20.dp) + .fillMaxWidth() .constrainAs(schedule) { top.linkTo(parent.top) start.linkTo(parent.start) @@ -128,15 +137,19 @@ fun ScheduleViewPagerInProgressItem( } ) AndroidView( - modifier = Modifier.fillMaxWidth().height(48.dp).background( - color = Brand100, - shape = RoundedCornerShape(16.dp) - ).constrainAs(button) { - bottom.linkTo(parent.bottom) - start.linkTo(parent.start) - end.linkTo(parent.end) - top.linkTo(schedule.bottom, 12.dp) - }, + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .background( + color = Brand100, + shape = RoundedCornerShape(16.dp) + ) + .constrainAs(button) { + bottom.linkTo(parent.bottom) + start.linkTo(parent.start) + end.linkTo(parent.end) + top.linkTo(schedule.bottom, 12.dp) + }, factory = { context -> AppCompatTextView(context).apply { text = context.getString(R.string.click_attendance_list) @@ -167,7 +180,9 @@ fun ScheduleViewPagerInProgressItem( private fun PreviewScheduleViewPagerEmptySchedule() { MashUpTheme { Box( - modifier = Modifier.width(294.dp).height(479.dp) + modifier = Modifier + .width(294.dp) + .height(479.dp) ) { ScheduleViewPagerInProgressItem( data = ScheduleCard.InProgressSchedule( diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt index a4199348..71f36f4b 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt @@ -11,7 +11,6 @@ import androidx.appcompat.widget.AppCompatTextView import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -44,10 +43,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.max import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.res.ResourcesCompat import androidx.core.text.HtmlCompat import com.mashup.R import com.mashup.core.ui.colors.Brand200 @@ -112,8 +109,7 @@ fun ScheduleViewPagerSuccessItem( location = data.scheduleResponse.location?.detailAddress ?: "" ) - - if (data.scheduleResponse.scheduleType.convertCamelCase() == PlatformType.Semina) { + if (data.scheduleResponse.scheduleType.convertCamelCase() == PlatformType.Seminar) { Spacer(modifier = Modifier.height(12.dp)) LazyColumn( state = listState, @@ -123,7 +119,7 @@ fun ScheduleViewPagerSuccessItem( shape = RoundedCornerShape(16.dp) ) .height(176.dp) - .padding(top = 16.dp, start = 20.dp, end = 20.dp), + .padding(top = 16.dp, start = 20.dp, end = 20.dp) ) { itemsIndexed(data.scheduleResponse.eventList, key = { _: Int, item: EventResponse -> item.eventId @@ -165,7 +161,7 @@ fun ScheduleViewPagerSuccessItem( ) } Spacer( - modifier= Modifier.height(6.dp) + modifier = Modifier.height(6.dp) ) } item { @@ -190,7 +186,7 @@ fun ScheduleViewPagerSuccessItem( Spacer(modifier = Modifier.height(18.dp)) Divider( modifier = Modifier.fillMaxWidth(), - color = Brand200, + color = Brand200 ) Spacer( modifier = Modifier.height(18.dp) @@ -221,7 +217,6 @@ fun ScheduleViewPagerSuccessItem( ) } - AndroidView( modifier = Modifier .fillMaxWidth() @@ -281,4 +276,3 @@ fun Spanned.toAnnotatedString(): AnnotatedString = buildAnnotatedString { } } } - diff --git a/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt b/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt index c5246687..eae3d3b0 100644 --- a/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt +++ b/app/src/main/java/com/mashup/ui/schedule/util/ScheduleColor.kt @@ -3,7 +3,6 @@ package com.mashup.ui.schedule.util import androidx.compose.ui.graphics.Color import com.mashup.core.ui.widget.PlatformType - fun String.getEventTimelineBackgroundColor(): Color { return when (this) { "ALL" -> Color(0xFFE1F2FA) @@ -39,20 +38,17 @@ fun String.getButtonTextColor(): Color { "ALL" -> Color(0xFF358CB6) else -> Color(0xFF6A36FF) } - } - fun String.convertCamelCase(): PlatformType { return when (this) { - "ALL" -> PlatformType.Semina + "ALL" -> PlatformType.Seminar "DESIGN" -> PlatformType.Design "SPRING" -> PlatformType.Spring "IOS" -> PlatformType.Ios "ANDROID" -> PlatformType.Android "WEB" -> PlatformType.Web "NODE" -> PlatformType.Node - else -> PlatformType.Semina + else -> PlatformType.Seminar } } - diff --git a/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt b/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt index 242ef2bb..195a2596 100644 --- a/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt +++ b/core/ui/src/main/java/com/mashup/core/ui/widget/MashupPlatformBadge.kt @@ -1,10 +1,8 @@ package com.mashup.core.ui.widget -import androidx.annotation.DrawableRes import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding @@ -17,7 +15,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mashup.core.ui.R import com.mashup.core.ui.typography.Body3 @@ -25,11 +22,8 @@ import com.mashup.core.ui.typography.Body3 @Composable fun MashupPlatformBadge( platform: String, - modifier: Modifier = Modifier, + modifier: Modifier = Modifier ) { - val convertedPlatform = platform.convertCamelCase() - - Row( modifier = modifier .background( @@ -43,7 +37,7 @@ fun MashupPlatformBadge( Image( modifier = Modifier.size(12.dp), painter = painterResource(id = platform.getIcon()), - contentDescription = null, + contentDescription = null ) Spacer( modifier = Modifier.width(4.dp) @@ -56,20 +50,17 @@ fun MashupPlatformBadge( } } - private fun String.getIcon(): Int { return when (this) { "ALL" -> R.drawable.ic_semina else -> R.drawable.ic_platform } - } enum class PlatformType { - Semina, Design, Spring, Ios, Android, Web, Node + Seminar, Design, Spring, Ios, Android, Web, Node } - private fun String.getColor(): Color { return when (this) { "ALL" -> Color(0xFF7CD5FF) @@ -79,44 +70,13 @@ private fun String.getColor(): Color { private fun String.convertCamelCase(): PlatformType { return when (this) { - "ALL" -> PlatformType.Semina + "ALL" -> PlatformType.Seminar "DESIGN" -> PlatformType.Design "SPRING" -> PlatformType.Spring "IOS" -> PlatformType.Ios "ANDROID" -> PlatformType.Android "WEB" -> PlatformType.Web "NODE" -> PlatformType.Node - else -> PlatformType.Semina + else -> PlatformType.Seminar } } - - -@Preview -@Composable -private fun PreviewMashUpPlatformBadge() { - Column { - MashupPlatformBadge( - platform = "ALL" - ) - MashupPlatformBadge( - platform = "DESIGN" - ) - MashupPlatformBadge( - platform = "SPRING" - ) - MashupPlatformBadge( - platform = "IOS" - ) - MashupPlatformBadge( - platform = "ANDROID" - ) - MashupPlatformBadge( - platform = "WEB" - ) - MashupPlatformBadge( - platform = "NODE" - ) - - } - -} \ No newline at end of file From ef359c9f13e7e377bd8ed6b7a49ac8793bd58e78 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sat, 29 Jun 2024 22:58:13 +0900 Subject: [PATCH 023/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20EmptyCard?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleRoute.kt | 4 +- .../com/mashup/ui/schedule/ScheduleScreen.kt | 47 ++++++++----------- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index bb11758f..ddd17108 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.remember 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.platform.LocalContext import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource @@ -42,7 +43,6 @@ import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM import com.mashup.core.common.extensions.fromHtml import com.mashup.core.ui.colors.Brand500 -import com.mashup.core.ui.colors.Gray50 import com.mashup.core.ui.colors.White import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.widget.MashUpHtmlText @@ -122,7 +122,7 @@ fun ScheduleRoute( is ScheduleState.Empty -> {} else -> { ScheduleScreen( - modifier = Modifier.fillMaxSize().background(Gray50), + modifier = Modifier.fillMaxSize().background(color = Color.White), scheduleState = scheduleState, onClickScheduleInformation = { scheduleId: Int -> AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 750b4dc2..b6f14ecb 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -16,7 +16,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp -import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem +import com.mashup.ui.schedule.item.EmptyScheduleItem import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem import com.mashup.ui.schedule.item.ScheduleViewPagerSuccessItem import com.mashup.ui.schedule.model.ScheduleCard @@ -67,51 +67,43 @@ fun ScheduleScreen( Box( modifier = Modifier.fillMaxSize() ) { - ScheduleViewPagerEmptyItem( - modifier = Modifier - .graphicsLayer { - val pageOffset = ( - (horizontalPagerState.currentPage - index) + horizontalPagerState - .currentPageOffsetFraction - ).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - }, - data = data + EmptyScheduleItem( + modifier = Modifier.fillMaxSize().graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + } ) } } + is ScheduleCard.EndSchedule -> { Box( modifier = Modifier.fillMaxSize() ) { ScheduleViewPagerSuccessItem( - modifier = Modifier - .graphicsLayer { - val pageOffset = ( - (horizontalPagerState.currentPage - index) + horizontalPagerState - .currentPageOffsetFraction - ).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - }, + modifier = Modifier.graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + }, data = data, onClickScheduleInformation = onClickScheduleInformation, onClickAttendance = onClickAttendance ) } } + is ScheduleCard.InProgressSchedule -> { Box( modifier = Modifier.fillMaxSize() ) { ScheduleViewPagerInProgressItem( - modifier = Modifier - .graphicsLayer { - val pageOffset = ( - (horizontalPagerState.currentPage - index) + horizontalPagerState - .currentPageOffsetFraction - ).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - }, + modifier = Modifier.graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + }, data = data, onClickScheduleInformation = onClickScheduleInformation, onClickAttendance = onClickAttendance @@ -121,6 +113,7 @@ fun ScheduleScreen( } } } + else -> {} } } From 799880d421208ffc72f41d0224a8a14e1633f328 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sun, 30 Jun 2024 00:02:10 +0900 Subject: [PATCH 024/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20InProgress=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mashup/ui/schedule/ScheduleViewModel.kt | 4 +- .../mashup/ui/schedule/item/CardInfoItem.kt | 38 ++++--- .../item/SchedeuleViewPagerInProgressItem.kt | 101 +++++++++--------- app/src/main/res/values/strings.xml | 2 +- 4 files changed, 74 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt index 71fcb289..e95b9d00 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt @@ -1,6 +1,7 @@ package com.mashup.ui.schedule import com.mashup.core.common.base.BaseViewModel +import com.mashup.core.ui.widget.PlatformType import com.mashup.data.dto.ScheduleResponse import com.mashup.data.dto.SchedulesProgress import com.mashup.data.repository.AttendanceRepository @@ -8,6 +9,7 @@ import com.mashup.data.repository.ScheduleRepository import com.mashup.datastore.data.repository.AppPreferenceRepository import com.mashup.datastore.data.repository.UserPreferenceRepository import com.mashup.ui.schedule.model.ScheduleCard +import com.mashup.ui.schedule.util.convertCamelCase import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -89,7 +91,7 @@ class ScheduleViewModel @Inject constructor( attendanceRepository.getScheduleAttendanceInfo(scheduleResponse.scheduleId) .onSuccess { response -> - return if (response.attendanceInfos.isEmpty()) { + return if (response.attendanceInfos.isEmpty() && scheduleResponse.scheduleType.convertCamelCase() == PlatformType.Seminar) { ScheduleCard.InProgressSchedule( scheduleResponse = scheduleResponse, attendanceInfo = response diff --git a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt index 824596c3..8b4ebfe7 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/CardInfoItem.kt @@ -67,7 +67,7 @@ fun CardInfoItem( Text( style = Body4, - text = calendar, + text = calendar.ifEmpty { "-" }, color = Gray800 ) } @@ -84,32 +84,30 @@ fun CardInfoItem( colorFilter = ColorFilter.tint(color = Gray300) ) Text( - text = timeLine, + text = timeLine.ifEmpty { "-" }, style = Body4, color = Gray800 ) } - if (location.isNotEmpty()) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Image( - modifier = Modifier.size(20.dp), - painter = painterResource(id = R.drawable.ic_location), - contentDescription = null, - contentScale = ContentScale.Fit, - colorFilter = ColorFilter.tint(color = Gray300) - ) + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Image( + modifier = Modifier.size(20.dp), + painter = painterResource(id = R.drawable.ic_location), + contentDescription = null, + contentScale = ContentScale.Fit, + colorFilter = ColorFilter.tint(color = Gray300) + ) - Text( - style = Body4, - text = location, - color = Gray800 - ) - } + Text( + style = Body4, + text = location.ifEmpty { "-" }, + color = Gray800 + ) } } } diff --git a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt index 3147a9d3..c1d801ec 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt @@ -1,8 +1,6 @@ package com.mashup.ui.schedule.item -import android.text.SpannableStringBuilder import android.view.Gravity -import android.view.View import androidx.appcompat.widget.AppCompatTextView import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -15,34 +13,39 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember 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.toArgb import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.ParagraphStyle +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView -import androidx.compose.ui.viewinterop.AndroidViewBinding import androidx.constraintlayout.compose.ConstraintLayout -import androidx.core.content.res.ResourcesCompat -import androidx.core.text.HtmlCompat import com.mashup.R -import com.mashup.core.ui.colors.Brand100 -import com.mashup.core.ui.colors.Gray50 -import com.mashup.core.ui.colors.Gray700 import com.mashup.core.ui.theme.MashUpTheme -import com.mashup.core.ui.typography.Body1 import com.mashup.data.dto.ScheduleResponse -import com.mashup.databinding.LayoutAttendanceCoachMarkBindingImpl import com.mashup.ui.schedule.model.ScheduleCard import com.mashup.ui.schedule.util.getBackgroundColor import com.mashup.ui.schedule.util.getBorderColor +import com.mashup.ui.schedule.util.getButtonTextColor import java.util.Date @Composable @@ -52,6 +55,7 @@ fun ScheduleViewPagerInProgressItem( onClickScheduleInformation: (Int) -> Unit = {}, onClickAttendance: (Int) -> Unit = {} ) { + val textColor by remember { mutableStateOf(data.scheduleResponse.scheduleType.getButtonTextColor()) } Column( modifier = modifier .fillMaxWidth() @@ -80,18 +84,18 @@ fun ScheduleViewPagerInProgressItem( title = data.scheduleResponse.name, calendar = data.scheduleResponse.getDate(), timeLine = data.scheduleResponse.getTimeLine(), - location = "" + location = data.scheduleResponse.location?.detailAddress ?: "" ) Spacer(modifier = Modifier.height(16.dp)) ConstraintLayout { - val (coachMark, button, schedule) = createRefs() + val (button, schedule) = createRefs() Column( modifier = Modifier - .background(color = Gray50, shape = RoundedCornerShape(16.dp)) - .height(220.dp) - .padding(top = 16.dp, bottom = 20.dp, start = 20.dp, end = 20.dp) + .background(color = Color(0xFFE1F2FA), shape = RoundedCornerShape(16.dp)) + .height(176.dp) + .padding(top = 12.dp, bottom = 12.dp, start = 20.dp, end = 20.dp) .fillMaxWidth() .constrainAs(schedule) { top.linkTo(parent.top) @@ -102,53 +106,56 @@ fun ScheduleViewPagerInProgressItem( verticalArrangement = Arrangement.Center ) { Image( - painterResource(id = com.mashup.core.common.R.drawable.img_standby), + modifier = Modifier.size(100.dp), + painter = painterResource(id = com.mashup.core.common.R.drawable.img_standby), contentDescription = null ) Spacer( modifier = Modifier.height(10.dp) ) - val text = stringResource(id = R.string.description_standby_schedule) - val spannableString = SpannableStringBuilder( - String.format( - text, - data.attendanceInfo?.memberName ?: "알 수 없음" - ) - ).toString() + Text( - text = HtmlCompat.fromHtml( - spannableString, - HtmlCompat.FROM_HTML_MODE_COMPACT - ).toAnnotatedString(), - color = Gray700, - style = Body1 + text = buildAnnotatedString { + withStyle( + ParagraphStyle(lineHeight = 19.09.sp) + ) { + withStyle( + SpanStyle( + color = Color(0xFF4D535E), + fontSize = 16.sp, + fontWeight = FontWeight.W500 + ) + ) { + append(data.attendanceInfo?.memberName ?: "알 수 없음") + } + withStyle( + SpanStyle( + color = Color(0xFFABB2C1), + fontSize = 16.sp, + fontWeight = FontWeight.W400 + ) + ) { + append("님의\n참석을 기다리고 있어요.") + } + } + }, + textAlign = TextAlign.Center ) } - AndroidViewBinding( - modifier = Modifier.constrainAs(coachMark) { - bottom.linkTo(button.top, 4.dp) - start.linkTo(button.start) - end.linkTo(button.end) - }, - factory = LayoutAttendanceCoachMarkBindingImpl::inflate, - update = { - this.root.visibility = View.VISIBLE - } - ) AndroidView( modifier = Modifier .fillMaxWidth() .height(48.dp) .background( - color = Brand100, + color = Color(0xFFC2EBFF), shape = RoundedCornerShape(16.dp) ) .constrainAs(button) { bottom.linkTo(parent.bottom) start.linkTo(parent.start) end.linkTo(parent.end) - top.linkTo(schedule.bottom, 12.dp) + top.linkTo(schedule.bottom, 14.dp) }, factory = { context -> AppCompatTextView(context).apply { @@ -158,11 +165,7 @@ fun ScheduleViewPagerInProgressItem( ) gravity = Gravity.CENTER setTextColor( - ResourcesCompat.getColor( - resources, - com.mashup.core.common.R.color.brand500, - null - ) + textColor.toArgb() ) setPadding(12, 0, 0, 0) setOnClickListener { @@ -200,7 +203,7 @@ private fun PreviewScheduleViewPagerEmptySchedule() { roadAddress = null, detailAddress = null ), - scheduleType = "" + scheduleType = "ALL" ), attendanceInfo = null ) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c039c87d..a96eaa1f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,7 +46,7 @@ 조금만 기다려주세요!]]> 종료되었어요.]]> - %s님의\n출석을 기다리고 있어요!]]> + %s님의\n출석을 기다리고 있어요!]]> D-? 등록된 일정이 없어요 From 3020ea630f99197a2141df489067206434b93f0d Mon Sep 17 00:00:00 2001 From: 014967 Date: Sun, 30 Jun 2024 02:56:46 +0900 Subject: [PATCH 025/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20add=20empty=20sc?= =?UTF-8?q?hedule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 3 + .../java/com/mashup/ui/main/MainActivity.kt | 7 + .../com/mashup/ui/schedule/ScheduleRoute.kt | 33 +++-- .../com/mashup/ui/schedule/ScheduleScreen.kt | 114 ++------------- .../mashup/ui/schedule/ScheduleViewModel.kt | 61 +++++++- .../ui/schedule/component/WeeklySchedule.kt | 131 ++++++++++++++++++ .../item/ScheduleViewPagerEmptySchedule.kt | 23 +-- .../mashup/ui/schedule/model/ScheduleType.kt | 5 + .../res/drawable/img_placeholder_sleeping.png | Bin 12597 -> 2758 bytes 9 files changed, 250 insertions(+), 127 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt create mode 100644 app/src/main/java/com/mashup/ui/schedule/model/ScheduleType.kt diff --git a/app/build.gradle b/app/build.gradle index 58d84760..4d214b61 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -164,4 +164,7 @@ dependencies { // Naver Map implementation "io.github.fornewid:naver-map-compose:1.4.0" + + // Date Time + implementation 'com.jakewharton.threetenabp:threetenabp:1.3.1' } \ No newline at end of file diff --git a/app/src/main/java/com/mashup/ui/main/MainActivity.kt b/app/src/main/java/com/mashup/ui/main/MainActivity.kt index 4c230395..d8c4d268 100644 --- a/app/src/main/java/com/mashup/ui/main/MainActivity.kt +++ b/app/src/main/java/com/mashup/ui/main/MainActivity.kt @@ -5,11 +5,13 @@ import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.os.Build +import android.os.Bundle import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.core.content.ContextCompat import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.NavHostFragment +import com.jakewharton.threetenabp.AndroidThreeTen import com.mashup.R import com.mashup.base.BaseActivity import com.mashup.constant.EXTRA_ANIMATION @@ -64,6 +66,11 @@ class MainActivity : BaseActivity() { } } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + AndroidThreeTen.init(this) + } + override fun initViews() { super.initViews() diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index ddd17108..da694e53 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -25,6 +25,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -50,6 +51,7 @@ import com.mashup.ui.attendance.platform.PlatformAttendanceActivity import com.mashup.ui.main.MainViewModel import com.mashup.ui.schedule.component.ScheduleTabRow import com.mashup.ui.schedule.detail.ScheduleDetailActivity +import com.mashup.ui.schedule.model.ScheduleType import com.mashup.util.AnalyticsManager import com.mashup.core.common.R as CR @@ -86,20 +88,30 @@ fun ScheduleRoute( LaunchedEffect(scheduleState) { when (val state = scheduleState) { is ScheduleState.Loading -> {} - is ScheduleState.Empty -> { isRefreshing = false } + is ScheduleState.Init -> { + isRefreshing = false + } + is ScheduleState.Success -> { isRefreshing = false title = context.setUiOfScheduleTitle(state.scheduleTitleState) } - is ScheduleState.Error -> { isRefreshing = false } + + is ScheduleState.Error -> { + isRefreshing = false + } } } - var selectedTabIndex by remember { mutableStateOf(0) } + var selectedTabIndex by remember { mutableIntStateOf(0) } CompositionLocalProvider( LocalOverscrollConfiguration provides null ) { - Box(modifier = modifier.pullRefresh(pullRefreshState).background(White)) { + Box( + modifier = modifier + .pullRefresh(pullRefreshState) + .background(White) + ) { LazyColumn(modifier = modifier) { item { ScheduleTopbar(title) @@ -119,10 +131,12 @@ fun ScheduleRoute( item { when (scheduleState) { is ScheduleState.Error -> {} - is ScheduleState.Empty -> {} + is ScheduleState.Init -> {} else -> { ScheduleScreen( - modifier = Modifier.fillMaxSize().background(color = Color.White), + modifier = Modifier + .fillMaxSize() + .background(color = Color.White), scheduleState = scheduleState, onClickScheduleInformation = { scheduleId: Int -> AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) @@ -136,8 +150,8 @@ fun ScheduleRoute( PlatformAttendanceActivity.newIntent(context, scheduleId) ) }, - refreshState = isRefreshing - + refreshState = isRefreshing, + scheduleType = ScheduleType.values()[selectedTabIndex] ) } } @@ -160,12 +174,15 @@ fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String ScheduleTitleState.Empty -> { getString(R.string.empty_schedule) } + is ScheduleTitleState.End -> { getString(R.string.end_schedule, scheduleTitleState.generatedNumber) } + is ScheduleTitleState.DateCount -> { getString(R.string.event_list_title, scheduleTitleState.dataCount) } + is ScheduleTitleState.SchedulePreparing -> { getString(R.string.preparing_attendance) } diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index b6f14ecb..794de2ec 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -1,119 +1,31 @@ package com.mashup.ui.schedule -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.PageSize -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -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.graphics.graphicsLayer -import androidx.compose.ui.unit.dp -import com.mashup.ui.schedule.item.EmptyScheduleItem -import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem -import com.mashup.ui.schedule.item.ScheduleViewPagerSuccessItem -import com.mashup.ui.schedule.model.ScheduleCard -import kotlin.math.abs -import kotlin.math.absoluteValue +import com.mashup.ui.schedule.component.WeeklySchedule +import com.mashup.ui.schedule.model.ScheduleType @Composable fun ScheduleScreen( scheduleState: ScheduleState, modifier: Modifier = Modifier, + scheduleType: ScheduleType = ScheduleType.WEEK, onClickScheduleInformation: (Int) -> Unit = {}, onClickAttendance: (Int) -> Unit = {}, refreshState: Boolean = false ) { - var cacheScheduleState by remember { - mutableStateOf(scheduleState) - } - - LaunchedEffect(scheduleState) { - if (scheduleState is ScheduleState.Success) { - cacheScheduleState = scheduleState - } - } - - when (cacheScheduleState) { - is ScheduleState.Success -> { - val castingState = cacheScheduleState as ScheduleState.Success - val horizontalPagerState = rememberPagerState( - initialPage = if (castingState.scheduleList.size < 6) 1 else castingState.scheduleList.size - 4, - pageCount = { castingState.scheduleList.size } - ) - LaunchedEffect(refreshState) { - if (refreshState.not()) { // refresh 가 끝났을 경우 - horizontalPagerState.animateScrollToPage(castingState.schedulePosition) - } - } - - HorizontalPager( + when (scheduleType) { + ScheduleType.WEEK -> { + WeeklySchedule( + scheduleState = scheduleState, modifier = modifier, - state = horizontalPagerState, - pageSpacing = 12.dp, - pageSize = PageSize.Fill, - contentPadding = PaddingValues(33.dp), - verticalAlignment = Alignment.Top - ) { index -> - when (val data = castingState.scheduleList[index]) { - is ScheduleCard.EmptySchedule -> { - Box( - modifier = Modifier.fillMaxSize() - ) { - EmptyScheduleItem( - modifier = Modifier.fillMaxSize().graphicsLayer { - val pageOffset = - ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - } - ) - } - } - - is ScheduleCard.EndSchedule -> { - Box( - modifier = Modifier.fillMaxSize() - ) { - ScheduleViewPagerSuccessItem( - modifier = Modifier.graphicsLayer { - val pageOffset = - ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - }, - data = data, - onClickScheduleInformation = onClickScheduleInformation, - onClickAttendance = onClickAttendance - ) - } - } - - is ScheduleCard.InProgressSchedule -> { - Box( - modifier = Modifier.fillMaxSize() - ) { - ScheduleViewPagerInProgressItem( - modifier = Modifier.graphicsLayer { - val pageOffset = - ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue - scaleY = 1 - 0.1f * abs(pageOffset) - }, - data = data, - onClickScheduleInformation = onClickScheduleInformation, - onClickAttendance = onClickAttendance - ) - } - } - } - } + onClickScheduleInformation = onClickScheduleInformation, + onClickAttendance = onClickAttendance, + refreshState = refreshState + ) } - else -> {} + ScheduleType.TOTAL -> { + } } } diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt index e95b9d00..b156e7a7 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt @@ -16,6 +16,12 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first +import org.threeten.bp.DayOfWeek +import org.threeten.bp.Instant +import org.threeten.bp.LocalDateTime +import org.threeten.bp.ZoneId +import org.threeten.bp.temporal.TemporalAdjusters +import java.util.Date import javax.inject.Inject @HiltViewModel @@ -25,7 +31,7 @@ class ScheduleViewModel @Inject constructor( private val scheduleRepository: ScheduleRepository, private val attendanceRepository: AttendanceRepository ) : BaseViewModel() { - private val _scheduleState = MutableStateFlow(ScheduleState.Empty) + private val _scheduleState = MutableStateFlow(ScheduleState.Init) val scheduleState: StateFlow = _scheduleState private val _showCoachMark = MutableSharedFlow() @@ -39,19 +45,27 @@ class ScheduleViewModel @Inject constructor( scheduleRepository.getScheduleList(generateNumber) .onSuccess { response -> + + val weeklySchedule = if (response.scheduleList.isEmpty()) { + listOf() + } else { + response.scheduleList.filterSchedulesForCurrentWeek() + } _scheduleState.emit( ScheduleState.Success( scheduleTitleState = when { response.progress == SchedulesProgress.DONE -> { ScheduleTitleState.End(generateNumber) } + response.progress == SchedulesProgress.NOT_REGISTERED -> { ScheduleTitleState.Empty } - response.progress == SchedulesProgress.ON_GOING && - response.dateCount != null -> { + + response.progress == SchedulesProgress.ON_GOING && response.dateCount != null -> { ScheduleTitleState.DateCount(response.dateCount) } + else -> { ScheduleTitleState.SchedulePreparing } @@ -61,7 +75,15 @@ class ScheduleViewModel @Inject constructor( } else { response.scheduleList.map { mapperToScheduleCard(it) } }, - schedulePosition = getSchedulePosition(response.scheduleList) + schedulePosition = getSchedulePosition(response.scheduleList), + weeklySchedule = weeklySchedule.map { mapperToScheduleCard(it) }, + weeklySchedulePosition = if (weeklySchedule.isEmpty()) { + 0 + } else { + getSchedulePosition( + weeklySchedule + ) + } ) ) showCoachMark(response.scheduleList) @@ -71,13 +93,36 @@ class ScheduleViewModel @Inject constructor( ScheduleState.Success( scheduleTitleState = ScheduleTitleState.Empty, scheduleList = listOf(ScheduleCard.EmptySchedule()), - schedulePosition = 0 + schedulePosition = 0, + weeklySchedule = listOf(ScheduleCard.EmptySchedule()), + weeklySchedulePosition = 0 ) ) } } } + private fun List.filterSchedulesForCurrentWeek(): List { + val koreaZone = ZoneId.of("Asia/Seoul") + val now = LocalDateTime.now(koreaZone) + val startOfWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)) + val endOfWeek = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)) + val result = this.filter { + val scheduleStart = it.startedAt.toLocalDateTime(koreaZone) + scheduleStart.isAfter(startOfWeek.minusDays(1)) && scheduleStart.isBefore( + endOfWeek.plusDays( + 1 + ) + ) + } + return result + } + + private fun Date.toLocalDateTime(zone: ZoneId = ZoneId.systemDefault()): LocalDateTime { + val instant = Instant.ofEpochMilli(this.time) + return LocalDateTime.ofInstant(instant, zone) + } + override fun handleErrorCode(code: String) { mashUpScope { _scheduleState.emit(ScheduleState.Error(code)) @@ -135,12 +180,14 @@ sealed interface ScheduleTitleState { } sealed interface ScheduleState { - object Empty : ScheduleState + object Init : ScheduleState object Loading : ScheduleState data class Success( val scheduleTitleState: ScheduleTitleState, val scheduleList: List, - val schedulePosition: Int + val weeklySchedule: List, + val schedulePosition: Int, + val weeklySchedulePosition: Int ) : ScheduleState data class Error(val code: String) : ScheduleState diff --git a/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt b/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt new file mode 100644 index 00000000..3e2dd983 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt @@ -0,0 +1,131 @@ +package com.mashup.ui.schedule.component + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.PageSize +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.graphics.graphicsLayer +import androidx.compose.ui.unit.dp +import com.mashup.ui.schedule.ScheduleState +import com.mashup.ui.schedule.item.EmptyScheduleItem +import com.mashup.ui.schedule.item.ScheduleViewPagerEmptyItem +import com.mashup.ui.schedule.item.ScheduleViewPagerInProgressItem +import com.mashup.ui.schedule.item.ScheduleViewPagerSuccessItem +import com.mashup.ui.schedule.model.ScheduleCard +import kotlin.math.abs +import kotlin.math.absoluteValue + +@Composable +fun WeeklySchedule( + scheduleState: ScheduleState, + modifier: Modifier = Modifier, + onClickScheduleInformation: (Int) -> Unit = {}, + onClickAttendance: (Int) -> Unit = {}, + refreshState: Boolean = false +) { + var cacheScheduleState by remember { + mutableStateOf(scheduleState) + } + + LaunchedEffect(scheduleState) { + if (scheduleState is ScheduleState.Success) { + cacheScheduleState = scheduleState + } + } + + when (cacheScheduleState) { + is ScheduleState.Success -> { + val castingState = cacheScheduleState as ScheduleState.Success + val horizontalPagerState = rememberPagerState( + initialPage = castingState.weeklySchedulePosition, + pageCount = { castingState.weeklySchedule.size } + ) + LaunchedEffect(refreshState) { + if (refreshState.not()) { // refresh 가 끝났을 경우 + horizontalPagerState.animateScrollToPage( + castingState.weeklySchedulePosition + ) + } + } + + if (castingState.weeklySchedule.isEmpty()) { + EmptyScheduleItem( + modifier = modifier + ) + } else { + HorizontalPager( + modifier = modifier, + state = horizontalPagerState, + pageSpacing = 12.dp, + pageSize = PageSize.Fill, + contentPadding = PaddingValues(33.dp), + verticalAlignment = Alignment.Top + ) { index -> + when (val data = castingState.weeklySchedule[index]) { + is ScheduleCard.EmptySchedule -> { + Box( + modifier = Modifier.fillMaxSize() + ) { + ScheduleViewPagerEmptyItem( + modifier = Modifier + .fillMaxSize() + .graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + }, + data = data + ) + } + } + + is ScheduleCard.EndSchedule -> { + Box( + modifier = Modifier.fillMaxSize() + ) { + ScheduleViewPagerSuccessItem( + modifier = Modifier.graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + }, + data = data, + onClickScheduleInformation = onClickScheduleInformation, + onClickAttendance = onClickAttendance + ) + } + } + + is ScheduleCard.InProgressSchedule -> { + Box( + modifier = Modifier.fillMaxSize() + ) { + ScheduleViewPagerInProgressItem( + modifier = Modifier.graphicsLayer { + val pageOffset = + ((horizontalPagerState.currentPage - index) + horizontalPagerState.currentPageOffsetFraction).absoluteValue + scaleY = 1 - 0.1f * abs(pageOffset) + }, + data = data, + onClickScheduleInformation = onClickScheduleInformation, + onClickAttendance = onClickAttendance + ) + } + } + } + } + } + } + else -> {} + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt index 8d6fd550..5c8560c6 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerEmptySchedule.kt @@ -22,12 +22,12 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.mashup.R -import com.mashup.core.ui.colors.Gray100 import com.mashup.core.ui.colors.Gray400 -import com.mashup.core.ui.colors.Gray50 import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.typography.Body1 import com.mashup.ui.schedule.model.ScheduleCard +import com.mashup.ui.schedule.util.getBackgroundColor +import com.mashup.ui.schedule.util.getBorderColor @Composable fun ScheduleViewPagerEmptyItem( @@ -36,28 +36,29 @@ fun ScheduleViewPagerEmptyItem( ) { Column( modifier = modifier.fillMaxWidth().wrapContentHeight().background( - color = Color.White, + color = data.scheduleResponse?.scheduleType?.getBackgroundColor() ?: Color(0xFFECF9FF), shape = RoundedCornerShape(20.dp) - ).border( - width = 1.dp, - color = Gray100, - shape = RoundedCornerShape(20.dp) - ).padding(20.dp), + ) + .border( + width = 1.dp, + color = data.scheduleResponse?.scheduleType?.getBorderColor() ?: Color(0xFFE1F2FA), + shape = RoundedCornerShape(20.dp) + ).padding(20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { CardInfoItem( modifier = Modifier.fillMaxWidth().wrapContentHeight(), - platform = data.scheduleResponse?.scheduleType ?: "", + platform = data.scheduleResponse?.scheduleType ?: "ALL", title = data.scheduleResponse?.name ?: "", calendar = data.scheduleResponse?.getDate() ?: "-", timeLine = data.scheduleResponse?.getTimeLine() ?: "-", - location = "" + location = "-" ) Spacer(modifier = Modifier.height(16.dp)) Box( modifier = Modifier.fillMaxWidth().background( - color = Gray50, + color = Color(0xFFE1F2FA), shape = RoundedCornerShape(16.dp) ).padding( vertical = 22.dp, diff --git a/app/src/main/java/com/mashup/ui/schedule/model/ScheduleType.kt b/app/src/main/java/com/mashup/ui/schedule/model/ScheduleType.kt new file mode 100644 index 00000000..16d17a31 --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/model/ScheduleType.kt @@ -0,0 +1,5 @@ +package com.mashup.ui.schedule.model + +enum class ScheduleType { + WEEK, TOTAL +} diff --git a/core/common/src/main/res/drawable/img_placeholder_sleeping.png b/core/common/src/main/res/drawable/img_placeholder_sleeping.png index aea507e88b282b398ced8db7f7aa2cfd9d400c16..8a2ca2459444b42d4e32527f1459e6f93f064c62 100644 GIT binary patch delta 2757 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 From 26400e75a7179e7dc25183b842e358c5e035d45b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sun, 30 Jun 2024 03:15:11 +0900 Subject: [PATCH 026/110] =?UTF-8?q?=F0=9F=A7=B8=20ScheduleScreen=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EB=A5=BC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=ED=95=98=EB=8A=94=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleRoute.kt | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index da694e53..f8f60d24 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -138,18 +138,8 @@ fun ScheduleRoute( .fillMaxSize() .background(color = Color.White), scheduleState = scheduleState, - onClickScheduleInformation = { scheduleId: Int -> - AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) - context.startActivity( - ScheduleDetailActivity.newIntent(context, scheduleId) - ) - }, - onClickAttendance = { scheduleId: Int -> - AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_STATUS_CONFIRM) - context.startActivity( - PlatformAttendanceActivity.newIntent(context, scheduleId) - ) - }, + onClickScheduleInformation = { context.moveToScheduleInformation(it) }, + onClickAttendance = { context.moveToAttendance(it) }, refreshState = isRefreshing, scheduleType = ScheduleType.values()[selectedTabIndex] ) @@ -189,6 +179,21 @@ fun Context.setUiOfScheduleTitle(scheduleTitleState: ScheduleTitleState): String } } +fun Context.moveToScheduleInformation(scheduleId: Int) { + AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_EVENT_DETAIL) + startActivity( + ScheduleDetailActivity.newIntent(this, scheduleId) + ) +} + +fun Context.moveToAttendance(scheduleId: Int) { + AnalyticsManager.addEvent(eventName = LOG_SCHEDULE_STATUS_CONFIRM) + startActivity( + PlatformAttendanceActivity.newIntent(this, scheduleId) + ) + +} + @Composable fun ScheduleTopbar(title: String) { Row( From 3f00ca08a60516327795b72c0ff7478a12bf33af Mon Sep 17 00:00:00 2001 From: 014967 Date: Sun, 30 Jun 2024 03:31:35 +0900 Subject: [PATCH 027/110] =?UTF-8?q?=F0=9F=A7=B8feat=20:=20add=20spacer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mashup/ui/schedule/component/WeeklySchedule.kt | 1 + .../mashup/ui/schedule/item/EmptyScheduleItem.kt | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt b/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt index 3e2dd983..12edd69b 100644 --- a/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt +++ b/app/src/main/java/com/mashup/ui/schedule/component/WeeklySchedule.kt @@ -126,6 +126,7 @@ fun WeeklySchedule( } } } + else -> {} } } diff --git a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt index 5a585552..efe58e7e 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/EmptyScheduleItem.kt @@ -5,6 +5,7 @@ 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.Spacer import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.width import androidx.compose.material3.Text @@ -28,8 +29,11 @@ fun EmptyScheduleItem( Column( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(17.dp) + verticalArrangement = Arrangement.Center ) { + Spacer( + modifier = Modifier.height(34.dp) + ) Image( painter = painterResource(id = CommonR.drawable.img_empty_schdule), contentDescription = null, @@ -37,12 +41,17 @@ fun EmptyScheduleItem( .width(284.dp) .height(256.dp) ) - + Spacer( + modifier = Modifier.height(17.dp) + ) Text( text = "이번주는 자유다..!", style = Header2, color = Color(0xFF412491) ) + Spacer( + modifier = Modifier.height(17.dp) + ) MashUpGradientButton( modifier = Modifier .width(256.dp) From e87641d4493ba8d8535d7ef0c9a9e064c441ec11 Mon Sep 17 00:00:00 2001 From: 014967 Date: Sun, 30 Jun 2024 03:33:37 +0900 Subject: [PATCH 028/110] [refactor] apply lint --- app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index f8f60d24..07cb9021 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -191,7 +191,6 @@ fun Context.moveToAttendance(scheduleId: Int) { startActivity( PlatformAttendanceActivity.newIntent(this, scheduleId) ) - } @Composable From 2df6ed272a8da6abf0dcff800c23bde7b9efcef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sun, 30 Jun 2024 03:54:34 +0900 Subject: [PATCH 029/110] =?UTF-8?q?=F0=9F=A7=B8=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=EC=97=90=EC=84=9C=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A4=84=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EA=B0=80=EA=B3=B5=20?= =?UTF-8?q?(=EC=9B=94/=EC=9D=BC=EB=B3=84=EB=A1=9C=20=EB=AC=B6=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EB=B3=B4=EC=97=AC=EC=A4=80=EB=8B=A4.)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleRoute.kt | 13 ++++--- .../mashup/ui/schedule/ScheduleViewModel.kt | 13 +++++++ .../mashup/core/common/extensions/DateExt.kt | 34 +++++++++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index 07cb9021..fe951e0c 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -44,6 +44,7 @@ import com.mashup.constant.log.LOG_SCHEDULE_EVENT_DETAIL import com.mashup.constant.log.LOG_SCHEDULE_STATUS_CONFIRM import com.mashup.core.common.extensions.fromHtml import com.mashup.core.ui.colors.Brand500 +import com.mashup.core.ui.colors.Gray50 import com.mashup.core.ui.colors.White import com.mashup.core.ui.theme.MashUpTheme import com.mashup.core.ui.widget.MashUpHtmlText @@ -110,12 +111,15 @@ fun ScheduleRoute( Box( modifier = modifier .pullRefresh(pullRefreshState) - .background(White) + .background(color = if (ScheduleType.values()[selectedTabIndex] == ScheduleType.WEEK) Color.White else Gray50) ) { LazyColumn(modifier = modifier) { item { ScheduleTopbar(title) - Spacer(modifier = Modifier.height(26.dp)) + Spacer(modifier = Modifier + .height(26.dp) + .fillMaxWidth() + .background(Color.White)) } stickyHeader { @@ -134,9 +138,7 @@ fun ScheduleRoute( is ScheduleState.Init -> {} else -> { ScheduleScreen( - modifier = Modifier - .fillMaxSize() - .background(color = Color.White), + modifier = Modifier.fillMaxSize(), scheduleState = scheduleState, onClickScheduleInformation = { context.moveToScheduleInformation(it) }, onClickAttendance = { context.moveToAttendance(it) }, @@ -197,6 +199,7 @@ fun Context.moveToAttendance(scheduleId: Int) { fun ScheduleTopbar(title: String) { Row( modifier = Modifier + .background(White) .padding(horizontal = 20.dp) .padding(top = 24.dp) .fillMaxWidth(), diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt index b156e7a7..ddfcae3c 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleViewModel.kt @@ -1,6 +1,8 @@ package com.mashup.ui.schedule import com.mashup.core.common.base.BaseViewModel +import com.mashup.core.common.extensions.month +import com.mashup.core.common.extensions.year import com.mashup.core.ui.widget.PlatformType import com.mashup.data.dto.ScheduleResponse import com.mashup.data.dto.SchedulesProgress @@ -75,6 +77,7 @@ class ScheduleViewModel @Inject constructor( } else { response.scheduleList.map { mapperToScheduleCard(it) } }, + monthlyScheduleList = getMonthlyScheduleList(response.scheduleList), schedulePosition = getSchedulePosition(response.scheduleList), weeklySchedule = weeklySchedule.map { mapperToScheduleCard(it) }, weeklySchedulePosition = if (weeklySchedule.isEmpty()) { @@ -93,6 +96,7 @@ class ScheduleViewModel @Inject constructor( ScheduleState.Success( scheduleTitleState = ScheduleTitleState.Empty, scheduleList = listOf(ScheduleCard.EmptySchedule()), + monthlyScheduleList = emptyList(), schedulePosition = 0, weeklySchedule = listOf(ScheduleCard.EmptySchedule()), weeklySchedulePosition = 0 @@ -155,6 +159,14 @@ class ScheduleViewModel @Inject constructor( return ScheduleCard.EmptySchedule(scheduleResponse) } + private fun getMonthlyScheduleList(scheduleList: List): List>> { + return scheduleList.groupBy { + val year = it.startedAt.year() + val month = it.startedAt.month() + "${year}년 ${month}월" + }.toList() + } + private fun getSchedulePosition(schedules: List): Int { return schedules.size - schedules.filter { it.dateCount >= 0 }.size } @@ -185,6 +197,7 @@ sealed interface ScheduleState { data class Success( val scheduleTitleState: ScheduleTitleState, val scheduleList: List, + val monthlyScheduleList: List>>, val weeklySchedule: List, val schedulePosition: Int, val weeklySchedulePosition: Int diff --git a/core/common/src/main/java/com/mashup/core/common/extensions/DateExt.kt b/core/common/src/main/java/com/mashup/core/common/extensions/DateExt.kt index c0c8fdbe..d67df070 100644 --- a/core/common/src/main/java/com/mashup/core/common/extensions/DateExt.kt +++ b/core/common/src/main/java/com/mashup/core/common/extensions/DateExt.kt @@ -1,6 +1,7 @@ package com.mashup.core.common.extensions import java.text.SimpleDateFormat +import java.util.Calendar import java.util.Date import java.util.Locale import java.util.TimeZone @@ -19,3 +20,36 @@ fun Date.getTimeFormat(): String { "??:??" } } + +fun Date.year(): Int { + val calendar = Calendar.getInstance() + calendar.time = this + return calendar.get(Calendar.YEAR) +} + +fun Date.month(): Int { + val calendar = Calendar.getInstance() + calendar.time = this + return calendar.get(Calendar.MONTH) + 1 +} + +fun Date.day(): Int { + val calendar = Calendar.getInstance() + calendar.time = this + return calendar.get(Calendar.DATE) +} + +fun Date.week(): String { + val calendar = Calendar.getInstance() + calendar.time = this + return when (calendar.get(Calendar.DAY_OF_WEEK)) { + Calendar.MONDAY -> "월" + Calendar.TUESDAY -> "화" + Calendar.WEDNESDAY -> "수" + Calendar.THURSDAY -> "목" + Calendar.FRIDAY -> "금" + Calendar.SATURDAY -> "토" + Calendar.SUNDAY -> "일" + else -> "" + } +} From 38274ccb8983dc32459fde1e478045ab426cfee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A0=95=EB=AF=BC=EC=A7=80?= Date: Sun, 30 Jun 2024 05:04:54 +0900 Subject: [PATCH 030/110] =?UTF-8?q?=F0=9F=A7=B8=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=A0=20Composable=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EB=B0=8F=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mashup/ui/schedule/ScheduleRoute.kt | 10 +- .../com/mashup/ui/schedule/ScheduleScreen.kt | 6 ++ .../ui/schedule/component/DailySchedule.kt | 83 ++++++++++++++++ .../ui/schedule/daily/DailyScheduleByMonth.kt | 86 +++++++++++++++++ .../ui/schedule/daily/DailyScheduleItem.kt | 95 +++++++++++++++++++ 5 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/mashup/ui/schedule/component/DailySchedule.kt create mode 100644 app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleByMonth.kt create mode 100644 app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleItem.kt diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt index fe951e0c..5d5ef5e3 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleRoute.kt @@ -116,10 +116,12 @@ fun ScheduleRoute( LazyColumn(modifier = modifier) { item { ScheduleTopbar(title) - Spacer(modifier = Modifier - .height(26.dp) - .fillMaxWidth() - .background(Color.White)) + Spacer( + modifier = Modifier + .height(26.dp) + .fillMaxWidth() + .background(Color.White) + ) } stickyHeader { diff --git a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt index 794de2ec..dfdbe61e 100644 --- a/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt +++ b/app/src/main/java/com/mashup/ui/schedule/ScheduleScreen.kt @@ -2,6 +2,7 @@ package com.mashup.ui.schedule import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import com.mashup.ui.schedule.component.DailySchedule import com.mashup.ui.schedule.component.WeeklySchedule import com.mashup.ui.schedule.model.ScheduleType @@ -26,6 +27,11 @@ fun ScheduleScreen( } ScheduleType.TOTAL -> { + DailySchedule( + scheduleState = scheduleState, + modifier = modifier, + onClickScheduleInformation = onClickScheduleInformation + ) } } } diff --git a/app/src/main/java/com/mashup/ui/schedule/component/DailySchedule.kt b/app/src/main/java/com/mashup/ui/schedule/component/DailySchedule.kt new file mode 100644 index 00000000..e64cb46f --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/component/DailySchedule.kt @@ -0,0 +1,83 @@ +package com.mashup.ui.schedule.component + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.colors.Gray50 +import com.mashup.core.ui.colors.Gray600 +import com.mashup.core.ui.typography.Body5 +import com.mashup.ui.schedule.ScheduleState +import com.mashup.ui.schedule.daily.DailyScheduleByMonth +import com.mashup.core.common.R as CR + +@Composable +fun DailySchedule( + scheduleState: ScheduleState, + modifier: Modifier = Modifier, + onClickScheduleInformation: (Int) -> Unit = {} +) { + var cacheScheduleState by remember { + mutableStateOf(scheduleState) + } + + LaunchedEffect(scheduleState) { + if (scheduleState is ScheduleState.Success) { + cacheScheduleState = scheduleState + } + } + + (cacheScheduleState as? ScheduleState.Success)?.let { state -> + if (state.monthlyScheduleList.isEmpty()) { + Column( + modifier = Modifier + .fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer(modifier = Modifier.height(200.dp)) + Image( + painter = painterResource(id = CR.drawable.img_placeholder_sleeping), + contentDescription = null, + modifier = Modifier.size(88.dp) + ) + Spacer(modifier = Modifier.height(12.dp)) + Text( + text = "열심히 일정을 준비하고 있어요\n조금만 기다려 주세요!", + style = Body5.copy(color = Gray600), + textAlign = TextAlign.Center + ) + } + } else { + Spacer(modifier = Modifier.height(22.dp)) + state.monthlyScheduleList.forEach { (title, scheduleList) -> + DailyScheduleByMonth( + title = title, + scheduleList = scheduleList, + modifier = Modifier + .background(Gray50) + .padding(horizontal = 20.dp), + isWeeklySchedule = { scheduleId -> + state.weeklySchedule.any { scheduleId == it.getScheduleId() } + }, + onClickScheduleInformation = onClickScheduleInformation + ) + } + } + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleByMonth.kt b/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleByMonth.kt new file mode 100644 index 00000000..4af7f82b --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleByMonth.kt @@ -0,0 +1,86 @@ +package com.mashup.ui.schedule.daily + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +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 +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.common.extensions.day +import com.mashup.core.common.extensions.week +import com.mashup.core.ui.colors.Gray500 +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.Body3 +import com.mashup.core.ui.typography.Caption2 +import com.mashup.core.ui.typography.Title3 +import com.mashup.data.dto.ScheduleResponse + +/** + * DailyScheduleByMonth.kt + * + * Created by Minji Jeong on 2024/06/29 + * Copyright © 2024 MashUp All rights reserved. + */ + +@Composable +fun DailyScheduleByMonth( + title: String, + scheduleList: List, + modifier: Modifier = Modifier, + isWeeklySchedule: (Int) -> Boolean = { false }, + onClickScheduleInformation: (Int) -> Unit = {} +) { + Column(modifier = modifier) { + Text(title, style = Title3) + Spacer(modifier = Modifier.height(18.dp)) + scheduleList + .groupBy { it.startedAt.day() } + .forEach { (_, dailySchedule) -> + DailyScheduleByDay(dailySchedule, isWeeklySchedule, onClickScheduleInformation) + } + } +} + +@Composable +fun DailyScheduleByDay( + schedule: List, + isWeeklySchedule: (Int) -> Boolean, + onClickScheduleInformation: (Int) -> Unit +) { + Row(modifier = Modifier.padding(bottom = 32.dp)) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(top = 14.dp, end = 14.dp) + ) { + Text(text = "${schedule[0].startedAt.day()}", style = Body3) + Text(text = schedule[0].startedAt.week(), style = Caption2.copy(color = Gray500)) + } + + Column { + schedule.forEach { + val highlight = isWeeklySchedule.invoke(it.scheduleId) + DailyScheduleItem( + title = it.name, + time = it.getTimeLine(), + place = it.location?.detailAddress ?: "-", + highlight = highlight, + modifier = Modifier.padding(bottom = 12.dp), + onClickScheduleInformation = { onClickScheduleInformation.invoke(it.scheduleId) } + ) + } + } + } +} + +@Preview +@Composable +fun PreviewDailySchedule() { + MashUpTheme { + DailyScheduleByMonth("2024년 8월", emptyList()) + } +} diff --git a/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleItem.kt b/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleItem.kt new file mode 100644 index 00000000..7345b01f --- /dev/null +++ b/app/src/main/java/com/mashup/ui/schedule/daily/DailyScheduleItem.kt @@ -0,0 +1,95 @@ +package com.mashup.ui.schedule.daily + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.mashup.core.ui.colors.Brand500 +import com.mashup.core.ui.colors.Gray100 +import com.mashup.core.ui.colors.White +import com.mashup.core.ui.theme.MashUpTheme +import com.mashup.core.ui.typography.SubTitle1 +import com.mashup.ui.schedule.detail.composable.ScheduleInfoText +import com.mashup.core.common.R as CR + +/** + * TotalScheduleItem.kt + * + * Created by Minji Jeong on 2024/06/29 + * Copyright © 2024 MashUp All rights reserved. + */ + +@Composable +fun DailyScheduleItem( + title: String, + time: String, + place: String, + highlight: Boolean, + modifier: Modifier = Modifier, + onClickScheduleInformation: () -> Unit = {} +) { + val borderColor = if (highlight) { + listOf(Brand500, Color(0xFF31C1FF)) + } else { + listOf(Gray100, Gray100) + } + + Column( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(16.dp)) + .clickable { onClickScheduleInformation() } + .background(White) + .border( + width = if (highlight) (1.5).dp else 1.dp, + brush = Brush.horizontalGradient(borderColor), + shape = RoundedCornerShape(16.dp) + ) + .padding(horizontal = 20.dp, vertical = 16.dp) + ) { + Text(text = title, style = SubTitle1) + Spacer(modifier = Modifier.height(4.dp)) + ScheduleInfoText(iconRes = CR.drawable.ic_clock, info = time) + Spacer(modifier = Modifier.height(4.dp)) + ScheduleInfoText(iconRes = CR.drawable.ic_mappin, info = place) + } +} + +@Preview +@Composable +fun PreviewDailyScheduleItemHighlight() { + MashUpTheme { + DailyScheduleItem( + "안드로이드 팀 세미나", + "오후 3:00 - 오전 7:00", + "디스코드", + true + ) + } +} + +@Preview +@Composable +fun PreviewDailyScheduleItem() { + MashUpTheme { + DailyScheduleItem( + "안드로이드 팀 세미나", + "오후 3:00 - 오전 7:00", + "디스코드", + false + ) + } +} From 4664028c24aa81113504877abb08865e456466c1 Mon Sep 17 00:00:00 2001 From: 014967 Date: Mon, 1 Jul 2024 18:01:36 +0900 Subject: [PATCH 031/110] parse notice --- .../com/mashup/data/dto/ScheduleResponse.kt | 2 + .../item/SchedeuleViewPagerInProgressItem.kt | 3 +- .../item/ScheduleViewPagerSuccessItem.kt | 144 +++++++++++++----- 3 files changed, 113 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt index 5ec60f23..80003897 100644 --- a/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt +++ b/app/src/main/java/com/mashup/data/dto/ScheduleResponse.kt @@ -11,6 +11,8 @@ import java.util.Locale data class ScheduleResponse( @field:Json(name = "scheduleType") val scheduleType: String, + @field:Json(name = "notice") + val notice: String?, @field:Json(name = "scheduleId") val scheduleId: Int, @field:Json(name = "dateCount") diff --git a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt index c1d801ec..e5339ad6 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/SchedeuleViewPagerInProgressItem.kt @@ -203,7 +203,8 @@ private fun PreviewScheduleViewPagerEmptySchedule() { roadAddress = null, detailAddress = null ), - scheduleType = "ALL" + scheduleType = "ALL", + notice = null ), attendanceInfo = null ) diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt index 71f36f4b..d00a7feb 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt @@ -8,14 +8,20 @@ import android.text.style.StyleSpan import android.text.style.UnderlineSpan import android.view.Gravity import androidx.appcompat.widget.AppCompatTextView +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border 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.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed @@ -33,6 +39,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.SpanStyle @@ -48,10 +55,12 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.core.text.HtmlCompat import com.mashup.R import com.mashup.core.ui.colors.Brand200 +import com.mashup.core.ui.colors.Gray600 import com.mashup.core.ui.colors.Gray700 import com.mashup.core.ui.colors.Gray900 import com.mashup.core.ui.typography.Body1 import com.mashup.core.ui.typography.Body5 +import com.mashup.core.ui.typography.Caption1 import com.mashup.core.ui.typography.SubTitle2 import com.mashup.core.ui.widget.PlatformType import com.mashup.data.dto.EventResponse @@ -182,6 +191,31 @@ fun ScheduleViewPagerSuccessItem( Spacer( modifier = Modifier.height(12.dp) ) + AndroidView( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .background( + color = data.scheduleResponse.scheduleType.getButtonBackgroundColor(), + shape = RoundedCornerShape(16.dp) + ), + factory = { context -> + AppCompatTextView(context).apply { + text = context.getString(R.string.click_attendance_list) + setTextAppearance( + com.mashup.core.common.R.style.TextAppearance_Mashup_Body3_14_M + ) + gravity = Gravity.CENTER + setTextColor( + textColor.toArgb() + ) + setPadding(12, 0, 0, 0) + setOnClickListener { + onClickAttendance(data.scheduleResponse.scheduleId) + } + } + } + ) } else { Spacer(modifier = Modifier.height(18.dp)) Divider( @@ -203,45 +237,85 @@ fun ScheduleViewPagerSuccessItem( Spacer( modifier = Modifier.height(6.dp) ) - Text( - text = "가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카타파하가나다라마바사아자차카", - maxLines = 5, - style = Body5.copy( - lineHeight = 20.sp - ), - color = Gray700, - overflow = TextOverflow.Ellipsis - ) - Spacer( - modifier = Modifier.height(40.dp) - ) - } - AndroidView( - modifier = Modifier - .fillMaxWidth() - .height(48.dp) - .background( - color = data.scheduleResponse.scheduleType.getButtonBackgroundColor(), - shape = RoundedCornerShape(16.dp) - ), - factory = { context -> - AppCompatTextView(context).apply { - text = context.getString(R.string.click_attendance_list) - setTextAppearance( - com.mashup.core.common.R.style.TextAppearance_Mashup_Body3_14_M - ) - gravity = Gravity.CENTER - setTextColor( - textColor.toArgb() - ) - setPadding(12, 0, 0, 0) - setOnClickListener { - onClickAttendance(data.scheduleResponse.scheduleId) + if (data.scheduleResponse.notice == null) { + Box( + modifier = Modifier + .fillMaxWidth() + .background( + color = Color(0xFFEFE9F8), + shape = RoundedCornerShape(16.dp) + ) + .padding( + vertical = 22.dp, + horizontal = 20.dp + ), + contentAlignment = Alignment.Center + ) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Image( + modifier = Modifier.size(88.dp), + painter = painterResource(id = com.mashup.core.common.R.drawable.img_placeholder_sleeping), + contentDescription = null + ) + Text( + text = "공지가 없어요!", + style = Caption1, + color = Gray600, + ) + } } + } else { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ){ + Text( + text = data.scheduleResponse.notice, + maxLines = 5, + style = Body5.copy( + lineHeight = 20.sp + ), + color = Gray700, + overflow = TextOverflow.Ellipsis, + textAlign = TextAlign.Left + ) + } + AndroidView( + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + .background( + color = data.scheduleResponse.scheduleType.getButtonBackgroundColor(), + shape = RoundedCornerShape(16.dp) + ), + factory = { context -> + AppCompatTextView(context).apply { + text = context.getString(R.string.click_attendance_list) + setTextAppearance( + com.mashup.core.common.R.style.TextAppearance_Mashup_Body3_14_M + ) + gravity = Gravity.CENTER + setTextColor( + textColor.toArgb() + ) + setPadding(12, 0, 0, 0) + setOnClickListener { + onClickAttendance(data.scheduleResponse.scheduleId) + } + } + } + ) } - ) + Spacer( + modifier = Modifier.height(40.dp) + ) + } } } From 674cbe0e52b02e805132aac917877d149816c198 Mon Sep 17 00:00:00 2001 From: 014967 Date: Wed, 3 Jul 2024 22:18:46 +0900 Subject: [PATCH 032/110] =?UTF-8?q?=ED=94=8C=EB=9E=AB=ED=8F=BC=20=EA=B3=B5?= =?UTF-8?q?=EC=A7=80=EA=B0=80=20=EC=97=86=EC=9D=84=20=EB=95=8C=20=EC=97=AC?= =?UTF-8?q?=EB=B0=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/schedule/item/ScheduleViewPagerSuccessItem.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt index d00a7feb..b2531e1a 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt @@ -267,7 +267,6 @@ fun ScheduleViewPagerSuccessItem( style = Caption1, color = Gray600, ) - } } } else { @@ -311,10 +310,11 @@ fun ScheduleViewPagerSuccessItem( } } ) + Spacer( + modifier = Modifier.height(40.dp) + ) } - Spacer( - modifier = Modifier.height(40.dp) - ) + } } } From b3655fd373640165b9c4b685d8ed26b5070a55a9 Mon Sep 17 00:00:00 2001 From: 014967 Date: Wed, 3 Jul 2024 22:22:06 +0900 Subject: [PATCH 033/110] =?UTF-8?q?=EB=A6=B0=ED=8A=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt index b2531e1a..679a3484 100644 --- a/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt +++ b/app/src/main/java/com/mashup/ui/schedule/item/ScheduleViewPagerSuccessItem.kt @@ -265,7 +265,7 @@ fun ScheduleViewPagerSuccessItem( Text( text = "공지가 없어요!", style = Caption1, - color = Gray600, + color = Gray600 ) } } @@ -273,7 +273,7 @@ fun ScheduleViewPagerSuccessItem( Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically - ){ + ) { Text( text = data.scheduleResponse.notice, maxLines = 5, @@ -314,7 +314,6 @@ fun ScheduleViewPagerSuccessItem( modifier = Modifier.height(40.dp) ) } - } } } From b2748ed5df0928b4629e04a63f903bf2cd13bdbd Mon Sep 17 00:00:00 2001 From: 014967 Date: Wed, 3 Jul 2024 22:54:41 +0900 Subject: [PATCH 034/110] =?UTF-8?q?=EC=B4=88=EA=B8=B0=20moreMenu=20feature?= =?UTF-8?q?=20=EA=B5=AC=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/moreMenu/.gitignore | 1 + feature/moreMenu/build.gradle | 74 +++++++++++++++++++ feature/moreMenu/consumer-rules.pro | 0 feature/moreMenu/proguard-rules.pro | 21 ++++++ .../moremenu/ExampleInstrumentedTest.kt | 24 ++++++ feature/moreMenu/src/main/AndroidManifest.xml | 12 +++ .../com/example/moremenu/MoreMenuActivity.kt | 27 +++++++ .../com/example/moremenu/MoreMenuScreen.kt | 11 +++ .../moreMenu/src/main/res/values/strings.xml | 3 + .../moreMenu/src/main/res/values/themes.xml | 5 ++ .../com/example/moremenu/ExampleUnitTest.kt | 17 +++++ settings.gradle | 1 + 12 files changed, 196 insertions(+) create mode 100644 feature/moreMenu/.gitignore create mode 100644 feature/moreMenu/build.gradle create mode 100644 feature/moreMenu/consumer-rules.pro create mode 100644 feature/moreMenu/proguard-rules.pro create mode 100644 feature/moreMenu/src/androidTest/java/com/example/moremenu/ExampleInstrumentedTest.kt create mode 100644 feature/moreMenu/src/main/AndroidManifest.xml create mode 100644 feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuActivity.kt create mode 100644 feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuScreen.kt create mode 100644 feature/moreMenu/src/main/res/values/strings.xml create mode 100644 feature/moreMenu/src/main/res/values/themes.xml create mode 100644 feature/moreMenu/src/test/java/com/example/moremenu/ExampleUnitTest.kt diff --git a/feature/moreMenu/.gitignore b/feature/moreMenu/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/feature/moreMenu/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/moreMenu/build.gradle b/feature/moreMenu/build.gradle new file mode 100644 index 00000000..f2e73227 --- /dev/null +++ b/feature/moreMenu/build.gradle @@ -0,0 +1,74 @@ +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' + id 'com.google.dagger.hilt.android' +} + +android { + namespace 'com.example.moremenu' + compileSdk compileVersion + + defaultConfig { + minSdk minVersion + targetSdk targetVersion + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + vectorDrawables { + useSupportLibrary true + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + compose true + } + composeOptions { + kotlinCompilerExtensionVersion composeCompiler + } + + kotlinOptions { + jvmTarget = '1.8' + } + kapt { + correctErrorTypes = true + } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' + } + } +} + +dependencies { + + implementation project(":core:common") + implementation project(':core:ui') + implementation project(":core:datastore") + implementation project(":core:model") + implementation project(':core:network') + implementation project(':core:data') + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.3' + implementation 'androidx.activity:activity-compose:1.9.0' + implementation platform('androidx.compose:compose-bom:2023.08.00') + implementation 'androidx.compose.ui:ui' + implementation 'androidx.compose.ui:ui-graphics' + implementation 'androidx.compose.ui:ui-tooling-preview' + implementation 'androidx.compose.material3:material3' + androidTestImplementation platform('androidx.compose:compose-bom:2023.08.00') + androidTestImplementation 'androidx.compose.ui:ui-test-junit4' + debugImplementation project(':core:testing') + + implementation "com.google.dagger:hilt-android:$hiltVersion" + debugImplementation 'androidx.compose.ui:ui-tooling' + debugImplementation 'androidx.compose.ui:ui-test-manifest' + kapt "com.google.dagger:hilt-compiler:$hiltVersion" + + implementation "com.squareup.moshi:moshi-kotlin:$moshiVersion" + implementation "com.squareup.moshi:moshi-adapters:$moshiVersion" + kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion" +} \ No newline at end of file diff --git a/feature/moreMenu/consumer-rules.pro b/feature/moreMenu/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/feature/moreMenu/proguard-rules.pro b/feature/moreMenu/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/feature/moreMenu/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/feature/moreMenu/src/androidTest/java/com/example/moremenu/ExampleInstrumentedTest.kt b/feature/moreMenu/src/androidTest/java/com/example/moremenu/ExampleInstrumentedTest.kt new file mode 100644 index 00000000..e7f3c80f --- /dev/null +++ b/feature/moreMenu/src/androidTest/java/com/example/moremenu/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.moremenu + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.example.moremenu.test", appContext.packageName) + } +} \ No newline at end of file diff --git a/feature/moreMenu/src/main/AndroidManifest.xml b/feature/moreMenu/src/main/AndroidManifest.xml new file mode 100644 index 00000000..df296b23 --- /dev/null +++ b/feature/moreMenu/src/main/AndroidManifest.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuActivity.kt b/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuActivity.kt new file mode 100644 index 00000000..c9111a48 --- /dev/null +++ b/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuActivity.kt @@ -0,0 +1,27 @@ +package com.example.moremenu + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.ui.Modifier +import com.mashup.core.ui.theme.MashUpTheme + +class MoreMenuActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + MashUpTheme { + Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + MoreMenuScreen( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + ) + } + } + } + } +} diff --git a/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuScreen.kt b/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuScreen.kt new file mode 100644 index 00000000..db974fd0 --- /dev/null +++ b/feature/moreMenu/src/main/java/com/example/moremenu/MoreMenuScreen.kt @@ -0,0 +1,11 @@ +package com.example.moremenu + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun MoreMenuScreen( + modifier: Modifier = Modifier, +) { + +} \ No newline at end of file diff --git a/feature/moreMenu/src/main/res/values/strings.xml b/feature/moreMenu/src/main/res/values/strings.xml new file mode 100644 index 00000000..469f44f2 --- /dev/null +++ b/feature/moreMenu/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + MoreMenuActivity + \ No newline at end of file diff --git a/feature/moreMenu/src/main/res/values/themes.xml b/feature/moreMenu/src/main/res/values/themes.xml new file mode 100644 index 00000000..d267c0f5 --- /dev/null +++ b/feature/moreMenu/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +