Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.selected
Expand Down Expand Up @@ -177,7 +178,7 @@ fun DatePickerContent(
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = "${currentYear}년 ${currentMonth}월",
text = stringResource(R.string.core_ui_calendar_year_month, currentYear, currentMonth),
style = AfternoteDesign.typography.bodySmallR,
color = AfternoteDesign.colors.gray9,
modifier = Modifier.weight(1f),
Expand Down Expand Up @@ -240,7 +241,7 @@ fun CalendarGridContent(
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
val dayLabels = listOf("일", "월", "화", "수", "목", "금", "토")
val dayLabels = stringArrayResource(R.array.core_ui_calendar_day_labels)
Row(modifier = Modifier.fillMaxWidth()) {
dayLabels.forEach { label ->
Text(
Expand Down
12 changes: 12 additions & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@
<string name="core_ui_network_error_retry">다시 시도하기</string>
<!-- 홈 상단바 설정 액션 접근성 이름 (#613). 프로필 아이콘은 목적지가 없는 장식이라 이름을 두지 않는다. -->
<string name="core_ui_home_top_bar_setting">설정</string>
<!-- 바텀시트 캘린더. 요일은 순서·개수가 고정된 집합이라 개별 키 7개 대신 배열로 둔다
(호출부에서 listOf 로 다시 조립하면 순서가 어긋날 여지가 생긴다). -->
<string name="core_ui_calendar_year_month">%1$d년 %2$d월</string>
<string-array name="core_ui_calendar_day_labels">
<item>일</item>
<item>월</item>
<item>화</item>
<item>수</item>
<item>목</item>
<item>금</item>
<item>토</item>
</string-array>
<!-- 수신자 선택 화면 공용 문구 (#791). 소비자가 달리 쓰려면 파라미터로 덮는다. -->
<string name="core_ui_receiver_select_title">수신자 선택</string>
<string name="core_ui_receiver_select_search_placeholder">이름으로 검색하기</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ private fun VideoCard(
content = {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Text(
text = "장례식에 남길 영상",
text = stringResource(R.string.afternote_editor_funeral_video_label),
style =
AfternoteDesign.typography.textField.copy(
fontWeight = FontWeight.Medium,
Expand Down Expand Up @@ -328,7 +328,8 @@ private fun VideoThumbnail(thumbnailUrl: String?) {
if (!thumbnailUrl.isNullOrBlank()) {
AsyncImage(
model = thumbnailUrl,
contentDescription = "장례식에 남길 영상 썸네일",
contentDescription =
stringResource(R.string.afternote_content_description_memorial_video_thumbnail),
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
Expand All @@ -354,7 +355,7 @@ private fun VideoThumbnail(thumbnailUrl: String?) {
// 재생 아이콘
Image(
painter = painterResource(R.drawable.feature_afternote_ic_playback),
contentDescription = "영상 재생",
contentDescription = stringResource(R.string.content_description_video_play),
modifier =
Modifier
.align(Alignment.Center)
Expand All @@ -380,7 +381,7 @@ private fun PlaylistCard(
content = {
Column {
Text(
text = "추억 플레이리스트",
text = stringResource(R.string.afternote_editor_playlist_screen_title),
style =
AfternoteDesign.typography.textField.copy(
fontWeight = FontWeight.Medium,
Expand All @@ -393,7 +394,7 @@ private fun PlaylistCard(
}
Spacer(Modifier.height(8.dp))
Text(
text = "현재 ${songCount}개의 노래가 담겨 있습니다.",
text = stringResource(R.string.afternote_detail_playlist_song_count, songCount),
style =
AfternoteDesign.typography.bodySmallR.copy(
color = AfternoteDesign.colors.black,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ fun EditorSectionLabel(
fontWeight = FontWeight.Medium,
),
) {
val requiredMarkerDescription =
stringResource(R.string.afternote_editor_semantics_required_field)
val requiredFieldDescription =
stringResource(R.string.afternote_editor_semantics_required_field_description, text)

Row(
modifier =
modifier.semantics(mergeDescendants = true) {
if (isRequired) {
contentDescription = "$text, $requiredMarkerDescription"
contentDescription = requiredFieldDescription
}
},
verticalAlignment = Alignment.CenterVertically,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.afternote.core.ui.AfternoteOutlinedCard
import com.afternote.core.ui.AfternoteSectionHeader
import com.afternote.core.ui.icon.RightArrowIcon
import com.afternote.core.ui.theme.AfternoteDesign
import com.afternote.feature.afternote.presentation.R

/**
* NEXT STEP 카드에 필요한 값 묶음.
Expand Down Expand Up @@ -52,7 +54,7 @@ internal fun HomeHeaderSection(
.padding(horizontal = 25.dp),
) {
Text(
text = "애프터노트",
text = stringResource(R.string.afternote_home_title),
style = AfternoteDesign.typography.h1,
color = AfternoteDesign.colors.gray9,
)
Expand Down Expand Up @@ -82,7 +84,7 @@ private fun NextStepCard(
modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
AfternoteSectionHeader(title = "NEXT STEP")
AfternoteSectionHeader(title = stringResource(R.string.afternote_home_next_step_section_title))
AfternoteOutlinedCard(
onClick = onClick,
contentPadding = PaddingValues(start = 16.dp, top = 16.dp, bottom = 16.dp, end = 20.dp),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
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 androidx.core.net.toUri
Expand Down Expand Up @@ -82,7 +83,7 @@ fun MemorialReceivedDetailScreen(
// → 탑바가 상태바(시계·배터리) 밑에서 시작(겹침 방지). 동적 인셋이라 회전·분할화면에도 대응.
Column(modifier = Modifier.statusBarsPadding()) {
DetailTopBar(
title = "故 ${senderName}님의 애프터노트",
title = stringResource(R.string.afternote_receiver_detail_title, senderName),
onBackClick = { onBackClick() },
)
}
Expand Down Expand Up @@ -117,7 +118,6 @@ fun MemorialReceivedDetailScreen(
},
playlistContent = {
MemorialPlaylist(
label = "추억 플레이리스트",
songCount = songCount,
albumCovers = albumCovers,
onCardClick = onNavigateToPlaylist,
Expand All @@ -143,7 +143,7 @@ fun MemorialReceivedDetailScreen(
Spacer(modifier = Modifier.height(70.dp))

AfternoteButton(
text = "애프터노트 확인하기",
text = stringResource(R.string.afternote_receiver_detail_confirm),
onClick = onNavigateToFullList,
type = AfternoteButtonType.Default,
)
Expand All @@ -153,14 +153,13 @@ fun MemorialReceivedDetailScreen(
}
}

private const val LABEL_VIDEO_SECTION = "장례식에 남길 영상"

@Composable
private fun ReceiverVideoSection(
memorialVideoUrl: String? = null,
memorialThumbnailUrl: String? = null,
) {
val context = LocalContext.current
val noVideoAppMessage = stringResource(R.string.receiver_memorial_video_no_app)
Column(modifier = Modifier.fillMaxWidth()) {
ReceiverSectionHeader()
Spacer(modifier = Modifier.height(12.dp))
Expand Down Expand Up @@ -190,7 +189,7 @@ private fun ReceiverVideoSection(
Toast
.makeText(
context,
"영상을 재생할 수 있는 앱이 없습니다.",
noVideoAppMessage,
Toast.LENGTH_SHORT,
).show()
},
Expand All @@ -211,7 +210,9 @@ private fun ReceiverVideoSection(
) {
Icon(
painter = painterResource(R.drawable.receiver_ic_play_arrow),
contentDescription = "Play",
// 영상이 없을 때만 그리는 플레이스홀더다. clickable 이 없어 재생 액션이 없으므로
// 라벨을 붙이면 없는 어포던스를 알린다. 맥락은 위 ReceiverSectionHeader 가 읽어 준다.
contentDescription = null,
tint = AfternoteDesign.colors.white,
modifier =
Modifier
Expand Down Expand Up @@ -295,7 +296,8 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) {
if (!thumbnailUrl.isNullOrBlank()) {
AsyncImage(
model = thumbnailUrl,
contentDescription = "장례식에 남길 영상 썸네일",
contentDescription =
stringResource(R.string.afternote_content_description_memorial_video_thumbnail),
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
)
Expand All @@ -317,7 +319,7 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) {
)
Image(
painter = painterResource(R.drawable.feature_afternote_ic_playback),
contentDescription = "영상 재생",
contentDescription = stringResource(R.string.content_description_video_play),
modifier =
Modifier
.align(Alignment.Center)
Expand All @@ -327,7 +329,7 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) {
}

@Composable
private fun ReceiverSectionHeader(title: String = LABEL_VIDEO_SECTION) {
private fun ReceiverSectionHeader(title: String = stringResource(R.string.afternote_editor_funeral_video_label)) {
Text(
text = title,
style =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import com.afternote.feature.afternote.presentation.shared.model.AlbumCover
@Composable
fun MemorialPlaylist(
modifier: Modifier = Modifier,
label: String = "추억 플레이리스트",
label: String = stringResource(R.string.afternote_editor_playlist_screen_title),
songCount: Int = 0,
albumCovers: List<AlbumCover> = emptyList(),
onCardClick: (() -> Unit)? = null,
Expand Down Expand Up @@ -133,7 +133,7 @@ private fun MemorialPlaylistCardContent(
)
Spacer(modifier = Modifier.size(24.dp))
Text(
text = "현재 ${songCount}개의 노래가 담겨 있습니다.",
text = stringResource(R.string.afternote_detail_playlist_song_count, songCount),
style =
AfternoteDesign.typography.bodySmallR.copy(
color = AfternoteDesign.colors.black,
Expand Down
12 changes: 10 additions & 2 deletions feature/afternote/presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<string name="nav_home">홈</string>
<string name="nav_record">기록</string>
<string name="nav_timeletter">타임 레터</string>
<string name="nav_afternote">애프터노트</string>
<string name="afternote_home_title">애프터노트</string>
<string name="home_coming_soon">홈 (준비 중)</string>

<string name="home_greeting">안녕하세요, %1$s님</string>
Expand Down Expand Up @@ -168,6 +168,7 @@
<string name="time_letter_recipients_count">%d명에게</string>
<string name="content_description_expand_down">아래로</string>
<string name="content_description_video_play">영상 재생</string>
<string name="afternote_content_description_memorial_video_thumbnail">장례식에 남길 영상 썸네일</string>

<string name="post_delivery_last_greeting_placeholder">마지막 인사말을 입력해주세요</string>
<string name="post_delivery_confirm">확인</string>
Expand Down Expand Up @@ -222,7 +223,7 @@
<string name="afternote_editor_content_description_dropdown">드롭다운</string>
<string name="afternote_editor_content_description_add">추가</string>
<string name="afternote_editor_content_description_more">더보기</string>
<string name="afternote_editor_semantics_required_field">필수 항목</string>
<string name="afternote_editor_semantics_required_field_description">%1$s, 필수 항목</string>
<string name="afternote_editor_funeral_video_label">장례식에 남길 영상</string>
<string name="afternote_editor_funeral_video_cd_change">영상 변경</string>
<string name="afternote_editor_funeral_video_cd_add">영상 추가</string>
Expand All @@ -241,6 +242,13 @@
<string name="afternote_editor_media_source_remove_photo">사진 삭제</string>
<string name="afternote_editor_media_source_remove_video">영상 삭제</string>
<string name="afternote_editor_media_capture_unavailable">카메라를 사용할 수 없습니다.</string>
<!-- 추억 노트 상세. 이름 세그먼트는 프로필 로드 실패·경합으로 비어 있을 수 있어 두 갈래로 둔다. -->
<string name="afternote_detail_playlist_song_count">현재 %1$d개의 노래가 담겨 있습니다.</string>
<string name="afternote_home_next_step_section_title">NEXT STEP</string>
<!-- 수신 애프터노트 상세. 이 화면 문자열은 afternote 모듈에 모여 있고(#1461 이 화면까지 이 모듈로 옮긴다),
신규 키는 #1079 규약대로 afternote_ 프리픽스를 쓴다. -->
<string name="afternote_receiver_detail_title">故 %1$s님의 애프터노트</string>
<string name="afternote_receiver_detail_confirm">애프터노트 확인하기</string>

<!-- 수신 애프터노트 화면 (#1461 로 :feature:receiver:presentation 에서 이관) -->
<string name="receiver_afternote_list_header_description">고인이 사후 정리하고자 하는 데이터입니다.</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,27 +50,27 @@ fun TermsDetailScreen(

// 각 약관 섹션들 (반복되는 구조는 별도 컴포저블로 분리하여 가독성 확보)
TermsSectionText(
title = "1. 서비스 이용약관",
title = stringResource(R.string.onboarding_terms_detail_section_1_title),
content = stringResource(R.string.onboarding_terms_detail_section_1),
)
TermsSectionText(
title = "2. 개인정보 수집 및 이용 동의",
title = stringResource(R.string.onboarding_terms_detail_section_2_title),
content = stringResource(R.string.onboarding_terms_detail_section_2),
)
TermsSectionText(
title = "3. 기록 및 콘텐츠 저장에 대한 안내",
title = stringResource(R.string.onboarding_terms_detail_section_3_title),
content = stringResource(R.string.onboarding_terms_detail_section_3),
)
TermsSectionText(
title = "4. 계정 및 데이터 관리",
title = stringResource(R.string.onboarding_terms_detail_section_4_title),
content = stringResource(R.string.onboarding_terms_detail_section_4),
)
TermsSectionText(
title = "5. 서비스 변경 및 종료",
title = stringResource(R.string.onboarding_terms_detail_section_5_title),
content = stringResource(R.string.onboarding_terms_detail_section_5),
)
TermsSectionText(
title = "6. 동의 철회",
title = stringResource(R.string.onboarding_terms_detail_section_6_title),
content = stringResource(R.string.onboarding_terms_detail_section_6),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,11 @@
<string name="onboarding_profile_headline">애프터노트에서의\n프로필을 설정해주세요</string>
<string name="onboarding_profile_name_placeholder">이름을 지정해주세요</string>
<string name="onboarding_profile_complete">회원가입 완료</string>
<!-- 약관 상세. 본문(onboarding_terms_detail_section_N)은 리소스였는데 제목만 코드에 남아 있었다. -->
<string name="onboarding_terms_detail_section_1_title">1. 서비스 이용약관</string>
<string name="onboarding_terms_detail_section_2_title">2. 개인정보 수집 및 이용 동의</string>
<string name="onboarding_terms_detail_section_3_title">3. 기록 및 콘텐츠 저장에 대한 안내</string>
<string name="onboarding_terms_detail_section_4_title">4. 계정 및 데이터 관리</string>
<string name="onboarding_terms_detail_section_5_title">5. 서비스 변경 및 종료</string>
<string name="onboarding_terms_detail_section_6_title">6. 동의 철회</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ fun AfternoteSection(
description = stringResource(R.string.receiver_home_afternote_section_desc),
countLine =
rememberCountLine(
prefix = "${countText(totalCount)}개",
suffix = "의 애프터노트가 있습니다.",
prefix = stringResource(R.string.receiver_home_afternote_count_prefix, countText(totalCount)),
suffix = stringResource(R.string.receiver_home_afternote_count_suffix),
),
buttonText = stringResource(R.string.receiver_home_afternote_section_button),
onButtonClick = onGoClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ fun MindRecordSection(
description = stringResource(R.string.receiver_home_mindrecord_section_desc),
countLine =
rememberCountLine(
prefix = "${countText(summary?.totalCount)}개 ",
suffix = "마음의 기록이 있습니다.",
prefix =
stringResource(R.string.receiver_home_mindrecord_count_prefix, countText(summary?.totalCount)),
suffix = stringResource(R.string.receiver_home_mindrecord_count_suffix),
),
buttonText = stringResource(R.string.receiver_home_mindrecord_section_button),
onButtonClick = onGoClick,
Expand Down
Loading
Loading