Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
f03cf17
[fix/#121] 토스트 메세지 좌우 여백 수정
vahkjsdf Sep 18, 2026
e6c3a2e
[fix/#121] 약관 전체동의 선택 시 배경색 변경
vahkjsdf Sep 18, 2026
a2428f8
[fix/#121] 모임 상세 프로필 이미지 crop
vahkjsdf Sep 18, 2026
589246e
[fix/#121] 모임 상세 - 참여자 본인 여부에 따라 배경색 변화 추가
vahkjsdf Sep 18, 2026
416970c
[fix/#121] 디자인 수정에 따른 모임 생성 버튼 shadow 수정
vahkjsdf Sep 18, 2026
6b225b7
[fix/#121] 조건 입력 - 일정 정보 에러 타입 추가
vahkjsdf Sep 18, 2026
efe32af
[fix/#121] shadowbutton shape 수정
vahkjsdf Sep 19, 2026
881290c
[fix/#121] 알림 카운터 ID - notificationId 로 수정
vahkjsdf Sep 19, 2026
5931f79
[fix/#121] 조건 입력 - 날짜 저장/다음 버튼 기능 바꿈
vahkjsdf Sep 19, 2026
89019df
[fix/#121] 참여자 카드 배경색 수정
vahkjsdf Sep 19, 2026
48e6347
[fix/#121] 모임 상세 - 툴팁 배경 및 위치 조정
vahkjsdf Sep 19, 2026
613702f
[fix/#121] 탭에 따른 empty 뷰 문구 수정
vahkjsdf Sep 19, 2026
4f836f6
[fix/#121] 토큰 재발급 중 네트워크 오류 시 토스트 띄우기
vahkjsdf Sep 19, 2026
07ddeea
[fix/#121] 확정된 모임 1줄 처리
vahkjsdf Sep 19, 2026
52eca34
[chore/#121] 장소 핀 마크 교체 - 여백 O
vahkjsdf Sep 19, 2026
eab9bf4
[fix/#121] fcm payload에 따른 수정
vahkjsdf Sep 19, 2026
4bdf09e
[fix/#121] 본인 투표 완료 시 모임 상세 하단 버튼 disabled 처리 - 중복 투표 방지
vahkjsdf Sep 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/img_logo_white_bg" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
<meta-data
android:name="firebase_messaging_auto_init_enabled"
android:value="false" />
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/com/moive/app/MoiveApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -12,6 +13,7 @@ class MoiveApplication : Application() {
super.onCreate()

initTimber()
NotificationChannels.createDefaultChannel(this)
initKakaoSdk()
initKakaoMapSdk()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -21,7 +18,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
Expand Down Expand Up @@ -61,33 +57,24 @@ 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()

showNotification(title, body, meetingId, notificationId)
}

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,
Manifest.permission.POST_NOTIFICATIONS,
) == PackageManager.PERMISSION_GRANTED
if (!granted) return

val androidNotificationId = notificationIdGenerator.incrementAndGet()
val androidNotificationId = (notificationId ?: System.currentTimeMillis()).toInt()
Comment thread
vahkjsdf marked this conversation as resolved.

val contentIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
Expand All @@ -101,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)
Expand All @@ -118,9 +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 = "디바이스 토큰 등록 성공"
private val notificationIdGenerator = AtomicInteger(0)
}
}
27 changes: 27 additions & 0 deletions app/src/main/java/com/moive/app/core/fcm/NotificationChannels.kt
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ data class ParticipantItemModel(
val statusLabel: String,
val isMe: Boolean,
val isDone: Boolean,
val isVoteDone: Boolean,
)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
)
Expand All @@ -43,10 +39,6 @@ fun ShadowButton(
)
.background(
color = colors.background.default00,
shape = RoundedCornerShape(
topStart = radius.md,
topEnd = radius.md,
),
)
) {
MoiveButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -156,7 +156,7 @@ class ConditionViewModel @Inject constructor(
}
}

fun onDateSaveClick() {
fun onDateNextClick() {
Comment thread
vahkjsdf marked this conversation as resolved.
_uiState.update {
it.copy(
isDateBottomSheetVisible = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,14 @@ fun DateBottomSheet(
text = "저장",
type = MoiveButtonType.TERTIARY,
size = MoiveButtonSize.LARGE,
enabled = state.pendingDateTime != null,
onClick = onSaveDateClick,
modifier = Modifier.weight(1f),
)
MoiveButton(
text = "다음",
type = MoiveButtonType.PRIMARY,
size = MoiveButtonSize.LARGE,
enabled = state.pendingDateTime != null,
onClick = onNextDateClick,
modifier = Modifier.weight(1f),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -27,6 +28,13 @@ interface HomeContract {
val displayedMyMeetingList: ImmutableList<MyMeetingCardItemModel>
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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ private fun HomeScreen(
)

Text(
text = "아직 참여 중인 모임이 없어요.",
text = uiState.emptyMyMeetingMessage,
color = colors.text.subtle,
style = typography.body.smNormalR,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -101,6 +102,8 @@ fun ConfirmedMeetingCardItem(
text = location,
color = colors.text.onBg,
style = typography.body.smNormalR,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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) })
Expand Down Expand Up @@ -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 },
)
}
}
}
}
19 changes: 10 additions & 9 deletions app/src/main/java/com/moive/app/presentation/main/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Loading
Loading