Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package com.twix.designsystem.components.dialog

import androidx.compose.foundation.Image
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.runtime.Composable
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.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.twix.designsystem.R
import com.twix.designsystem.components.dialog.CommonDialog
import com.twix.designsystem.components.text.AppText
import com.twix.designsystem.theme.GrayColor
import com.twix.designsystem.theme.TwixTheme
import com.twix.domain.model.enums.AppTextStyle
import com.twix.ui.extension.noRippleClickable

@Composable
fun MarketingDialog(
visible: Boolean,
onConfirm: (Boolean, Boolean) -> Unit,
) {
var isMarketingChecked by remember { mutableStateOf(true) }
var isNightMarketingChecked by remember { mutableStateOf(true) }

CommonDialog(
visible = visible,
confirmText = stringResource(R.string.word_confirm),
dismissText = null,
onDismissRequest = { },
onConfirm = {
onConfirm(isMarketingChecked, isNightMarketingChecked)
},
content = {
MarketingDialogContent(
isMarketingChecked = isMarketingChecked,
isNightMarketingChecked = isNightMarketingChecked,
onMarketingToggle = {
isMarketingChecked = !isMarketingChecked
},
onNightMarketingToggle = {
isNightMarketingChecked = !isNightMarketingChecked
},
)
},
)
}

@Composable
private fun MarketingDialogContent(
isMarketingChecked: Boolean,
isNightMarketingChecked: Boolean,
onMarketingToggle: () -> Unit,
onNightMarketingToggle: () -> Unit,
) {
Column {
AppText(
text = stringResource(R.string.marketing_dialog_title),
style = AppTextStyle.T1,
color = GrayColor.C500,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth(),
)

Spacer(Modifier.height(24.dp))

MarketingCheckItem(
text = stringResource(R.string.marketing_dialog_marketing),
checked = isMarketingChecked,
onClick = onMarketingToggle,
)

Spacer(Modifier.height(12.dp))

MarketingCheckItem(
text = stringResource(R.string.marketing_dialog_night_marketing),
checked = isNightMarketingChecked,
onClick = onNightMarketingToggle,
)

Spacer(Modifier.height(14.dp))

AppText(
text = stringResource(R.string.marketing_dialog_description),
style = AppTextStyle.C2,
color = GrayColor.C300,
modifier = Modifier.padding(start = 10.dp),
)
}
}

@Composable
private fun MarketingCheckItem(
text: String,
checked: Boolean,
onClick: () -> Unit,
) {
val icon = if (checked) R.drawable.ic_checked_you else R.drawable.ic_empty_check

Row(
verticalAlignment = Alignment.CenterVertically,
modifier =
Modifier
.fillMaxWidth()
.noRippleClickable(onClick = onClick),
) {
Image(
painter = painterResource(icon),
contentDescription = null,
modifier =
Modifier
.size(24.dp),
)

Spacer(Modifier.width(8.dp))

AppText(
text = text,
style = AppTextStyle.B2,
color = GrayColor.C500,
)
}
}

@Preview(showBackground = true, showSystemUi = true)
@Composable
private fun MarketingDialogPreview() {
TwixTheme {
MarketingDialog(
visible = true,
onConfirm = { _, _ -> },
)
}
}
18 changes: 18 additions & 0 deletions core/design-system/src/main/res/drawable/ic_empty_check.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12.001,12.001m-9.857,0a9.857,9.857 0,1 1,19.714 0a9.857,9.857 0,1 1,-19.714 0"
android:strokeWidth="0.857143"
android:fillColor="#ffffff"
android:strokeColor="#C6C6C6"/>
<path
android:pathData="M7.715,11.099L11.286,15.429L16.286,8.572"
android:strokeLineJoin="round"
android:strokeWidth="1.02857"
android:fillColor="#00000000"
android:strokeColor="#ffffff"
android:strokeLineCap="round"/>
</vector>
7 changes: 7 additions & 0 deletions core/design-system/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<string name="word_cancel">취소</string>
<string name="word_delete">삭제</string>
<string name="word_modify">수정</string>
<string name="word_confirm">확인</string>
<string name="word_save">저장</string>
<string name="word_setting">설정</string>
<string name="word_account">계정</string>
Expand Down Expand Up @@ -122,6 +123,12 @@
<string name="dialog_withdraw_account_title">정말 탈퇴하시겠어요?</string>
<string name="dialog_withdraw_account_content">커플 연결이 끊어집니다.\n데이터는 전부 삭제되며 복구가 불가능합니다.</string>

