From f03cf172374d7304bddb0faad751c27ffe486e13 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:50:58 +0900 Subject: [PATCH 01/17] =?UTF-8?q?[fix/#121]=20=ED=86=A0=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EC=A2=8C=EC=9A=B0=20=EC=97=AC?= =?UTF-8?q?=EB=B0=B1=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - horizontal padding: 16 -> 20 --- .../app/core/designsystem/component/toast/MoiveSnackbarHost.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/moive/app/core/designsystem/component/toast/MoiveSnackbarHost.kt b/app/src/main/java/com/moive/app/core/designsystem/component/toast/MoiveSnackbarHost.kt index f43d2e5d..4e67c09c 100644 --- a/app/src/main/java/com/moive/app/core/designsystem/component/toast/MoiveSnackbarHost.kt +++ b/app/src/main/java/com/moive/app/core/designsystem/component/toast/MoiveSnackbarHost.kt @@ -1,6 +1,7 @@ package com.moive.app.core.designsystem.component.toast import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable @@ -22,7 +23,7 @@ fun MoiveSnackbarHost( text = visuals.message, type = visuals.type, modifier = Modifier - .padding(horizontal = 16.dp) + .padding(horizontal = 20.dp) .padding(bottom = 80.dp), ) } From e6c3a2eaea6e2ddeef5774f1c28f4f1d7fcc10d0 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Fri, 18 Sep 2026 16:11:55 +0900 Subject: [PATCH 02/17] =?UTF-8?q?[fix/#121]=20=EC=95=BD=EA=B4=80=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=EB=8F=99=EC=9D=98=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EC=8B=9C=20=EB=B0=B0=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 --- .../login/component/AgreementBottomSheet.kt | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/login/component/AgreementBottomSheet.kt b/app/src/main/java/com/moive/app/presentation/login/component/AgreementBottomSheet.kt index 717c89b6..a5818214 100644 --- a/app/src/main/java/com/moive/app/presentation/login/component/AgreementBottomSheet.kt +++ b/app/src/main/java/com/moive/app/presentation/login/component/AgreementBottomSheet.kt @@ -17,8 +17,10 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -36,6 +38,7 @@ import com.moive.app.core.designsystem.component.bottomsheet.MoiveBottomSheet import com.moive.app.core.designsystem.component.button.MoiveButton import com.moive.app.core.designsystem.component.button.MoiveButtonSize import com.moive.app.core.designsystem.component.button.MoiveButtonType +import com.moive.app.core.designsystem.component.toast.LocalSnackbarHostState import com.moive.app.core.designsystem.theme.MoiveTheme import com.moive.app.core.designsystem.theme.MoiveTheme.colors import com.moive.app.core.designsystem.theme.MoiveTheme.radius @@ -137,7 +140,7 @@ private fun AllAgreementButton( shape = RoundedCornerShape(radius.md), ) .background( - color = if (isPressed) colors.fill.default06 else colors.fill.default07, + color = if (isPressed || isChecked) colors.fill.default06 else colors.fill.default07, shape = RoundedCornerShape(radius.md), ) .noRippleClickable(onClick = { onAllAgreementClick(!isChecked) }) @@ -216,31 +219,34 @@ private fun AgreementBottomSheetPreview() { var isServiceAgreed by remember { mutableStateOf(false) } var isPrivacyAgreed by remember { mutableStateOf(false) } var isMarketingAgreed by remember { mutableStateOf(false) } + val snackbarHostState = remember { SnackbarHostState() } + + CompositionLocalProvider(LocalSnackbarHostState provides snackbarHostState) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + MoiveButton( + text = "약관동의 바텀시트 열기", + type = MoiveButtonType.PRIMARY, + size = MoiveButtonSize.LARGE, + onClick = { showBottomSheet = true }, + ) + } - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - MoiveButton( - text = "약관동의 바텀시트 열기", - type = MoiveButtonType.PRIMARY, - size = MoiveButtonSize.LARGE, - onClick = { showBottomSheet = true }, - ) - } - - if (showBottomSheet) { - AgreementBottomSheet( - isServiceAgreed = isServiceAgreed, - isPrivacyAgreed = isPrivacyAgreed, - isMarketingAgreed = isMarketingAgreed, - isConfirmEnabled = isServiceAgreed && isPrivacyAgreed, - onServiceClick = { isServiceAgreed = it }, - onPrivacyClick = { isPrivacyAgreed = it }, - onMarketingClick = { isMarketingAgreed = it }, - onConfirmClick = {}, - onDismissRequest = { showBottomSheet = false }, - ) + if (showBottomSheet) { + AgreementBottomSheet( + isServiceAgreed = isServiceAgreed, + isPrivacyAgreed = isPrivacyAgreed, + isMarketingAgreed = isMarketingAgreed, + isConfirmEnabled = isServiceAgreed && isPrivacyAgreed, + onServiceClick = { isServiceAgreed = it }, + onPrivacyClick = { isPrivacyAgreed = it }, + onMarketingClick = { isMarketingAgreed = it }, + onConfirmClick = {}, + onDismissRequest = { showBottomSheet = false }, + ) + } } } } From a2428f871c983ae8dd5cb05ea81ec37e42f7876e Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:42:47 +0900 Subject: [PATCH 03/17] =?UTF-8?q?[fix/#121]=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20crop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/meeting/detail/component/ParticipantItem.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt index 04e13f2c..6e870d45 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt @@ -13,6 +13,7 @@ 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.layout.ContentScale import androidx.compose.ui.unit.dp import com.moive.app.core.designsystem.component.button.MoiveButton import com.moive.app.core.designsystem.component.button.MoiveButtonSize @@ -52,6 +53,7 @@ fun ParticipantItem( modifier = Modifier .size(40.dp) .clip(RoundedCornerShape(radius.circular)), + contentScale = ContentScale.Crop, ) Column( From 589246ee1ee1c594b8ea0ef7e93d3f05cf30c934 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:45:02 +0900 Subject: [PATCH 04/17] =?UTF-8?q?[fix/#121]=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20=EC=B0=B8=EC=97=AC=EC=9E=90=20?= =?UTF-8?q?=EB=B3=B8=EC=9D=B8=20=EC=97=AC=EB=B6=80=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=EB=B0=B0=EA=B2=BD=EC=83=89=20=EB=B3=80=ED=99=94=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/meeting/detail/component/ParticipantItem.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt index 6e870d45..314d4da4 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt @@ -1,5 +1,6 @@ package com.moive.app.presentation.meeting.detail.component +import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -41,6 +42,10 @@ fun ParticipantItem( color = if (participant.isMe) colors.stroke.default03 else colors.stroke.default04, shape = RoundedCornerShape(radius.md), ) + .background( + color = if (participant.isMe) colors.fill.default03 else colors.fill.default04, + shape = RoundedCornerShape(radius.md), + ) .padding(12.dp), verticalArrangement = Arrangement.spacedBy(16.dp), ) { From 416970c219f4e5835669d2007440722ca9206a8f Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:46:23 +0900 Subject: [PATCH 05/17] =?UTF-8?q?[fix/#121]=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=83=9D=EC=84=B1=20=EB=B2=84=ED=8A=BC=20shadow=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moive/app/presentation/main/component/MainBottomBar.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/main/component/MainBottomBar.kt b/app/src/main/java/com/moive/app/presentation/main/component/MainBottomBar.kt index c9981e30..93b2755d 100644 --- a/app/src/main/java/com/moive/app/presentation/main/component/MainBottomBar.kt +++ b/app/src/main/java/com/moive/app/presentation/main/component/MainBottomBar.kt @@ -122,8 +122,8 @@ private fun MeetingFloatingButton( .customShadow( shape = RoundedCornerShape(radius.circular), color = colors.shadow20, - blur = 10.dp, - offsetY = 4.dp, + blur = 5.dp, + offsetY = 2.dp, ) .background( color = colors.fill.default00, From 6b225b74ae90d9ee15dcc57225e574bc20a9e0b2 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 00:48:09 +0900 Subject: [PATCH 06/17] =?UTF-8?q?[fix/#121]=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20-=20=EC=9D=BC=EC=A0=95=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=97=90=EB=9F=AC=20=ED=83=80=EC=9E=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/create/component/MeetingCreationContent.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/create/component/MeetingCreationContent.kt b/app/src/main/java/com/moive/app/presentation/meeting/create/component/MeetingCreationContent.kt index 558bb239..aaaddd57 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/create/component/MeetingCreationContent.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/create/component/MeetingCreationContent.kt @@ -137,6 +137,7 @@ fun MeetingCreationContent( onKeyboardAction = { focusManager.clearFocus() }, + isError = uiState.isMeetingScheduleFormatInvalid, ) if (uiState.isMeetingScheduleFormatInvalid) { From efe32afc1e06b9a4ab78ac228749197329d6c92d Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 18:42:43 +0900 Subject: [PATCH 07/17] =?UTF-8?q?[fix/#121]=20shadowbutton=20shape=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/common/component/ShadowButton.kt | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/common/component/ShadowButton.kt b/app/src/main/java/com/moive/app/presentation/common/component/ShadowButton.kt index edba5535..8d33b554 100644 --- a/app/src/main/java/com/moive/app/presentation/common/component/ShadowButton.kt +++ b/app/src/main/java/com/moive/app/presentation/common/component/ShadowButton.kt @@ -4,15 +4,14 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.unit.dp import com.moive.app.core.designsystem.component.button.MoiveButton import com.moive.app.core.designsystem.component.button.MoiveButtonSize import com.moive.app.core.designsystem.component.button.MoiveButtonType import com.moive.app.core.designsystem.theme.MoiveTheme.colors -import com.moive.app.core.designsystem.theme.MoiveTheme.radius import com.moive.app.core.extensions.customShadow @Composable @@ -30,10 +29,7 @@ fun ShadowButton( .then( if (showShadow) { Modifier.customShadow( - shape = RoundedCornerShape( - topStart = radius.md, - topEnd = radius.md, - ), + shape = RectangleShape, color = colors.shadowBlack8, blur = 12.dp, ) @@ -43,10 +39,6 @@ fun ShadowButton( ) .background( color = colors.background.default00, - shape = RoundedCornerShape( - topStart = radius.md, - topEnd = radius.md, - ), ) ) { MoiveButton( From 881290c69a222602230c4d82a46fafd8da49b8f5 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 18:56:49 +0900 Subject: [PATCH 08/17] =?UTF-8?q?[fix/#121]=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=B9=B4=EC=9A=B4=ED=84=B0=20ID=20-=20notificationId=20?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt b/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt index e4aa09e5..0a8f11ab 100644 --- a/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt +++ b/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt @@ -21,7 +21,6 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import timber.log.Timber -import java.util.concurrent.atomic.AtomicInteger import javax.inject.Inject @AndroidEntryPoint @@ -87,7 +86,7 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { ) == PackageManager.PERMISSION_GRANTED if (!granted) return - val androidNotificationId = notificationIdGenerator.incrementAndGet() + val androidNotificationId = (notificationId ?: System.currentTimeMillis()).toInt() val contentIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP @@ -121,6 +120,5 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { private const val CHANNEL_ID = "moive_default_channel" private const val CHANNEL_NAME = "일반 알림" private const val DEVICE_TOKEN_PUT_SUCCESS_MESSAGE = "디바이스 토큰 등록 성공" - private val notificationIdGenerator = AtomicInteger(0) } } From 5931f792c915cf127426a4515cd764663d71a95c Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 19:22:40 +0900 Subject: [PATCH 09/17] =?UTF-8?q?[fix/#121]=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20-=20=EB=82=A0=EC=A7=9C=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5/=EB=8B=A4=EC=9D=8C=20=EB=B2=84=ED=8A=BC=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EB=B0=94=EA=BF=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moive/app/presentation/condition/ConditionViewModel.kt | 4 ++-- .../app/presentation/condition/component/DateBottomSheet.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/condition/ConditionViewModel.kt b/app/src/main/java/com/moive/app/presentation/condition/ConditionViewModel.kt index 3aae3bf4..98a2ee76 100644 --- a/app/src/main/java/com/moive/app/presentation/condition/ConditionViewModel.kt +++ b/app/src/main/java/com/moive/app/presentation/condition/ConditionViewModel.kt @@ -133,7 +133,7 @@ class ConditionViewModel @Inject constructor( } } - fun onDateNextClick() { + fun onDateSaveClick() { val state = _uiState.value val pending = state.pendingDateTime val isNewDate = pending != null && state.confirmedDateTimes.none { @@ -156,7 +156,7 @@ class ConditionViewModel @Inject constructor( } } - fun onDateSaveClick() { + fun onDateNextClick() { _uiState.update { it.copy( isDateBottomSheetVisible = false, diff --git a/app/src/main/java/com/moive/app/presentation/condition/component/DateBottomSheet.kt b/app/src/main/java/com/moive/app/presentation/condition/component/DateBottomSheet.kt index 8ca85f46..0a7e6381 100644 --- a/app/src/main/java/com/moive/app/presentation/condition/component/DateBottomSheet.kt +++ b/app/src/main/java/com/moive/app/presentation/condition/component/DateBottomSheet.kt @@ -90,6 +90,7 @@ fun DateBottomSheet( text = "저장", type = MoiveButtonType.TERTIARY, size = MoiveButtonSize.LARGE, + enabled = state.pendingDateTime != null, onClick = onSaveDateClick, modifier = Modifier.weight(1f), ) @@ -97,7 +98,6 @@ fun DateBottomSheet( text = "다음", type = MoiveButtonType.PRIMARY, size = MoiveButtonSize.LARGE, - enabled = state.pendingDateTime != null, onClick = onNextDateClick, modifier = Modifier.weight(1f), ) From 89019dfd54027d6b1f5ed4137282afc485517c13 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 20:47:22 +0900 Subject: [PATCH 10/17] =?UTF-8?q?[fix/#121]=20=EC=B0=B8=EC=97=AC=EC=9E=90?= =?UTF-8?q?=20=EC=B9=B4=EB=93=9C=20=EB=B0=B0=EA=B2=BD=EC=83=89=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/meeting/detail/component/ParticipantItem.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt index 314d4da4..4be407d3 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/component/ParticipantItem.kt @@ -43,7 +43,7 @@ fun ParticipantItem( shape = RoundedCornerShape(radius.md), ) .background( - color = if (participant.isMe) colors.fill.default03 else colors.fill.default04, + color = if (participant.isMe) colors.fill.default08 else colors.fill.default07, shape = RoundedCornerShape(radius.md), ) .padding(12.dp), From 48e63475280a7957d4396a15c2d6bd8db6271cac Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 21:05:32 +0900 Subject: [PATCH 11/17] =?UTF-8?q?[fix/#121]=20=EB=AA=A8=EC=9E=84=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20-=20=ED=88=B4=ED=8C=81=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=20=EB=B0=8F=20=EC=9C=84=EC=B9=98=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../meeting/detail/MeetingDetailScreen.kt | 132 ++++++++++-------- 1 file changed, 75 insertions(+), 57 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt index 4b738069..424235aa 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt @@ -2,13 +2,13 @@ package com.moive.app.presentation.meeting.detail 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.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -19,15 +19,18 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf 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.vector.ImageVector -import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.zIndex import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.Lifecycle import androidx.lifecycle.compose.LocalLifecycleOwner @@ -97,6 +100,7 @@ fun MeetingDetailRoute( uiState.scheduledDate, uiState.scheduledTime, ) + else -> Unit } }, @@ -137,6 +141,11 @@ private fun MeetingDetailScreen( val isContentScrollable by remember { derivedStateOf { lazyListState.canScrollForward || lazyListState.canScrollBackward } } + val density = LocalDensity.current + var toolTipHeight by remember { mutableStateOf(0.dp) } + val isToolTipVisible = uiState.toolTipMessage.isNotEmpty() + val toolTipReservedHeight = + if (isToolTipVisible) toolTipHeight + 4.dp else 0.dp Column( modifier = modifier @@ -150,74 +159,83 @@ private fun MeetingDetailScreen( onTrailingIconClick = onMoreClick, ) - LazyColumn( - state = lazyListState, + Box( modifier = Modifier.weight(1f), - contentPadding = PaddingValues(horizontal = 20.dp, vertical = 20.dp), ) { - item { - MeetingInfoRow( - thumbnailRes = uiState.thumbnailType.toMeetingThumbnailRes(), - meetingName = uiState.meetingName, - meetingPurpose = uiState.meetingPurpose, - ) + LazyColumn( + state = lazyListState, + modifier = Modifier.fillMaxSize(), + contentPadding = PaddingValues( + start = 20.dp, + top = 20.dp, + end = 20.dp, + bottom = 20.dp + toolTipReservedHeight, + ), + ) { + item { + MeetingInfoRow( + thumbnailRes = uiState.thumbnailType.toMeetingThumbnailRes(), + meetingName = uiState.meetingName, + meetingPurpose = uiState.meetingPurpose, + ) - Spacer(modifier = Modifier.height(20.dp)) + Spacer(modifier = Modifier.height(20.dp)) - MoiveButton( - text = "친구 초대", - icon = ImageVector.vectorResource(R.drawable.ic_mail_fill_20), - type = MoiveButtonType.TERTIARY, - size = MoiveButtonSize.MEDIUM, - onClick = onInviteFriendClick, - ) + MoiveButton( + text = "친구 초대", + icon = ImageVector.vectorResource(R.drawable.ic_mail_fill_20), + type = MoiveButtonType.TERTIARY, + size = MoiveButtonSize.MEDIUM, + onClick = onInviteFriendClick, + ) - Spacer(modifier = Modifier.height(32.dp)) + Spacer(modifier = Modifier.height(32.dp)) - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - Icon( - imageVector = ImageVector.vectorResource(R.drawable.ic_user_16), - contentDescription = null, - tint = colors.icon.tertiary, - ) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_user_16), + contentDescription = null, + tint = colors.icon.tertiary, + ) - Text( - text = "참여자 ${uiState.participants.size}명", - color = colors.text.tertiary, - style = typography.label.xsR, - ) + Text( + text = "참여자 ${uiState.participants.size}명", + color = colors.text.tertiary, + style = typography.label.xsR, + ) + } + + Spacer(modifier = Modifier.height(12.dp)) } - Spacer(modifier = Modifier.height(12.dp)) + items( + items = uiState.participants, + key = { it.id } + ) { participant -> + ParticipantItem( + participant = participant, + status = uiState.status, + onActionButtonClick = onActionButtonClick, + ) + + Spacer(modifier = Modifier.height(12.dp)) + } } - items( - items = uiState.participants, - key = { it.id } - ) { participant -> - ParticipantItem( - participant = participant, - status = uiState.status, - onActionButtonClick = onActionButtonClick, + if (isToolTipVisible) { + MoiveToolTip( + text = uiState.toolTipMessage, + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 4.dp) + .onSizeChanged { toolTipHeight = with(density) { it.height.toDp() } }, ) - - Spacer(modifier = Modifier.height(12.dp)) } } - if (uiState.toolTipMessage.isNotEmpty()) { - MoiveToolTip( - text = uiState.toolTipMessage, - modifier = Modifier - .align(Alignment.CenterHorizontally) - .zIndex(1f) - .offset(y = 8.dp), - ) - } - ShadowButton( text = uiState.primaryActionLabel, isEnabled = uiState.primaryActionEnabled, @@ -241,7 +259,7 @@ private fun MeetingDetailScreen( } } -@Preview(showBackground = true,) +@Preview(showBackground = true) @Composable private fun MeetingDetailScreenPreview() { MoiveTheme { From 613702f20e4afb1b8812d1da40adae4bae587e30 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 21:09:52 +0900 Subject: [PATCH 12/17] =?UTF-8?q?[fix/#121]=20=ED=83=AD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20empty=20=EB=B7=B0=20=EB=AC=B8=EA=B5=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/moive/app/presentation/home/HomeContract.kt | 8 ++++++++ .../java/com/moive/app/presentation/home/HomeScreen.kt | 2 +- .../app/presentation/meeting/list/MeetingListContract.kt | 8 ++++++++ .../app/presentation/meeting/list/MeetingListScreen.kt | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/home/HomeContract.kt b/app/src/main/java/com/moive/app/presentation/home/HomeContract.kt index 54d7b4af..cf716e57 100644 --- a/app/src/main/java/com/moive/app/presentation/home/HomeContract.kt +++ b/app/src/main/java/com/moive/app/presentation/home/HomeContract.kt @@ -2,6 +2,7 @@ package com.moive.app.presentation.home import androidx.compose.runtime.Immutable import com.moive.app.data.home.mapper.MeetingTab +import com.moive.app.data.home.mapper.toMeetingTab import com.moive.app.data.home.model.MyMeetingCardItemModel import com.moive.app.data.home.model.ConfirmedMeetingItemModel import kotlinx.collections.immutable.ImmutableList @@ -27,6 +28,13 @@ interface HomeContract { val displayedMyMeetingList: ImmutableList get() = myMeetingList.take(MY_MEETING_LIST_MAX_SIZE).toImmutableList() + val emptyMyMeetingMessage: String + get() = when (selectedTab.toMeetingTab()) { + MeetingTab.ALL -> "아직 참여 중인 모임이 없어요." + MeetingTab.UPCOMING -> "예정된 모임이 없어요." + MeetingTab.PAST -> "지난 모임이 없어요." + } + companion object { private const val MY_MEETING_LIST_MAX_SIZE = 5 } diff --git a/app/src/main/java/com/moive/app/presentation/home/HomeScreen.kt b/app/src/main/java/com/moive/app/presentation/home/HomeScreen.kt index 8bde06d2..3139c36d 100644 --- a/app/src/main/java/com/moive/app/presentation/home/HomeScreen.kt +++ b/app/src/main/java/com/moive/app/presentation/home/HomeScreen.kt @@ -223,7 +223,7 @@ private fun HomeScreen( ) Text( - text = "아직 참여 중인 모임이 없어요.", + text = uiState.emptyMyMeetingMessage, color = colors.text.subtle, style = typography.body.smNormalR, ) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListContract.kt b/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListContract.kt index 232ffc29..600a1b06 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListContract.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListContract.kt @@ -2,6 +2,7 @@ package com.moive.app.presentation.meeting.list import androidx.compose.runtime.Immutable import com.moive.app.data.home.mapper.MeetingTab +import com.moive.app.data.home.mapper.toMeetingTab import com.moive.app.data.meeting.model.MeetingListCardItemModel import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -20,6 +21,13 @@ interface MeetingListContract { MeetingTab.UPCOMING.label, MeetingTab.PAST.label, ) + + val emptyMeetingMessage: String + get() = when (selectedTab.toMeetingTab()) { + MeetingTab.ALL -> "아직 참여 중인 모임이 없어요." + MeetingTab.UPCOMING -> "예정된 모임이 없어요." + MeetingTab.PAST -> "지난 모임이 없어요." + } } } diff --git a/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListScreen.kt b/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListScreen.kt index 1a02a51c..8a222b83 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListScreen.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/list/MeetingListScreen.kt @@ -118,7 +118,7 @@ private fun MeetingListScreen( Spacer(modifier = Modifier.height(16.dp)) Text( - text = "아직 참여 중인 모임이 없어요.", + text = uiState.emptyMeetingMessage, color = colors.text.subtle, style = typography.body.smNormalR, ) From 4f836f6b5da570047a30cde4d27198979916b15c Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 21:38:47 +0900 Subject: [PATCH 13/17] =?UTF-8?q?[fix/#121]=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=9C=EA=B8=89=20=EC=A4=91=20=EB=84=A4=ED=8A=B8?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=20=EC=98=A4=EB=A5=98=20=EC=8B=9C=20=ED=86=A0?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=9D=84=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../moive/app/presentation/splash/SplashContract.kt | 2 ++ .../moive/app/presentation/splash/SplashOverlay.kt | 5 +++++ .../moive/app/presentation/splash/SplashViewModel.kt | 12 +++++++++--- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/moive/app/presentation/splash/SplashContract.kt b/app/src/main/java/com/moive/app/presentation/splash/SplashContract.kt index cd58ad7b..c7e1394a 100644 --- a/app/src/main/java/com/moive/app/presentation/splash/SplashContract.kt +++ b/app/src/main/java/com/moive/app/presentation/splash/SplashContract.kt @@ -1,6 +1,7 @@ package com.moive.app.presentation.splash import androidx.compose.runtime.Immutable +import com.moive.app.core.designsystem.component.toast.ToastType interface SplashContract { @@ -11,6 +12,7 @@ interface SplashContract { sealed interface SideEffect { data class NavigateToHome(val isAutoLoginSuccess: Boolean) : SideEffect + data class OnShowToast(val msg: String, val type: ToastType) : SideEffect } } diff --git a/app/src/main/java/com/moive/app/presentation/splash/SplashOverlay.kt b/app/src/main/java/com/moive/app/presentation/splash/SplashOverlay.kt index c2defe74..65b3cdb8 100644 --- a/app/src/main/java/com/moive/app/presentation/splash/SplashOverlay.kt +++ b/app/src/main/java/com/moive/app/presentation/splash/SplashOverlay.kt @@ -22,9 +22,11 @@ import com.airbnb.lottie.compose.LottieCompositionSpec import com.airbnb.lottie.compose.animateLottieCompositionAsState import com.airbnb.lottie.compose.rememberLottieComposition import com.moive.app.R +import com.moive.app.core.designsystem.component.toast.LocalToastTrigger import com.moive.app.core.designsystem.theme.MoiveTheme import com.moive.app.core.designsystem.theme.MoiveTheme.colors import com.moive.app.presentation.splash.SplashContract.SideEffect.NavigateToHome +import com.moive.app.presentation.splash.SplashContract.SideEffect.OnShowToast @Composable fun SplashOverlay( @@ -34,6 +36,7 @@ fun SplashOverlay( viewModel: SplashViewModel = hiltViewModel(), ) { val lifeCycleOwner = LocalLifecycleOwner.current + val showToast = LocalToastTrigger.current val uiState by viewModel.uiState.collectAsStateWithLifecycle() var isAnimationEnded by remember { mutableStateOf(false) } @@ -56,6 +59,8 @@ fun SplashOverlay( if (sideEffect.isAutoLoginSuccess) navigateToHome() else navigateToLogin() viewModel.onReady() } + + is OnShowToast -> showToast(sideEffect.msg, sideEffect.type) } } } diff --git a/app/src/main/java/com/moive/app/presentation/splash/SplashViewModel.kt b/app/src/main/java/com/moive/app/presentation/splash/SplashViewModel.kt index b687fb7e..f4c9fa82 100644 --- a/app/src/main/java/com/moive/app/presentation/splash/SplashViewModel.kt +++ b/app/src/main/java/com/moive/app/presentation/splash/SplashViewModel.kt @@ -2,9 +2,11 @@ package com.moive.app.presentation.splash import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.moive.app.core.designsystem.component.toast.ToastType import com.moive.app.core.utils.suspendRunCatching import com.moive.app.data.auth.repository.AuthRepository import com.moive.app.presentation.splash.SplashContract.SideEffect.NavigateToHome +import com.moive.app.presentation.splash.SplashContract.SideEffect.OnShowToast import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel @@ -15,6 +17,7 @@ import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import timber.log.Timber +import java.io.IOException import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds @@ -44,16 +47,18 @@ class SplashViewModel @Inject constructor( } delayTime.await() - val isAutoLoginSuccess = reissueToken.await() + val reissueResult = reissueToken.await() .onSuccess { Timber.tag(AUTHORIZATION).d(AUTO_LOGIN_SUCCESS_MESSAGE) } .onFailure { error -> Timber.tag(AUTHORIZATION).e("$AUTO_LOGIN_FAILURE_MESSAGE $error") } - .isSuccess - _sideEffect.send(NavigateToHome(isAutoLoginSuccess = isAutoLoginSuccess)) + if (reissueResult.exceptionOrNull() is IOException) { + _sideEffect.send(OnShowToast(NETWORK_ERROR_MESSAGE, ToastType.ERROR)) + } + _sideEffect.send(NavigateToHome(isAutoLoginSuccess = reissueResult.isSuccess)) } } @@ -76,6 +81,7 @@ class SplashViewModel @Inject constructor( private const val REISSUE_FAILURE_MESSAGE = "토큰 재발급 실패" private const val AUTO_LOGIN_SUCCESS_MESSAGE = "자동 로그인 성공" private const val AUTO_LOGIN_FAILURE_MESSAGE = "자동 로그인 실패" + private const val NETWORK_ERROR_MESSAGE = "네트워크 연결을 확인해주세요." } } From 07ddeea5f660dececacd6477e85be7b57c016248 Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 23:20:13 +0900 Subject: [PATCH 14/17] =?UTF-8?q?[fix/#121]=20=ED=99=95=EC=A0=95=EB=90=9C?= =?UTF-8?q?=20=EB=AA=A8=EC=9E=84=201=EC=A4=84=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/home/component/ConfirmedMeetingCardItem.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/com/moive/app/presentation/home/component/ConfirmedMeetingCardItem.kt b/app/src/main/java/com/moive/app/presentation/home/component/ConfirmedMeetingCardItem.kt index 36ed6262..1a33fa7a 100644 --- a/app/src/main/java/com/moive/app/presentation/home/component/ConfirmedMeetingCardItem.kt +++ b/app/src/main/java/com/moive/app/presentation/home/component/ConfirmedMeetingCardItem.kt @@ -18,6 +18,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.moive.app.R @@ -101,6 +102,8 @@ fun ConfirmedMeetingCardItem( text = location, color = colors.text.onBg, style = typography.body.smNormalR, + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) } From 52eca34b87f0c0028ce5cb28d45fd767f60ed63c Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sat, 19 Sep 2026 23:22:23 +0900 Subject: [PATCH 15/17] =?UTF-8?q?[chore/#121]=20=EC=9E=A5=EC=86=8C=20?= =?UTF-8?q?=ED=95=80=20=EB=A7=88=ED=81=AC=20=EA=B5=90=EC=B2=B4=20-=20?= =?UTF-8?q?=EC=97=AC=EB=B0=B1=20O?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/img_pin_marker_1.png | Bin 2383 -> 2468 bytes .../main/res/drawable/img_pin_marker_2.png | Bin 2340 -> 2411 bytes .../main/res/drawable/img_pin_marker_3.png | Bin 2327 -> 2415 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/main/res/drawable/img_pin_marker_1.png b/app/src/main/res/drawable/img_pin_marker_1.png index 66fd1cdcba98e5a756345515d9ab364d252d3608..c0844657df477668d34c11d0ea31c5023becf02d 100644 GIT binary patch delta 2417 zcmV-%36A#95~LF$iBL{Q4GJ0x0000DNk~Le000150001Z2nGNE0CLRbKan9$e+eH+ zL_t(|0qvbjY!y`)$G>k%q$R-=T#1-mNg$$$KoBLt#chil)KCpupl)D+O4+pFhSo$L zWnm$*fDHxK@`%wDwqqg*LI{O~M<8HLpss`_Ci0Mbj^{hQmq2^x%F z&i&v2{LlMbfP#X8f`WpAf-FFAe~ivDZ=N{=mI8+*;%g~KXh!kx_)%V(aQYbMFoJ+% z;=Ex*7=a30ehe_&@8cLagcCw{ujXaWU@dT77Gf<04Tv{j7!ZAAaC)zgK3K+@&|jDN z(u&90#Vu?V|7`}dj0ov{U|z2feFQ9!xzOZZ5eYlVy7eRV$#i-GjINN*wonp4qPV%n^7l`HHCXr{ zfl_E$2wIvR5SGo8&R=vvUSkD>a#(yQg+>p`V2L8qIBc91zmA*6nMtlqa*q??fXbW>?7gc_8~6iK@X5N} zu&U)aJQBTaS1-50nV+}7gTG%>UPEr~{^mnS!{Pn`xO3}0*2>Ac0d|te*l)g9mGHD9San?tBtoKPd%OTZFy()}Xo~U%DPh-C?sQYu7qvDIi zI6JrjMn#`8IcnbP*F_8OxR&NLy-{E7_zbRzr|9CjfA+|~pTtiiH237(?s!5AtEbB6 zJGWLSkCPZ5uiFEr7;nU!s@v-qMB0G_1Xc<<<|(d9H94GanzA`h+)fi41jka)pQ^Asl_@LU!)hp?R z#)Lv^e}NuJ*9j}QbzofRs~R3j(_B3FDVWB%&=enGtwEd6z1eoOww0$Be|I-NbVeIj zXr>Ta-x6P!b6V%UVKSk)Hlee6JmYfbriius8e@&q3f=ms96bUWx#nP@sQXD1!+uE| z9sKSjK}*X^Gy0#hU~{VaIz~Vv)FdCZHT$y;e^l+%8XF*|^^OD`Qwe<;G;`*sE#L|! zqKq*JTzU~GbmLRdz8Kw=9z80YO;kDmsZFcD)H} z8ET)E;zE<$M3WnlD-%FH-2mZN(2VUSxv@Gu^OUAk3f)uzA2c?_YuId(n<|hWgW8lz zf1zbgqy9pX1_W#sibmYb!4KP&EVTEIaXpL9pN9%XnsSgeR1oW~I}@DaK-f8RdkrL)#BehaOK5rrIbc6bb2!7ExZAbGo^H^@e_+3A zY;4LSUi%Xe8pI^F(6V0LfRRetsfcI=_9WQ^JkbOiSujq+2%*^QOSoHD;+aZ~40@+k zgivJAYfeaFp(#QdI8qP#^r(e!Y)SLE0jcKR?ecM$GoJWe&J7GZ({2izdXi(G-_Spm z^O|y5h#b3?F%d1ZNvnCSeSp9=e>C9QH;CIn16qWZRX)n=sZ==9=evxTL0ZtdQFnE< zE$vmBdRc~L#zZbJ)45r<)`{ry#ym7Xecmt)uJ4FWP-6yJep`;BAERTJfsYI^vb184 zj{~B#?tz>^oke{<8W~M8`Z+9Jt$e2#Q|o~oP!-u&o51)7-sC}S(;^d@e|&^fS4(98 z5v^^4r3S^gpZPK+6QKz=#m+`#`IjI=x?9*K(DZqQX_2kIA#WLEgz*KP&(kP+z+7mm zlgLl#UNR(8M-w~Cy!jFGOR6mwj6&T6Tz`Wkj7%L(RQp9*tn`am5}C-{(KRyf7qKWZ zk-4L5&qAfnOFKP4H_ix6$Vrqs zrY|IzglHOPGWvPatuAmUm!HQeM?WL!JZ#GNnDdsi!bzc%MhMOHe{?M}YB(7kHDX1G zaP!_F?+tJiH>0BlMju{cfF0m4P757*ff5IQ-wI zA@_Hh?A(xjj9el&M?zQkcY1-aeT-ZpH$qqUck-Y8Ai_RIE|D9dC2}hZIXEyT`ZcT% jPZbmt6ciK`6u8I#(}25r7Zd9Y00000NkvXXu0mjf3TJ!x delta 2331 zcmV+$3FP*q6VDPMiBL{Q4GJ0x0000DNk~Le0000^0001N2nGNE0L0FOAdw+Xe+bG+ zL_t(|0qvblY*bYg$Ip3fq$R-=T#1;BBoNU=N)RQ%#k9o@YN&=SP&TkYrEFSoL+gT% zvaltxfDHp(%SVi^uze4tk-J0)9wK*v3Ak_{he2H~R4$xx!AcPVG7kHXf4evV3Q;Cp ze_AAThkqj;c7v7hjLHypKmmQ7xn3dKO|Vup0(-=J96#8_cY*?9IZk#d9DW9@7R-#7RZ-;o=J1`^GKhP)OzqTa4{O{FJf zvCgF15@-2}yRf^r2WDrNz`0Z3!XFRc1S8}-$gba0l^w^pkrs66e=Cn*`<^eLrS&gZ zx@;PD?Dq;N z7v#3}8!wi9eN*Q-ldkLab6vUPY9vLSklXxd6{4AP9ksH44aGd+@^0fjU;uL4%GK8@ zK5x`@Q0}_=I&B>vIOT^ZW}(_&1Ge&fquzbh($Q6=RQ3IFB6&)|-5`HidH zfxkbA8AmwoKzp<3*u~0kQ};JieV%Ua<84Pl7x_-{e?{L>l}f}N7)4+yNBkdau^+t& z%5C+;gE(PIa1_GvcxBe??91`rNP*7x?U_`+d9I3-XB*iNm6EDXwoyR9GubaUhCr=SXD!cn-^suoN_?@hJil4AQQ};v~d8{yvaLAJ5vY?PV7B&*9 zBSB0vkmG3olRA|2%oU?P3NTBxY8DhiCD^p7)kQu~H%V!jf?NhBg_{J$T>fD%*n*DK z!5B<9EiXXn<}kvR5ff^xbaava;V|h8${ogPe;Wu2R~xz}I$C(zSWLUJy~;uPEUyhE zn935%1Ch%J%});^{0xdQU4m)rQ!+=IObXYU0~ZvQULGb(FkKDQGsv4v3Mca%s&6D{ zfYVeXp~Y<+T<_G0;^+wD;WmK&DrNw6t2)M$$(u#^O!e~DSE`p!2|tCb4* zPWgbRX=nmwXbkshhrRZ8*3@+Q5Q3!H5!0AgNpYdH{Rrw zl5>FjI{6_nCO-gmKtZ(FeNtryDA$8{szf7{9@*X3k;@>Wu|pB6gJRx5T~1bh*14VH zsTECrN6-_MLjB}8>=je(M{qxZZ7dweNg zMWU|5qa0ab-C9x@6)tMX(n=yzA?jf?R6Rn4tZ>`0apw&%jM-52z~IB#jQ$j!1y~_m z;04~I_rz;(=`sYokwoJX}>r)vm2D)u-|f|Yk_adW$tm{}!UOHS@3 zE9=+M&b{XVm%t*d60Wd=vCMU}bI;VDb+3eFp(@V@D0fz2AG}RiCtTrtfO&ZP;BCS> z;R@#ixWzBb*#~bE)(Iz(TR-Js=ZvUJ6B`Z>!@u7}wy8aYU_$@^002ovPDHLkV1nQQ BT;%`& diff --git a/app/src/main/res/drawable/img_pin_marker_2.png b/app/src/main/res/drawable/img_pin_marker_2.png index dae6d2cdb623ed0035ab41e7c2c730f11bf9b145..3d4fc79c59c30acf9bf01de158931d3d55306964 100644 GIT binary patch delta 2359 zcmV-73CQ-O66+EniBL{Q4GJ0x0000DNk~Le000150001Z2nGNE0CLRbKan9%f96R< zK~#7F?VUYr97Pnz-`fj`6AV~Eh#&$GdxX z``ot)H=J8osp=%&@ME7DOccLS*QwiN{MoUlbc^Jck zX&N_)t%I@)A@X_HBB02mWJZ;cx6fQQR=nrt@=c$bV2}mUL_+VoOwvfnes0(+8 zC;DrWTnjOgokL7UbLQ;cTZdQQ{vGQ7crf?*Q?Pn{J6NIFpz-5ee-b~U8Ml&Q^gp={ zLvQ^7+jp^tez$_?UWjWUv4kEUYD|D7%cvY#lLEJ)-wzDk0!x%dSvnEtg2+NQYg|m^ zPiY}h_Z_~o>F)=I|F#*`qj91-dPFCz1av^r+zk@hR#a0K5~pH}By=;H`3P8mqIu8$ z`+>);Mm0o_>Sz&de=(Z(?7#PrH+Nz)s^$Af^y-M#VQ-wTa^$bjb115<5z(tdg+4VT zEu#z;*mwB0GMd{^RMWXOkX~Ja&|$Dpp*e=Xh$*5(bDMoH-2rQ`@IeBl(6SP=G(8~9 zo4cJ)KUP4fhS`TwX!M{8mIzAe)Yn8W0lL{2^Huu6YS6$RROw z6YYkCOus}{e?UJZ0NvC|ZP%u2NMz~;P0Pz8H{qL4p6>ckNnk25oz`?<_?G-kVGl^f zI+Ih5;|VP%f~SD`j=Ry0I1=I7<;P^7GChdh&(`IG(NT=)fxY(rZ?Y6EUG0zj`cX=P z3hqgvFLXN=D6}XFsrPPcX&CQWTZde_zuLBp|SI&@oSORjSG16shFR zdE&;;$)j1qu^egvi(oJ=G}%X3YtSb2*|Mm# zRYGf9e|fre#a;WLY(p1Zp_xKxeM@|)b>=EMZ3B}D&9w>LES@{SHK-EQYHOTU=ypdH z(aWHbl?C@IMctL481_pN(ZNqA2}|GiJC{@IuLOgGQ`Oh83>qPkSFb+;u0SPBcQ%BW z#5xcbK{K_BrZ+K&&dOr?CU+-{LEzGhK%x8Ae?j|VbXR)xD3VQNLjUsM;0(O$Nx6fI z-U^XKcA-gbqRCAgv8Z;v2@9{UKr=2h$xS?LM6PrI^>hP-??5xQo8-ot+{{x3rBdjf z4e&u@Q@oAMCVB1R6JP={)T<0irO?u+QGca)ZSHYvm7>Ah-~^xFpY*iA=RCmt$vE6tk)%}`X+ zTEQ$Vr2Sqd9xMWnl$k}kOVQ%dZXX0SV7~s~8Kd2(lrz(N7+d_wyvZo1MP4~OKFsDt zIjMpnl*oFpNr|0k_Xh4h5GUX$`?xo6+zTc%;2Wdg;M%}GVx@oUc zcV@~YV@>$-L7kg*YwbgnAI#Gie+9NExxOPhL5&$?`E5ChevFYb2EH=HNU!+EKF*5T zdIE9=brwzgXk;|W==ZRU4e`@rOl<;kKucs}Z35$8c#{XQO^Zwz7n&FwY|J8}wN0?p zpcwZvU#DauG~uS$*@!IP2{L4SkS&0w?<-7;Z1v512O%ReodDM-dca(0f2xznb^0tB zl4(Q}r>lJ69`Xg%mJ3FqZUU~qK@vvhQ#xDyB7;`?MJ$O-WFFCNGVd3$C^BJfJlmHQxN?kTKapHh!GMK{TFetz81}NzesDcOX?Alv{>`#PRulD zqR;j;jWdh0cXDr3YbGLIf9pQ;%-d2#oDup#+NY;-TuVDWKsQcpHy|fb>X^QeU=pHf zobl+5q+4C!jxTS-tqnBVB%Oy%9v^ewa#lDgbW#hUnVzm$MjI!sqfIOe5z#y~@4Wzy z;-+=9!RW(F3~&S-#%ZA=FHqv(pPfhTJ2B|Q?T98KL^aF7)CQ+Lf4YsztFs=GN{agt zEy3XR);u3mhI1iwUqh}%-;`I=&I0v-FE4P7TnOFTVPR8L)6N1e^=GKaiFL^Roi;~q z$Ua6cksF~~`#U{E*gi%sksF~~`#bp${t#gwBbUgH&=R?og&Z7M6a5<2ho=e(3JMAe d3JTogKQQ0B@i;z_4dMU*002ovPDHLkV1h0ZVnYA` delta 2287 zcmV_Q(C{ct7ky3z^vq7m6;iL~SP0C;zo1_SK3KE+F z)288)^n55?gzzGff`VWx0@2`{C~$*>X^8o_d6_r2d-(2l@AhM6XU>kuq4S*GDFgD?UF`{mCFe<2K`{9S*QN-c-45kVCJ*W__ah){(ZEI$WWTJUiV zEPzlT(?_XH0*(PuSzi1IXg~_O1c*KgxH{*f4+UXdxbMm|QuD;P{HT-izr$dbs+7_P z;mt}Bt6&gg!m)Kp7d*q(1vVgQeFU?ntWdjf)&*-t3MdFpo%3-CG@?zof9bLe=pLPy z568htsG`$_JD9^-mDAFi#Jwf)PUW&IkK~`GOx3*Q`%a6W*f1x+l)Z^p9V=KsV zGR|cqg_|C$&448rJ-TmJ2^PYS55IE(EKzzB;AGSbZLS*Bp#OjcSfuGs_O?CGE<5+f z3ar00-GST=$?=XC0{66zZM0ilm!N18wzep?N>{aIb==BEH55(4)$Gd2MQhu;!*7aht=P0WrZv{JxT?Kzf}{I>=z7c{i^9pc-(+#kv7#bh|f%lOyC>`r@;Y#M(k^38xURJ3WrxXGT+^K6+V=W3Jdq=gOl+4-{&C@gMcNRIzr<}*?V~3+j&Lx zX0)>M_+z*!e^2t>YWwILi^knXX&Qwn_~x*9Q8$SNV~dUo1xW<&h`{kdHL))TJGU=K zKF=r2KYUSqmmfXdukQFRdHi8b^U5O}c`!046T4jTjV-Ga zd~u&jS2jgGDXyrWq~z@wMGz%V{+p|>hEKvqcTXN3e{{LoT_KdhQNA*Z`^s{kNP*mb zIFbKGBS_(Za+?dsuwLQbYW|c}=Dow5$K@7|18pz3D>qbkH3)}+a9X(i&{`isVsfP* zEoc)?$DK5d&YP=EIKG=tp1lpO!fv{vu@Ph8v~}cji{&aht&K;%q;RNFICtZm&U3@M zaHLJRf4V!A!8Ph(qy*X^sItXXK_mAZY$SAhf*fXGi{tfA`rwmvEvH-2UfE!kYt<@f zgiEkTwq_Sa!2N?--4xU`FeThFXofp7UBN`?5CWFGp;w@FaTw!Dj|p3viI)B)!Lm22 zX5r{#c9h_w;;;mpiN?}(sui@=h= zjl@k0y~Awjx^p*%2rJ>^hH%@2Y9O?`D_fn3i-?0i%S0Z@JtFfP)_FCA3(}GbXojus zf45tg3US%>;ImBJCK*Ep$%09QgR}eUvbd##YlWykye}RR~ z9Pc=;NzoE7PfRsiDTsI4J3MW}12FT~G1Uz3RKlqgh2!03YAkqv;d%^DMe1$Pm|!&y z@3quh)6LsilX2}pmd*DvO)OL&-$0&NYvXFJ?#MvBM+~%6f`jd|p z*&5A2kHN+Jyq|AyDpQPWWonGhf5<-h8R!85(Q@acT7+YIK|EceG1`PMK%0vm8yNZAwIZWysRCa7yit<<%KMPrOvTu9+{Z2_V&f5t2>gfD<= zLMW&QnR}~Ei^doij^Ub6*0tt#GzgJBxOwW&G!!BnW4f*l29FEdV9t1qYsE~0+&-Jg zG=*7Q$X4-4reyqbBv}7;fw^DaJH~$GDB; zoBdgQT-%5hi))Z|9v;WYf0%h|MPXIAtS-wliEO!Oh*eh&N#(NA+U6F$JzyETt{Q^L zyR!v<6`lh)Azb1K+XVi(MZ5tH;D*I939L>yG!*GXj0@=$>r8clXT=?hQ(*i`ZE|ah znNz|I)zn(Dw!BV#iwD3}a0sV_3sx|;Sskz3v-P#^aX99xYJY%sMav4-!MlWW!Ug*S zG!d?YcM0c&3-$-_8&7Ol2k#Qj38zp?KUHVvnygDLe&0$w{{fyS!G!hKagzW5002ov JPDHLkV1nMTT3-MF diff --git a/app/src/main/res/drawable/img_pin_marker_3.png b/app/src/main/res/drawable/img_pin_marker_3.png index b7a7498ef0a49130c2a93124d0893a070dd637fd..bb0084f2146fa6b8d2fc7cd7243244e2ac92bae8 100644 GIT binary patch delta 2363 zcmV-B3B>l767LcriBL{Q4GJ0x0000DNk~Le000150001Z2nGNE0CLRbKan9%f9gp@ zK~#7F?VZ1G6h{=t-|UfK)8IrjP{2VNlqkYLkpfG(Gbl}na3ZA)aZ*qQ)7T`Df}MiI zril3qxFkJ4+6duAN(u^sDL^zhCkkkgFby$3ZYJ~Q_8fD*ot@p8*_l1>M>=tMckgz; z_x8=3H*aPEN=iyfN=iyf@_>M6e@xWa(B@4r3=H=1*Dxb6MEJk$t*qL$`!ZwDBtVw= zev5=a6IyWlIl$t4NS47PybyZo2&*v)$AGaK7i$;{z<+>6AS5IduFQrc1jjfN`nwt% zZUuCVpTbH0-yyI|lS>~04Q9CLO>jW&LZkI^mv9EH7hJ%&bu*aB+sbnjf7-dg-EhGv zgHz{1vIsd~UFfMAZ@>cf3x7KXUcwrAxRd}aGCA6s;3D4wZ$(DPI6udQZx6FC!6H^H zT7+l;y8vDb+zWfwZCvQcRV?tgRVXG+prmeEY@@DYvc|?DS5bxHQf2%a#I+d2m_?ti zy&7jhZ~^*=fRgc_Lh>sZf53=EW24t^A|o_l4bh+*K-;4G(UQ9{VcA+jx4Y58C-*&+ zlKncJo6N2QqYEzbCDh!J)P`v{PMOhQl9Tl27iMDBno z+|2>c*JL>sQX-N=R9JKF?AW>pCq_o$-yxYjDNrZDC*Qld)ECOUC8VoOR)0N_5jU#7$2{ELCJ2_u}O7{&e#Z;0Ij(fgWPqv zvTBS%(lm@pLbu~be>M&dKx^K!?RxC?LtJQQz8ctss;^eFXouFkXIuE1Z|=sWRU@jt zTG4g58|OQ+_s7J24mlK>w_8e9ohbC_QQ@y#)+S4go5h;{KQ_Hpn~1|15UHPz z6*@|CS3!eM-aiG?AHOYLpC9;I$>-ueIt`nuRpUNK*PI`os}2}_d_T%|#chujnpO15 zXW!d?c{RQre-PnUL*y$?jMU*>zO5H1GNwUwk^QJBFrEW`&&ZlyC7!FU+j&LfHQN+> z6c&POuzl<8o_|N*i?1ios_@tSlko8AK5?--`2Hh?y3;7~H}wN>_t6;Kd~jU(^YOfv z9@ii%ED%Cp>9s9ZXnrebS@hE552f2tjH8;jtBk?ue=fq8D!Ky+1ZXvGTOc_~EBA;e z?IL}t!~F!~NQ9AU+@^S;nO;MPxnk`T&ykxC#`O(@#A_xA@0hkZq7N<#cOU6@8JJ{> zh%AoQ78)CtBDfE1nC}=6nq(B(2sa-%%SkDt6KSYoU1$@QVw*gS!Mf0BEl-~90$)M5 zv6Mrje=QT**gzb%=)Pjonwdm1iO|HL(Ej>qljlaV3C)ZN-M&3*;2UkXRs~})oT1wr znMF6jAa^}%6iwf0eAq9GMaTa-S-^|(Ev7c#2*w+yEZ5NlgJ75Zp{wf89^B!XJ)>>| zL|Jb$ZktT#+hCZh_kI9hu;I!mh1jVVu|f~Le*)u^(S6D2p(WdhgkG|E#Zh=6b*7FlI!QqS-*7{-S#xs4y25GM5i@^S+L>BsyNaNQ-h*5#&w)F`Dw z54Io#gI)0sF1zGc@7XDgeGYP?lnO2UG%?>O;(&mwM$w8jGYFF^{}Z!!l$n`yz7}j0 zfB$qa`hs_o>DU=zj5Lz=Nfdeu6%C?s_kmVz;XXX0KJgQrUA8s6xn$&7yP^q#Y3yrxrxj zni1tO!`Z7O#*78zyP=c*M2N+xs{h1D){ zoC_=S{p_#NFLRN#mrpQKO&a-Y;{yb)!2#E~YsAQmCL=stu+Lrz$qf6%#>0iFT# zp{tG}zrb_Jkz6erIa6apD}>#WExBM7OcOBk9g-w+wP+;Di`1RuMI4EYglHRYeDqrMW*7M5m)GKzMX!>z4jX-Z%DUye@KWfkE(9w*eRCNdymTEMQn?Ur z&9e)^ZtxU8T}KC^KDGA9JiNd+3L$i~!ooVM#+3zp%4f(Zi0csR zJFU0egmsL3qA)^7>pQ(h(mF;yQ5d14^_{}iKPaqYy>~002ovPDHLkV1lULU)BHs delta 2274 zcmV<82p#wD5|Uqb7qBzRnUkw;mBPg1kaGWzyw^lkHf4k7b+LdxM1xF0U3u==Ul9Se?pWAH(eG9 z-Qk~$o5#RP_@c@Xc0d7BWA#ZP+6}N)Gy*5Ydt82hoWBDK$mBTLrEvHKuv)Mnvb!&} za9(IGi4N8*{L`z3%QZOI7ePHY^7@{b=elqBe4&fRt3U-ZeU64ro4&U$i`GN7j zO}cI}$aS5Li%5z(A-4rVqM33XwX#7CMT>9^xA6%u0J&}N{zswr8+9FYx~|o62Hm!I z|HGEt){aTn$=7eoe|2r4YHpsObmXtd$B^rc(U$9)!kr$IAzB0j>^pp~tJ{3Yb@W&h z$Xr)|=CFHHI59)6WGp@naopy!@3s424EA`?Qwk>=1w+$$QMoPX@$_W`gt8y5QaE&= z42B5nf^>gQe21!LM*)t~|57*(jc@WMstXc^N!KA~W%}RCe{nqX0+=*?tTb+W{M_WO zQ_&CPfHKbwc%9xNWZ=;8b=k+-c;LWVWe6%)M&RC^fv(R9E3e|>yYBYSgOQJWsq{d; z772IryWQ~PS9>5W)Vh8+#$O)b1t=kh)Xk=62pjqU-umb_>GIX44PD%!<9~uKwz@nn>%V3j z7)4-3NBo;ro_TpGH3Gc? z<-@FqwseG~&nz4{t{1|U8mhIGU62*@gj2%m^(Vo0ZvUh%r6?0FsJ~_#DnDFh!cn+J zRSPDe_olKDBjJ?oOj*5VZ@5xxstVCK)P!*Aw)9Z%-BwhFDK>=T%7kl#!%nabY7~^F z5e`*ye_Rz5vUbD1MnZLqFQysDakT$Q9jiYKTi2&kU)f-lYSk(zghX4v^#s@gMS$wo zp0<6Ga4Vpg%4OY~1mm-|lD))ghcT!)gPWjqa~NUEhzU7OM@#=NhZSd5?l4x{K#*uQ zlwc}LEFaofOuMpuTYL?Qv7rRh@!=tI8KI5oe?f%rK{2LFFx4ei6Xr;hN#Ta-;DW-^ z%g1C1R=NB%=s-;UNRvt7WS&Fyjl|8Rr;IfcTHMCL^-rB>UKQiXHi5-~L^CluOa;A; zG{HG8`nQ|HiOC|0UFG3QuFEsm(Q8$%s1H*b5t-kz&#Nh%*DYBD#gOZ0uR%W$c ze-8?QxAZ((u155Tm4_=q9pZ03eqQUa6ZP5XHMDIeVb1Khp9dZ}#yrD1slSO=SZmDo$>rXm8jX0}wkzudR!%EuRMs$2kb63$7K6K%K zJcQc<4m=3esammkmW9hAgG2`H0gXB0E2W3}*W(WGO`Hnj?r5jzYG; z@ongrR+i&voO3s0b+^yDSmBIEehNJg!^yaZRK>1S=H0@=cFuQ{*Mw;2<32u7e}U)a zJLLnOrlAR#`6WD+Kr5M-O57Lp%Z5_9C4dz^zTy_7e#9{13d;6@AGc9$tfl0 z08fqaGh$4B26_Nbw9I`{Wd|tte}Z_bL?e_Q**!H{UqnP>haz+b#k_&KoUHt;b34UT zE1LX`pn>U8b^{dsy@ssFs$khU2#V1%r#2`?7;GrbNVE-lFB;I|IO0s1k32+9&MSfm zs4V2^JGfD3o5l6&+EF8Qt!B{(ZI1KFy{^qcG(!7I7`gze2_dHuWE!p3e=Qo3%c?)B z2}NC-XuK;GVgxr!{h5T^mP_icYrVECIPmwu+k|z(dFKPT w%^z&p2X7PB2`7 Date: Sun, 20 Sep 2026 00:00:18 +0900 Subject: [PATCH 16/17] =?UTF-8?q?[fix/#121]=20fcm=20payload=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - notification: title/body - data: meetingId/notificationId --- app/src/main/AndroidManifest.xml | 3 +++ .../java/com/moive/app/MoiveApplication.kt | 2 ++ .../core/fcm/MoiveFirebaseMessagingService.kt | 22 +++------------ .../app/core/fcm/NotificationChannels.kt | 27 +++++++++++++++++++ .../app/presentation/main/MainActivity.kt | 19 ++++++------- app/src/main/res/values/strings.xml | 1 + 6 files changed, 47 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/com/moive/app/core/fcm/NotificationChannels.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4ba127f1..d9fb9b64 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -67,6 +67,9 @@ + diff --git a/app/src/main/java/com/moive/app/MoiveApplication.kt b/app/src/main/java/com/moive/app/MoiveApplication.kt index 4eedb429..4b6fae45 100644 --- a/app/src/main/java/com/moive/app/MoiveApplication.kt +++ b/app/src/main/java/com/moive/app/MoiveApplication.kt @@ -3,6 +3,7 @@ package com.moive.app import android.app.Application import com.kakao.sdk.common.KakaoSdk import com.kakao.vectormap.KakaoMapSdk +import com.moive.app.core.fcm.NotificationChannels import dagger.hilt.android.HiltAndroidApp import timber.log.Timber @@ -12,6 +13,7 @@ class MoiveApplication : Application() { super.onCreate() initTimber() + NotificationChannels.createDefaultChannel(this) initKakaoSdk() initKakaoMapSdk() } diff --git a/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt b/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt index 0a8f11ab..a3825552 100644 --- a/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt +++ b/app/src/main/java/com/moive/app/core/fcm/MoiveFirebaseMessagingService.kt @@ -1,12 +1,9 @@ package com.moive.app.core.fcm import android.Manifest -import android.app.NotificationChannel -import android.app.NotificationManager import android.app.PendingIntent import android.content.Intent import android.content.pm.PackageManager -import android.os.Build import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat @@ -60,8 +57,8 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) - val title = remoteMessage.data[MESSAGE_TITLE] ?: return - val body = remoteMessage.data[MESSAGE_BODY] + val title = remoteMessage.notification?.title ?: remoteMessage.data[MESSAGE_TITLE] ?: return + val body = remoteMessage.notification?.body ?: remoteMessage.data[MESSAGE_BODY] val meetingId = remoteMessage.data[MESSAGE_MEETING_ID]?.toLongOrNull() val notificationId = remoteMessage.data[MESSAGE_NOTIFICATION_ID]?.toLongOrNull() @@ -69,16 +66,7 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { } private fun showNotification(title: String, body: String?, meetingId: Long?, notificationId: Long?) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel( - CHANNEL_ID, - CHANNEL_NAME, - NotificationManager.IMPORTANCE_HIGH, - ).apply { - enableVibration(true) - } - getSystemService(NotificationManager::class.java).createNotificationChannel(channel) - } + NotificationChannels.createDefaultChannel(this) val granted = ContextCompat.checkSelfPermission( this, @@ -100,7 +88,7 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) - val notification = NotificationCompat.Builder(this, CHANNEL_ID) + val notification = NotificationCompat.Builder(this, NotificationChannels.defaultChannelId(this)) .setSmallIcon(R.drawable.img_logo_white_bg) .setContentTitle(title) .setContentText(body) @@ -117,8 +105,6 @@ class MoiveFirebaseMessagingService: FirebaseMessagingService() { const val MESSAGE_NOTIFICATION_ID = "notificationId" private const val MESSAGE_TITLE = "title" private const val MESSAGE_BODY = "body" - private const val CHANNEL_ID = "moive_default_channel" - private const val CHANNEL_NAME = "일반 알림" private const val DEVICE_TOKEN_PUT_SUCCESS_MESSAGE = "디바이스 토큰 등록 성공" } } diff --git a/app/src/main/java/com/moive/app/core/fcm/NotificationChannels.kt b/app/src/main/java/com/moive/app/core/fcm/NotificationChannels.kt new file mode 100644 index 00000000..a4176e69 --- /dev/null +++ b/app/src/main/java/com/moive/app/core/fcm/NotificationChannels.kt @@ -0,0 +1,27 @@ +package com.moive.app.core.fcm + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import com.moive.app.R + +object NotificationChannels { + private const val DEFAULT_CHANNEL_NAME = "일반 알림" + + fun defaultChannelId(context: Context): String = + context.getString(R.string.default_notification_channel_id) + + fun createDefaultChannel(context: Context) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return + + val channel = NotificationChannel( + defaultChannelId(context), + DEFAULT_CHANNEL_NAME, + NotificationManager.IMPORTANCE_HIGH, + ).apply { + enableVibration(true) + } + context.getSystemService(NotificationManager::class.java).createNotificationChannel(channel) + } +} diff --git a/app/src/main/java/com/moive/app/presentation/main/MainActivity.kt b/app/src/main/java/com/moive/app/presentation/main/MainActivity.kt index 484075bf..39907aa9 100644 --- a/app/src/main/java/com/moive/app/presentation/main/MainActivity.kt +++ b/app/src/main/java/com/moive/app/presentation/main/MainActivity.kt @@ -155,14 +155,15 @@ class MainActivity : ComponentActivity() { private fun Intent.extractInviteCode(): String? = takeIf { it.action == Intent.ACTION_VIEW }?.data?.lastPathSegment -private fun Intent.extractMeetingId(): Long? { - val meetingId = getLongExtra(MoiveFirebaseMessagingService.MESSAGE_MEETING_ID, -1L) - if (meetingId != -1L) removeExtra(MoiveFirebaseMessagingService.MESSAGE_MEETING_ID) - return meetingId.takeIf { it != -1L } -} +private fun Intent.extractMeetingId(): Long? = + extractLongExtra(MoiveFirebaseMessagingService.MESSAGE_MEETING_ID) + +private fun Intent.extractNotificationId(): Long? = + extractLongExtra(MoiveFirebaseMessagingService.MESSAGE_NOTIFICATION_ID) -private fun Intent.extractNotificationId(): Long? { - val notificationId = getLongExtra(MoiveFirebaseMessagingService.MESSAGE_NOTIFICATION_ID, -1L) - if (notificationId != -1L) removeExtra(MoiveFirebaseMessagingService.MESSAGE_NOTIFICATION_ID) - return notificationId.takeIf { it != -1L } +private fun Intent.extractLongExtra(key: String): Long? { + val value = getLongExtra(key, -1L).takeIf { it != -1L } + ?: getStringExtra(key)?.toLongOrNull() + removeExtra(key) + return value } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 69304061..0d696b71 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ MOIVE + moive_default_channel From 4bdf09e95a1159605d7c6de677ad27d0f517144e Mon Sep 17 00:00:00 2001 From: vahkjsdf <130419090+vahkjsdf@users.noreply.github.com> Date: Sun, 20 Sep 2026 01:59:47 +0900 Subject: [PATCH 17/17] =?UTF-8?q?[fix/#121]=20=EB=B3=B8=EC=9D=B8=20?= =?UTF-8?q?=ED=88=AC=ED=91=9C=20=EC=99=84=EB=A3=8C=20=EC=8B=9C=20=EB=AA=A8?= =?UTF-8?q?=EC=9E=84=20=EC=83=81=EC=84=B8=20=ED=95=98=EB=8B=A8=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20disabled=20=EC=B2=98=EB=A6=AC=20-=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=ED=88=AC=ED=91=9C=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/moive/app/data/meeting/mapper/MeetingDetailMapper.kt | 3 +++ .../com/moive/app/data/meeting/model/MeetingDetailModel.kt | 1 + .../app/presentation/meeting/detail/MeetingDetailScreen.kt | 2 ++ .../presentation/meeting/detail/MeetingDetailViewModel.kt | 5 ++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/moive/app/data/meeting/mapper/MeetingDetailMapper.kt b/app/src/main/java/com/moive/app/data/meeting/mapper/MeetingDetailMapper.kt index 3bc1e7fa..79c1dec6 100644 --- a/app/src/main/java/com/moive/app/data/meeting/mapper/MeetingDetailMapper.kt +++ b/app/src/main/java/com/moive/app/data/meeting/mapper/MeetingDetailMapper.kt @@ -32,4 +32,7 @@ fun ParticipantResponse.toModel(): ParticipantItemModel = statusLabel = participantStateLabel, isMe = isMe, isDone = participantState.endsWith("_DONE"), + isVoteDone = participantState == VOTE_DONE_STATE, ) + +private const val VOTE_DONE_STATE = "VOTE_DONE" diff --git a/app/src/main/java/com/moive/app/data/meeting/model/MeetingDetailModel.kt b/app/src/main/java/com/moive/app/data/meeting/model/MeetingDetailModel.kt index 696692f0..07e1159f 100644 --- a/app/src/main/java/com/moive/app/data/meeting/model/MeetingDetailModel.kt +++ b/app/src/main/java/com/moive/app/data/meeting/model/MeetingDetailModel.kt @@ -31,4 +31,5 @@ data class ParticipantItemModel( val statusLabel: String, val isMe: Boolean, val isDone: Boolean, + val isVoteDone: Boolean, ) diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt index 424235aa..26d8ed39 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailScreen.kt @@ -278,6 +278,7 @@ private fun MeetingDetailScreenPreview() { statusLabel = "조건 입력 전", isMe = true, isDone = false, + isVoteDone = false, ), ParticipantItemModel( id = 2L, @@ -286,6 +287,7 @@ private fun MeetingDetailScreenPreview() { statusLabel = "조건 입력 완료", isMe = false, isDone = true, + isVoteDone = false, ), ), ), diff --git a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailViewModel.kt b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailViewModel.kt index c357f73f..fa66440c 100644 --- a/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailViewModel.kt +++ b/app/src/main/java/com/moive/app/presentation/meeting/detail/MeetingDetailViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute +import com.moive.app.data.meeting.mapper.MeetingStatus import com.moive.app.data.meeting.repository.MeetingRepository import com.moive.app.data.meeting.repository.NotMeetingParticipantException import com.moive.app.presentation.meeting.detail.MeetingDetailContract.SideEffect @@ -43,6 +44,7 @@ class MeetingDetailViewModel @Inject constructor( meetingRepository.getMeetingDetail(meetingId) .onSuccess { detail -> + val isMyVoteDone = detail.participants.any { it.isMe && it.isVoteDone } _uiState.update { it.copy( meetingDetailUiState = MeetingDetailUiState.Success, @@ -58,7 +60,8 @@ class MeetingDetailViewModel @Inject constructor( participants = detail.participants, toolTipMessage = detail.homeMessage ?: "", primaryActionLabel = detail.primaryActionLabel ?: "", - primaryActionEnabled = detail.primaryActionEnabled, + primaryActionEnabled = detail.primaryActionEnabled && + !(detail.status == MeetingStatus.VOTING && isMyVoteDone), ) } }