diff --git a/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt b/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt index d439e7c810..8dd8e12dff 100644 --- a/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt +++ b/app/src/androidTest/java/com/afternote/afternote_fe/ReceiverAdvancedAndroidTest.kt @@ -40,9 +40,6 @@ import com.afternote.feature.receiver.presentation.recordsbox.ReceivedRecordsVie import com.afternote.feature.receiver.presentation.recordsbox.SenderRegistrationScreen import com.afternote.feature.receiver.presentation.recordsbox.SenderRegistrationViewModel import com.afternote.feature.receiver.presentation.recordsbox.SenderRegistry -import com.afternote.feature.receiver.presentation.summary.ReceiverAfterNoteScreen -import com.afternote.feature.receiver.presentation.summary.ReceiverDownloadAllEvent -import com.afternote.feature.receiver.presentation.summary.ReceiverDownloadAllViewModel import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNull @@ -205,80 +202,6 @@ class ReceiverAdvancedAndroidTest { assertEquals(listOf(91L, 91L), repository.requestedDetailIds) } - - @Test - fun download_cancelThenDownloadFailureSaveFailureAndSuccess_preservesStageBoundaries() { - val saveFailureBundle = ReceivedExportBundle(payloadJson = "{\"attempt\":2}") - val successBundle = ReceivedExportBundle(payloadJson = "{\"attempt\":3}") - val downloadResults = ArrayDeque>() - val saveResults = ArrayDeque>() - val repository = - FakeReceiverRepository.strict().apply { - onDownloadReceivedExport = { downloadResults.removeFirst() } - onSaveReceivedExportToFile = { saveResults.removeFirst() } - } - downloadResults.addLast(Result.failure(IllegalStateException("offline"))) - downloadResults.addLast(Result.success(saveFailureBundle)) - downloadResults.addLast(Result.success(successBundle)) - saveResults.addLast(Result.failure(IllegalStateException("disk full"))) - saveResults.addLast(Result.success(Unit)) - val viewModel = ReceiverDownloadAllViewModel(repository, FakeErrorReporter()) - - composeRule.setContent { - val uiState by viewModel.uiState.collectAsStateWithLifecycle() - AfternoteTheme { - ReceiverAfterNoteScreen( - downloadUiState = uiState, - showBottomBar = false, - onDownloadConfirm = { - viewModel.onEvent(ReceiverDownloadAllEvent.ConfirmDownload) - }, - ) - } - } - - openDownloadDialog() - composeRule.onNodeWithText("아니요").performClick() - assertEquals(0, repository.downloadCalls) - assertEquals(0, repository.savedBundles.size) - - confirmDownload() - composeRule.waitUntil(timeoutMillis = 5_000) { - viewModel.uiState.value.errorMessageRes == ReceiverR.string.receiver_download_all_failed - } - assertEquals(1, repository.downloadCalls) - assertEquals(0, repository.savedBundles.size) - - confirmDownload() - composeRule.waitUntil(timeoutMillis = 5_000) { - viewModel.uiState.value.errorMessageRes == ReceiverR.string.receiver_download_all_save_failed - } - assertEquals(2, repository.downloadCalls) - assertEquals(listOf(saveFailureBundle), repository.savedBundles) - - confirmDownload() - composeRule.waitUntil(timeoutMillis = 5_000) { - viewModel.uiState.value.downloadSuccess - } - assertEquals(3, repository.downloadCalls) - assertEquals(listOf(saveFailureBundle, successBundle), repository.savedBundles) - assertNull(viewModel.uiState.value.errorMessageRes) - assertTrue(viewModel.uiState.value.downloadSuccess) - assertFalse(viewModel.uiState.value.isLoading) - } - - private fun openDownloadDialog() { - composeRule - .onNodeWithText("모든 기록 내려받기") - .performScrollTo() - .performClick() - composeRule.onNodeWithText("모든 기록을 내려받으시겠습니까?").assertIsDisplayed() - } - - private fun confirmDownload() { - openDownloadDialog() - composeRule.onNodeWithText("예").performClick() - } } private enum class RegistrationPhase { diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/SenderMessageHeroCard.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/SenderMessageHeroCard.kt index cfa567ad7f..ca4bb5026e 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/SenderMessageHeroCard.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/SenderMessageHeroCard.kt @@ -67,8 +67,8 @@ fun SenderMessageHeroCard( /** * SenderMessageHeroCard 전용 파스텔 그라데이션 (그린 → 크림 → 피치). * - * 본 화면 1회용 + 다른 화면 (예: [HeroCard]) 의 그라데이션과 색 조합이 달라 디자인 시스템 - * 토큰으로 추상화하면 재사용성보다 SSOT 위반 비용이 큼. + * 본 화면 1회용이고 다른 화면의 그라데이션과 색 조합이 달라, 디자인 시스템 토큰으로 추상화하면 + * 재사용성보다 SSOT 위반 비용이 큼. * 공용 색상 토큰으로 일반화하기 어려운 화면 전용 예외라 이 한 곳에 고정. */ private fun heroGradient(): Brush = diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ContentSection.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ContentSection.kt deleted file mode 100644 index aa1bb28f4e..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ContentSection.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.defaultMinSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -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.graphics.painter.Painter -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.afternote.core.ui.icon.RightArrowIcon -import com.afternote.core.ui.theme.AfternoteDesign - -@Composable -fun ContentSection( - title: String, - desc: String, - subDesc: String, - btnText: String, - imageResource: Painter, - modifier: Modifier = Modifier, - onButtonClick: () -> Unit = {}, -) { - Column(modifier = modifier.padding(bottom = 24.dp)) { - Text( - text = title, - style = AfternoteDesign.typography.bodyLargeB, - color = AfternoteDesign.colors.gray9, - ) - - Box( - modifier = - Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .background(AfternoteDesign.colors.white), - ) { - Box( - modifier = - Modifier - .align(Alignment.BottomEnd), - ) { - Image( - painter = imageResource, - contentDescription = null, - modifier = - Modifier - .size(170.dp), - ) - } - - Column(modifier = Modifier.padding(20.dp)) { - Text( - text = desc, - style = - AfternoteDesign.typography.textField.copy( - fontWeight = FontWeight.Medium, - color = AfternoteDesign.colors.gray9, - ), - ) - Text( - text = subDesc, - style = AfternoteDesign.typography.captionLargeR, - color = AfternoteDesign.colors.gray9, - modifier = Modifier.padding(top = 4.dp, bottom = 16.dp), - ) - - Button( - onClick = onButtonClick, - colors = ButtonDefaults.buttonColors(containerColor = AfternoteDesign.colors.gray9), - shape = RoundedCornerShape(50), - contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), - modifier = Modifier.defaultMinSize(minHeight = 36.dp), - ) { - Text( - text = btnText, - style = - AfternoteDesign.typography.captionLargeR.copy( - fontWeight = FontWeight.Medium, - color = AfternoteDesign.colors.gray9, - ), - ) - - RightArrowIcon( - modifier = - Modifier - .padding(start = 4.dp) - .size(12.dp), - tint = AfternoteDesign.colors.gray9, - ) - } - } - } - } -} diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCard.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCard.kt deleted file mode 100644 index 6c152e423d..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCard.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -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.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.draw.clip -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.afternote.core.ui.theme.AfternoteDesign -import com.afternote.feature.receiver.presentation.R - -/** - * HeroCard 전용 파스텔 그라데이션 (라이트 블루 → 화이트-ish → 라이트 피치). - * - * 본 화면 1회용 + 다른 화면 (예: SenderMessageHeroCard) 의 그라데이션과 색 조합이 달라 - * 디자인 시스템 토큰으로 추상화하면 재사용성보다 SSOT 위반 비용이 큼. - * 공용 색상 토큰으로 일반화하기 어려운 화면 전용 예외라 이 한 곳에 고정. - */ -private val HeroGradient: Brush = - Brush.linearGradient( - colors = - listOf( - Color(0xFFD0E4FF), - Color(0xFFF0F4F8), - Color(0xFFFFE0CC), - ), - ) - -@Composable -fun HeroCard( - modifier: Modifier = Modifier, - leaveMessage: String = stringResource(R.string.receiver_hero_default_message), -) { - Box( - modifier = - modifier - .fillMaxWidth() - .height(140.dp) - .clip(RoundedCornerShape(16.dp)) - .background(brush = HeroGradient), - ) { - Image( - painter = painterResource(R.drawable.receiver_img_hero_background), - contentDescription = null, - modifier = Modifier.fillMaxSize(), - contentScale = ContentScale.Crop, - ) - - Column( - modifier = - Modifier - .padding(20.dp) - .align(Alignment.CenterStart), - ) { - Text( - text = leaveMessage, - style = AfternoteDesign.typography.h2, - color = AfternoteDesign.colors.gray8, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = stringResource(R.string.receiver_hero_last_greeting_caption), - style = - AfternoteDesign.typography.bodySmallR.copy( - fontWeight = FontWeight.Medium, - color = AfternoteDesign.colors.gray5, - ), - ) - } - } -} diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverAfternoteScreen.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverAfternoteScreen.kt deleted file mode 100644 index 4262cdcf3a..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverAfternoteScreen.kt +++ /dev/null @@ -1,209 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import android.widget.Toast -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.material3.Scaffold -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.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalResources -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import com.afternote.core.ui.bottombar.BottomBar -import com.afternote.core.ui.bottombar.BottomNavTab -import com.afternote.core.ui.button.AfternoteButton -import com.afternote.core.ui.button.AfternoteButtonType -import com.afternote.core.ui.popup.Popup -import com.afternote.core.ui.popup.PopupType -import com.afternote.core.ui.theme.AfternoteDesign -import com.afternote.feature.receiver.presentation.R - -/** - * 수신자 애프터노트 메인 Entry. - * - * ViewModel에서 데이터를 로드·가공하고, Entry는 Screen에 전달만 합니다. - */ -@Composable -fun ReceiverAfterNoteEntry( - modifier: Modifier = Modifier, - summary: ReceiverSummaryUiState = ReceiverSummaryUiState(), - showBottomBar: Boolean = true, - selectedNavTab: BottomNavTab = BottomNavTab.NOTE, - onNavTabSelected: (BottomNavTab) -> Unit = {}, - onNavigateToRecord: () -> Unit = {}, - onNavigateToTimeLetter: () -> Unit = {}, - onNavigateToAfternote: () -> Unit = {}, - viewModel: ReceiverDownloadAllViewModel = hiltViewModel(), -) { - val downloadUiState by viewModel.uiState.collectAsStateWithLifecycle() - val context = LocalContext.current - val resources = LocalResources.current - - LaunchedEffect(downloadUiState.downloadSuccess) { - if (downloadUiState.downloadSuccess) { - viewModel.onEvent(ReceiverDownloadAllEvent.DownloadSuccessConsumed) - } - } - LaunchedEffect(downloadUiState.errorMessageRes) { - downloadUiState.errorMessageRes?.let { messageRes -> - Toast.makeText(context, resources.getString(messageRes), Toast.LENGTH_SHORT).show() - viewModel.onEvent(ReceiverDownloadAllEvent.ErrorConsumed) - } - } - - ReceiverAfterNoteScreen( - modifier = modifier, - summary = summary, - downloadUiState = downloadUiState, - showBottomBar = showBottomBar, - selectedNavTab = selectedNavTab, - onNavTabSelected = onNavTabSelected, - onNavigateToRecord = onNavigateToRecord, - onNavigateToTimeLetter = onNavigateToTimeLetter, - onNavigateToAfternote = onNavigateToAfternote, - onDownloadConfirm = { viewModel.onEvent(ReceiverDownloadAllEvent.ConfirmDownload) }, - ) -} - -/** - * 수신자 애프터노트 메인 Screen. - * - * ViewModel 의존성 없이 순수하게 UI만 그립니다. Preview 가능합니다. - */ -@Composable -fun ReceiverAfterNoteScreen( - modifier: Modifier = Modifier, - summary: ReceiverSummaryUiState = ReceiverSummaryUiState(), - downloadUiState: ReceiverDownloadAllUiState = ReceiverDownloadAllUiState(), - showBottomBar: Boolean = true, - selectedNavTab: BottomNavTab = BottomNavTab.NOTE, - onNavTabSelected: (BottomNavTab) -> Unit = {}, - onNavigateToRecord: () -> Unit = {}, - onNavigateToTimeLetter: () -> Unit = {}, - onNavigateToAfternote: () -> Unit = {}, - onDownloadConfirm: () -> Unit = {}, -) { - var showDialog by remember { mutableStateOf(false) } - - if (showDialog) { - Popup( - type = PopupType.Variant2, - message = stringResource(R.string.receiver_download_all_dialog_message), - onConfirm = { - onDownloadConfirm() - showDialog = false - }, - onDismiss = { showDialog = false }, - isLoading = downloadUiState.isLoading, - ) - } - - val scrollState = rememberScrollState() - - Scaffold( - modifier = modifier, - containerColor = Color.Transparent, - topBar = { TopHeader() }, - bottomBar = { - if (showBottomBar) { - BottomBar( - selectedNavTab = selectedNavTab, - onTabClick = onNavTabSelected, - ) - } - }, - ) { innerPadding -> - androidx.compose.foundation.layout.Column( - modifier = - Modifier - .padding(innerPadding) - .fillMaxSize() - .padding(horizontal = 20.dp, vertical = 10.dp) - .verticalScroll(scrollState), - ) { - Text( - text = - stringResource( - R.string.receiver_sender_record_title, - summary.senderName.ifBlank { "" }, - ), - style = - AfternoteDesign.typography.bodyLargeB.copy( - color = AfternoteDesign.colors.gray9, - ), - modifier = Modifier.padding(bottom = 16.dp), - ) - - HeroCard( - leaveMessage = - summary.leaveMessage?.takeIf { it.isNotBlank() } - ?: stringResource(R.string.receiver_hero_default_message), - ) - - Spacer(modifier = Modifier.height(24.dp)) - - ContentSection( - title = stringResource(R.string.receiver_mindrecord_section_title), - desc = stringResource(R.string.receiver_mindrecord_section_desc), - subDesc = - stringResource( - R.string.receiver_mindrecord_section_count, - summary.mindRecordTotalCount, - ), - btnText = stringResource(R.string.receiver_mindrecord_section_button), - imageResource = painterResource(R.drawable.receiver_img_book), - onButtonClick = onNavigateToRecord, - ) - - ContentSection( - title = stringResource(R.string.receiver_timeletter_section_title), - desc = stringResource(R.string.receiver_timeletter_section_desc), - subDesc = - stringResource( - R.string.receiver_timeletter_section_count, - summary.timeLetterTotalCount, - ), - btnText = stringResource(R.string.receiver_timeletter_section_button), - imageResource = painterResource(R.drawable.receiver_img_letter), - onButtonClick = onNavigateToTimeLetter, - ) - - ContentSection( - title = stringResource(R.string.receiver_afternote_section_title), - desc = stringResource(R.string.receiver_afternote_section_desc), - subDesc = - stringResource( - R.string.receiver_afternote_section_count, - summary.afternoteTotalCount, - ), - btnText = stringResource(R.string.receiver_afternote_section_button), - imageResource = painterResource(R.drawable.receiver_img_notebook), - onButtonClick = onNavigateToAfternote, - ) - - Spacer(modifier = Modifier.height(20.dp)) - - AfternoteButton( - text = stringResource(R.string.receiver_download_all_button), - onClick = { showDialog = true }, - type = AfternoteButtonType.Default, - ) - } - } -} diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllEvent.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllEvent.kt deleted file mode 100644 index 740c4aafec..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllEvent.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -/** - * 모든 기록 내려받기 UI 이벤트. - */ -sealed interface ReceiverDownloadAllEvent { - data object ConfirmDownload : ReceiverDownloadAllEvent - - data object DownloadSuccessConsumed : ReceiverDownloadAllEvent - - data object ErrorConsumed : ReceiverDownloadAllEvent -} diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllUiState.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllUiState.kt deleted file mode 100644 index 6c73ab6a58..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllUiState.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.annotation.StringRes - -/** - * 모든 기록 내려받기 다이얼로그/화면 UI 상태. - */ -data class ReceiverDownloadAllUiState( - val isLoading: Boolean = false, - @param:StringRes val errorMessageRes: Int? = null, - val downloadSuccess: Boolean = false, -) diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllViewModel.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllViewModel.kt deleted file mode 100644 index cd90f04af0..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverDownloadAllViewModel.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.afternote.core.common.reporting.ErrorReporter -import com.afternote.feature.receiver.domain.repository.ReceiverRepository -import com.afternote.feature.receiver.presentation.R -import com.afternote.feature.receiver.presentation.reporting.ReceiverFailureStage -import com.afternote.feature.receiver.presentation.reporting.recordReceiverFailure -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import javax.inject.Inject - -/** - * 모든 기록 내려받기: 인증번호로 묶음을 조회한 뒤 파일로 저장합니다. - */ -@HiltViewModel -class ReceiverDownloadAllViewModel - @Inject - constructor( - private val receiverRepository: ReceiverRepository, - private val errorReporter: ErrorReporter, - ) : ViewModel() { - private val _uiState = MutableStateFlow(ReceiverDownloadAllUiState()) - val uiState: StateFlow = _uiState.asStateFlow() - - fun onEvent(event: ReceiverDownloadAllEvent) { - when (event) { - ReceiverDownloadAllEvent.ConfirmDownload -> handleConfirmDownload() - ReceiverDownloadAllEvent.DownloadSuccessConsumed -> handleClearDownloadSuccess() - ReceiverDownloadAllEvent.ErrorConsumed -> handleClearError() - } - } - - private fun handleConfirmDownload() { - viewModelScope.launch { - _uiState.update { - it.copy(isLoading = true, errorMessageRes = null, downloadSuccess = false) - } - receiverRepository - .downloadReceivedExport() - .onSuccess { result -> - receiverRepository - .saveReceivedExportToFile(result) - .onSuccess { - _uiState.update { - it.copy(isLoading = false, downloadSuccess = true) - } - }.onFailure { e -> - errorReporter.recordReceiverFailure(ReceiverFailureStage.RECEIVED_EXPORT_SAVE, e) - _uiState.update { - it.copy( - isLoading = false, - errorMessageRes = R.string.receiver_download_all_save_failed, - ) - } - } - }.onFailure { e -> - errorReporter.recordReceiverFailure(ReceiverFailureStage.RECEIVED_EXPORT_DOWNLOAD, e) - _uiState.update { - it.copy( - isLoading = false, - errorMessageRes = R.string.receiver_download_all_failed, - ) - } - } - } - } - - private fun handleClearDownloadSuccess() { - _uiState.update { it.copy(downloadSuccess = false) } - } - - private fun handleClearError() { - _uiState.update { it.copy(errorMessageRes = null) } - } - } diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverSummaryUiState.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverSummaryUiState.kt deleted file mode 100644 index f16db091c2..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/ReceiverSummaryUiState.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -/** - * 수신자 홈 화면에 표시할 요약 정보. - * - * Route에서 ViewModel 데이터를 수집한 뒤 Stateless Screen에 전달합니다. - */ -data class ReceiverSummaryUiState( - val authCode: String = "", - val senderName: String = "", - val leaveMessage: String? = null, - val mindRecordTotalCount: Int = 0, - val timeLetterTotalCount: Int = 0, - val afternoteTotalCount: Int = 0, -) diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/TopHeader.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/TopHeader.kt deleted file mode 100644 index 0a27fd5d49..0000000000 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/summary/TopHeader.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.afternote.core.ui.theme.AfternoteDesign -import com.afternote.core.ui.topbar.DetailTopBar -import com.afternote.feature.receiver.presentation.R - -@Composable -fun TopHeader(modifier: Modifier = Modifier) { - DetailTopBar( - modifier = modifier, - title = "AFTERNOTE", - actions = { - Icon( - painter = painterResource(R.drawable.receiver_ic_person), - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = AfternoteDesign.colors.gray9, - ) - Spacer(modifier = Modifier.width(16.dp)) - Icon( - painter = painterResource(R.drawable.receiver_ic_settings), - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = AfternoteDesign.colors.gray9, - ) - }, - ) -} diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_ic_person.xml b/feature/receiver/presentation/src/main/res/drawable/receiver_ic_person.xml deleted file mode 100644 index deebb3d405..0000000000 --- a/feature/receiver/presentation/src/main/res/drawable/receiver_ic_person.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_ic_settings.xml b/feature/receiver/presentation/src/main/res/drawable/receiver_ic_settings.xml deleted file mode 100644 index 7279c4da99..0000000000 --- a/feature/receiver/presentation/src/main/res/drawable/receiver_ic_settings.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_img_book.png b/feature/receiver/presentation/src/main/res/drawable/receiver_img_book.png deleted file mode 100644 index a75515d65f..0000000000 Binary files a/feature/receiver/presentation/src/main/res/drawable/receiver_img_book.png and /dev/null differ diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_img_hero_background.png b/feature/receiver/presentation/src/main/res/drawable/receiver_img_hero_background.png deleted file mode 100644 index 37aa6fb8da..0000000000 Binary files a/feature/receiver/presentation/src/main/res/drawable/receiver_img_hero_background.png and /dev/null differ diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_img_letter.png b/feature/receiver/presentation/src/main/res/drawable/receiver_img_letter.png deleted file mode 100644 index ebc42b0433..0000000000 Binary files a/feature/receiver/presentation/src/main/res/drawable/receiver_img_letter.png and /dev/null differ diff --git a/feature/receiver/presentation/src/main/res/drawable/receiver_img_notebook.png b/feature/receiver/presentation/src/main/res/drawable/receiver_img_notebook.png deleted file mode 100644 index 0ffd71cda4..0000000000 Binary files a/feature/receiver/presentation/src/main/res/drawable/receiver_img_notebook.png and /dev/null differ diff --git a/feature/receiver/presentation/src/main/res/values/strings.xml b/feature/receiver/presentation/src/main/res/values/strings.xml index 2df113292d..e9d40279c9 100644 --- a/feature/receiver/presentation/src/main/res/values/strings.xml +++ b/feature/receiver/presentation/src/main/res/values/strings.xml @@ -56,33 +56,6 @@ 고인이 계정 정보를 남기지 않았습니다. 남기지 않음 - - - - 故 %1$s님이 남기신 기록 - 가족들에게…\n내가 없어도 너무 슬퍼하지마. - - 고인이 남긴 마지막 인사말 - 마음의 기록 - 고인의 일상적인 생각과 감정, 일기들입니다. - 마음의 기록 확인하러 가기 - %1$d개 마음의 기록이 있습니다. - 타임레터 - 고인이 특별한 날에 작성한 편지입니다. - 라이프 이벤트 레터 확인하러 가기 - %1$d개 라이프 이벤트 레터가 있습니다. - 애프터노트 - 고인이 사후 정리하고자 하는 데이터입니다. - 애프터노트 확인하러 가기 - %1$d개의 애프터노트가 있습니다. - 모든 기록 내려받기 - 모든 기록을 내려받으시겠습니까? - 모든 기록 내려받기에 실패했습니다. - 파일 저장에 실패했습니다. - %1$s님의 플레이리스트 플레이리스트를 불러오지 못했습니다. diff --git a/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTest.kt b/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTest.kt deleted file mode 100644 index 51aaf1eefa..0000000000 --- a/feature/receiver/presentation/src/screenshotTest/kotlin/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTest.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.afternote.feature.receiver.presentation.summary - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.Preview -import com.afternote.core.ui.theme.AfternoteTheme -import com.android.tools.screenshot.PreviewTest - -@PreviewTest -@Preview(showBackground = true) -@Composable -internal fun heroCardScreenshot() { - AfternoteTheme { - HeroCard() - } -} diff --git a/feature/receiver/presentation/src/screenshotTestDebug/reference/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTestKt/heroCardScreenshot_748aa731_0.png b/feature/receiver/presentation/src/screenshotTestDebug/reference/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTestKt/heroCardScreenshot_748aa731_0.png deleted file mode 100644 index 4cc5aecda5..0000000000 Binary files a/feature/receiver/presentation/src/screenshotTestDebug/reference/com/afternote/feature/receiver/presentation/summary/HeroCardScreenshotTestKt/heroCardScreenshot_748aa731_0.png and /dev/null differ