<!-- 마케팅 다이얼로그 -->
<string name="marketing_dialog_title">도움이 되는 정보를\n알림으로 받아보시겠어요?</string>
<string name="marketing_dialog_marketing">[선택] 마케팅 정보 알림</string>
<string name="marketing_dialog_night_marketing">[선택] 야간 마케팅 정보 알림</string>
<string name="marketing_dialog_description">* 언제든지 설정 > 알림 설정에서 변경 가능해요</string>

<!-- 인증샷 촬영 화면 !-->
<string name="task_certification_upload">업로드</string>
<string name="task_certification_image_capture_fail">이미지 캡처에 실패했습니다. 다시 시도해 주세요.</string>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.twix.onboarding.vm
package com.twix.onboarding

import androidx.lifecycle.viewModelScope
import com.twix.domain.model.OnboardingStatus
Expand All @@ -16,10 +16,6 @@ class OnBoardingViewModel(
private val onBoardingRepository: OnBoardingRepository,
private val notificationRepository: NotificationRepository,
) : BaseViewModel<OnBoardingUiState, OnBoardingIntent, OnBoardingSideEffect>(OnBoardingUiState()) {
init {
initNotificationSettings()
}

fun fetchMyInviteCode() {
launchResult(
block = { onBoardingRepository.fetchInviteCode() },
Expand All @@ -43,6 +39,9 @@ class OnBoardingViewModel(
// 디데이 설정 화면
is OnBoardingIntent.SelectDate -> reduceDday(intent.value)
OnBoardingIntent.SubmitDday -> anniversarySetup()

is OnBoardingIntent.SubmitMarketingConsent ->
initNotificationSettings(intent.isPushEnabled, intent.isMarketingEnabled, intent.isNightMarketingEnabled)
}
}

Expand Down Expand Up @@ -145,9 +144,19 @@ class OnBoardingViewModel(
)
}

private fun initNotificationSettings() {
private fun initNotificationSettings(
isPushEnabled: Boolean,
isMarketingEnabled: Boolean,
isNightMarketingEnabled: Boolean,
) {
launchResult(
block = { notificationRepository.initNotificationSettings(true, true, true) },
block = {
notificationRepository.initNotificationSettings(
isPushEnabled,
isMarketingEnabled,
isNightMarketingEnabled,
)
},
onSuccess = {},
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.twix.onboarding.couple

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
Expand All @@ -13,18 +17,23 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.twix.designsystem.components.bottomsheet.CommonBottomSheet
import com.twix.designsystem.components.bottomsheet.model.CommonBottomSheetConfig
import com.twix.designsystem.components.dialog.MarketingDialog
import com.twix.designsystem.components.text.AppText
import com.twix.designsystem.components.toast.ToastManager
import com.twix.designsystem.components.toast.model.ToastData
Expand All @@ -33,11 +42,12 @@ import com.twix.designsystem.theme.CommonColor
import com.twix.designsystem.theme.GrayColor
import com.twix.designsystem.theme.TwixTheme
import com.twix.domain.model.enums.AppTextStyle
import com.twix.onboarding.OnBoardingViewModel
import com.twix.onboarding.R
import com.twix.onboarding.couple.component.ConnectButton
import com.twix.onboarding.couple.component.RestoreCoupleBottomSheetContent
import com.twix.onboarding.model.OnBoardingIntent
import com.twix.onboarding.model.OnBoardingSideEffect
import com.twix.onboarding.vm.OnBoardingViewModel
import com.twix.ui.base.ObserveAsEvents
import com.twix.ui.extension.noRippleClickable
import org.koin.compose.koinInject
Expand All @@ -48,7 +58,10 @@ fun CoupleConnectRoute(
toastManager: ToastManager = koinInject(),
navigateToNext: () -> Unit,
) {
var showMarketingDialog by rememberSaveable { mutableStateOf(true) }
var showRestoreSheet by rememberSaveable { mutableStateOf(false) }
val context = LocalContext.current
val currentContext by rememberUpdatedState(context)

LaunchedEffect(Unit) {
viewModel.fetchMyInviteCode()
Expand All @@ -71,13 +84,30 @@ fun CoupleConnectRoute(
}
}

CoupleConnectScreen(
showRestoreSheet = showRestoreSheet,
onClickSend = { },
onClickConnect = navigateToNext,
onClickRestore = { showRestoreSheet = true },
onDismissSheet = { showRestoreSheet = false },
)
Box {
CoupleConnectScreen(
showRestoreSheet = showRestoreSheet,
onClickSend = { },
onClickConnect = navigateToNext,
onClickRestore = { showRestoreSheet = true },
onDismissSheet = { showRestoreSheet = false },
)

MarketingDialog(
visible = showMarketingDialog,
onConfirm = { marketing, nightMarketing ->
showMarketingDialog = false
val isPushEnabled = isNotificationPermissionGranted(context)
viewModel.dispatch(
OnBoardingIntent.SubmitMarketingConsent(
isPushEnabled = isPushEnabled,
isMarketingEnabled = marketing,
isNightMarketingEnabled = nightMarketing,
),
)
},
)
}
}

@Composable
Expand Down Expand Up @@ -142,9 +172,23 @@ fun CoupleConnectScreen(
}
}

private fun isNotificationPermissionGranted(context: Context): Boolean {
val notificationsEnabled = NotificationManagerCompat.from(context).areNotificationsEnabled()
if (!notificationsEnabled) return false

return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS,
) == PackageManager.PERMISSION_GRANTED
} else {
true
}
}

@Preview(showBackground = true)
@Composable
fun CoupleConnectScreenPreview() {
private fun CoupleConnectScreenPreview() {
TwixTheme {
CoupleConnectScreen(
showRestoreSheet = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ import com.twix.designsystem.theme.CommonColor
import com.twix.designsystem.theme.GrayColor
import com.twix.designsystem.theme.TwixTheme
import com.twix.domain.model.enums.AppTextStyle
import com.twix.onboarding.OnBoardingViewModel
import com.twix.onboarding.R
import com.twix.onboarding.dday.component.DDayField
import com.twix.onboarding.dday.component.DdayTopBar
import com.twix.onboarding.model.OnBoardingIntent
import com.twix.onboarding.model.OnBoardingSideEffect
import com.twix.onboarding.vm.OnBoardingViewModel
import com.twix.ui.base.ObserveAsEvents
import org.koin.compose.koinInject
import java.time.LocalDate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.twix.onboarding.di

import com.twix.navigation.NavRoutes
import com.twix.navigation.base.NavGraphContributor
import com.twix.onboarding.OnBoardingViewModel
import com.twix.onboarding.navigation.OnboardingNavGraph
import com.twix.onboarding.vm.OnBoardingViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.core.qualifier.named
import org.koin.dsl.module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ import com.twix.designsystem.theme.CommonColor
import com.twix.designsystem.theme.GrayColor
import com.twix.designsystem.theme.TwixTheme
import com.twix.domain.model.enums.AppTextStyle
import com.twix.onboarding.OnBoardingViewModel
import com.twix.onboarding.R
import com.twix.onboarding.invite.component.InviteCodeTextField
import com.twix.onboarding.model.OnBoardingIntent
import com.twix.onboarding.model.OnBoardingSideEffect
import com.twix.onboarding.vm.OnBoardingViewModel
import com.twix.ui.base.ObserveAsEvents
import com.twix.ui.extension.noRippleClickable
import com.twix.ui.keyboard.Keyboard
Expand Down
Loading