Original 작품 상세 문자열 리소스화

This commit is contained in:
2025-12-01 17:37:36 +09:00
parent 73b2eba1f8
commit 2066dbc716
9 changed files with 101 additions and 47 deletions

View File

@@ -65,11 +65,4 @@ class OriginalWorkViewModel(
}) })
) )
} }
fun refresh() {
page = 0
isLast = false
_items.value = emptyList()
loadMore()
}
} }

View File

@@ -33,8 +33,13 @@ class OriginalWorkDetailActivity : BaseActivity<ActivityOriginalWorkDetailBindin
val originalId = intent.getLongExtra(EXTRA_ORIGINAL_ID, -1) val originalId = intent.getLongExtra(EXTRA_ORIGINAL_ID, -1)
if (originalId <= 0) { if (originalId <= 0) {
Toast.makeText(applicationContext, "잘못된 요청입니다.", Toast.LENGTH_LONG).show() Toast.makeText(
applicationContext,
getString(R.string.original_detail_error_invalid_request),
Toast.LENGTH_LONG
).show()
finish() finish()
return
} }
bind() bind()
@@ -62,8 +67,12 @@ class OriginalWorkDetailActivity : BaseActivity<ActivityOriginalWorkDetailBindin
private fun setupTabs() { private fun setupTabs() {
val tabs = binding.tabs val tabs = binding.tabs
tabs.addTab(tabs.newTab().setText("캐릭터").setTag("character")) tabs.addTab(
tabs.addTab(tabs.newTab().setText("작품정보").setTag("info")) tabs.newTab().setText(R.string.screen_original_detail_tab_character).setTag("character")
)
tabs.addTab(
tabs.newTab().setText(R.string.screen_original_detail_tab_info).setTag("info")
)
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) { override fun onTabSelected(tab: TabLayout.Tab) {
@@ -101,7 +110,13 @@ class OriginalWorkDetailActivity : BaseActivity<ActivityOriginalWorkDetailBindin
private fun bind() { private fun bind() {
viewModel.toast.observe(this) { viewModel.toast.observe(this) {
it?.let { Toast.makeText(applicationContext, it, Toast.LENGTH_LONG).show() } it?.let { uiText ->
Toast.makeText(
applicationContext,
uiText.asString(this),
Toast.LENGTH_LONG
).show()
}
} }
viewModel.isLoading.observe(this) { viewModel.isLoading.observe(this) {

View File

@@ -4,11 +4,12 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.base.BaseViewModel import kr.co.vividnext.sodalive.base.BaseViewModel
import kr.co.vividnext.sodalive.chat.character.Character
import kr.co.vividnext.sodalive.chat.original.OriginalWorkDetailResponse import kr.co.vividnext.sodalive.chat.original.OriginalWorkDetailResponse
import kr.co.vividnext.sodalive.chat.original.OriginalWorkRepository import kr.co.vividnext.sodalive.chat.original.OriginalWorkRepository
import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.common.UiText
class OriginalWorkDetailViewModel( class OriginalWorkDetailViewModel(
private val repository: OriginalWorkRepository private val repository: OriginalWorkRepository
@@ -17,8 +18,8 @@ class OriginalWorkDetailViewModel(
private val _isLoading = MutableLiveData(false) private val _isLoading = MutableLiveData(false)
val isLoading: LiveData<Boolean> get() = _isLoading val isLoading: LiveData<Boolean> get() = _isLoading
private val _toast = MutableLiveData<String?>(null) private val _toast = MutableLiveData<UiText?>(null)
val toast: LiveData<String?> get() = _toast val toast: LiveData<UiText?> get() = _toast
private val _detail = MutableLiveData<OriginalWorkDetailResponse?>(null) private val _detail = MutableLiveData<OriginalWorkDetailResponse?>(null)
val detail: LiveData<OriginalWorkDetailResponse?> get() = _detail val detail: LiveData<OriginalWorkDetailResponse?> get() = _detail
@@ -41,12 +42,14 @@ class OriginalWorkDetailViewModel(
detailResponse = data detailResponse = data
_detail.value = detailResponse _detail.value = detailResponse
} else { } else {
_toast.value = response.message ?: "알 수 없는 오류가 발생했습니다." _toast.value = response.message?.let { UiText.DynamicString(it) }
?: UiText.StringResource(R.string.common_error_unknown)
} }
_isLoading.value = false _isLoading.value = false
}, { e -> }, { e ->
_isLoading.value = false _isLoading.value = false
_toast.value = e.message ?: "알 수 없는 오류가 발생했습니다." _toast.value = e.message?.let { UiText.DynamicString(it) }
?: UiText.StringResource(R.string.common_error_unknown)
}) })
) )
} }

View File

@@ -12,6 +12,7 @@ import androidx.core.view.isVisible
import kr.co.vividnext.sodalive.base.BaseFragment import kr.co.vividnext.sodalive.base.BaseFragment
import kr.co.vividnext.sodalive.chat.original.OriginalWorkDetailResponse import kr.co.vividnext.sodalive.chat.original.OriginalWorkDetailResponse
import kr.co.vividnext.sodalive.databinding.FragmentOriginalWorkInfoBinding import kr.co.vividnext.sodalive.databinding.FragmentOriginalWorkInfoBinding
import kr.co.vividnext.sodalive.R
class OriginalWorkInfoFragment : BaseFragment<FragmentOriginalWorkInfoBinding>( class OriginalWorkInfoFragment : BaseFragment<FragmentOriginalWorkInfoBinding>(
FragmentOriginalWorkInfoBinding::inflate FragmentOriginalWorkInfoBinding::inflate
@@ -106,7 +107,10 @@ class OriginalWorkInfoFragment : BaseFragment<FragmentOriginalWorkInfoBinding>(
binding.tvOriginalWork.setBackgroundResource(outValue.resourceId) binding.tvOriginalWork.setBackgroundResource(outValue.resourceId)
} }
// 접근성 설명 // 접근성 설명
binding.tvOriginalWork.contentDescription = "원작 $originalWork 링크 열기" binding.tvOriginalWork.contentDescription = getString(
R.string.original_detail_link_content_description,
originalWork
)
binding.tvOriginalWork.setOnClickListener { binding.tvOriginalWork.setOnClickListener {
openUrl(originalLink) openUrl(originalLink)
@@ -156,7 +160,7 @@ class OriginalWorkInfoFragment : BaseFragment<FragmentOriginalWorkInfoBinding>(
if (!host.isNullOrBlank()) host else url if (!host.isNullOrBlank()) host else url
} catch (_: Exception) { } catch (_: Exception) {
// 파싱 실패 시 간단한 레이블 제공 // 파싱 실패 시 간단한 레이블 제공
"링크 ${index + 1}" getString(R.string.original_detail_link_fallback, index + 1)
} }
} }

View File

@@ -19,7 +19,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/pretendard_bold" android:fontFamily="@font/pretendard_bold"
android:text="작품 소개" android:text="@string/original_work_info_section_title"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -36,8 +36,8 @@
app:ellipsizeTextColor="@color/white" app:ellipsizeTextColor="@color/white"
app:expandType="layout" app:expandType="layout"
app:isExpanded="false" app:isExpanded="false"
app:readLessText="간략히" app:readLessText="@string/read_less"
app:readMoreText="전체보기" app:readMoreText="@string/read_more"
app:textMode="line" app:textMode="line"
tools:text="특별한 꽃을 길러낼 수 있는 능력을 가진 리엘라.\n그녀는 호손 공작의 상속자가 되고 말아버리는데...\n생각하지도 못했던 상속에 당황한 리엘라의 앞에 왕의 동생이자 보석술사인 하운 대공이 나타난다.\n바로 그녀의 특별한 ‘능력’ 때문에!\n\n꽃집 소녀 리엘라의 우당탕탕 공작 상속기!\n두 명의 상속인" /> tools:text="특별한 꽃을 길러낼 수 있는 능력을 가진 리엘라.\n그녀는 호손 공작의 상속자가 되고 말아버리는데...\n생각하지도 못했던 상속에 당황한 리엘라의 앞에 왕의 동생이자 보석술사인 하운 대공이 나타난다.\n바로 그녀의 특별한 ‘능력’ 때문에!\n\n꽃집 소녀 리엘라의 우당탕탕 공작 상속기!\n두 명의 상속인" />
</LinearLayout> </LinearLayout>
@@ -55,7 +55,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/pretendard_bold" android:fontFamily="@font/pretendard_bold"
android:text="원작 보러 가기" android:text="@string/original_work_info_link_title"
android:textColor="#B0BEC5" android:textColor="#B0BEC5"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -85,7 +85,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/pretendard_bold" android:fontFamily="@font/pretendard_bold"
android:text="상세 정보" android:text="@string/original_work_info_detail_title"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="16sp" /> android:textSize="16sp" />
@@ -105,13 +105,13 @@
<!-- 작가 라벨/내용 --> <!-- 작가 라벨/내용 -->
<TextView <TextView
android:id="@+id/tv_label_writer" android:id="@+id/tv_label_writer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:fontFamily="@font/pretendard_regular" android:fontFamily="@font/pretendard_regular"
android:text="작가" android:text="@string/original_work_info_label_writer"
android:textColor="#B0BEC5" android:textColor="#B0BEC5"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
@@ -131,14 +131,14 @@
<!-- 제작사 라벨/내용 --> <!-- 제작사 라벨/내용 -->
<TextView <TextView
android:id="@+id/tv_label_studio" android:id="@+id/tv_label_studio"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:fontFamily="@font/pretendard_regular" android:fontFamily="@font/pretendard_regular"
android:text="제작사" android:text="@string/original_work_info_label_studio"
android:textColor="#B0BEC5" android:textColor="#B0BEC5"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_label_writer" /> app:layout_constraintTop_toBottomOf="@id/tv_label_writer" />
<TextView <TextView
@@ -158,14 +158,14 @@
<!-- 원작 라벨/내용 --> <!-- 원작 라벨/내용 -->
<TextView <TextView
android:id="@+id/tv_label_original" android:id="@+id/tv_label_original"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:fontFamily="@font/pretendard_regular" android:fontFamily="@font/pretendard_regular"
android:text="원작" android:text="@string/original_work_info_label_original"
android:textColor="#B0BEC5" android:textColor="#B0BEC5"
android:textSize="14sp" android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_label_studio" /> app:layout_constraintTop_toBottomOf="@id/tv_label_studio" />
<TextView <TextView

View File

@@ -29,7 +29,7 @@
android:gravity="center" android:gravity="center"
android:includeFontPadding="false" android:includeFontPadding="false"
android:maxLines="1" android:maxLines="1"
android:text="N" android:text="@string/original_work_label_new"
android:textColor="@color/white" android:textColor="@color/white"
android:textSize="18sp" android:textSize="18sp"
android:visibility="gone" android:visibility="gone"

View File

@@ -166,6 +166,19 @@
<string name="common_error_unknown">An unknown error occurred. Please try again.</string> <string name="common_error_unknown">An unknown error occurred. Please try again.</string>
<string name="common_error_request">An error occurred while processing the request.</string> <string name="common_error_request">An error occurred while processing the request.</string>
<string name="common_error_network_retry">A network error occurred. Please try again later.</string> <string name="common_error_network_retry">A network error occurred. Please try again later.</string>
<!-- Original detail -->
<string name="screen_original_detail_tab_character">Characters</string>
<string name="screen_original_detail_tab_info">Work info</string>
<string name="original_detail_error_invalid_request">Invalid request.</string>
<string name="original_detail_link_content_description">Open original work %1$s link</string>
<string name="original_detail_link_fallback">Link %1$d</string>
<string name="original_work_info_section_title">About the work</string>
<string name="original_work_info_link_title">View original</string>
<string name="original_work_info_detail_title">Details</string>
<string name="original_work_info_label_writer">Writer</string>
<string name="original_work_info_label_studio">Studio</string>
<string name="original_work_info_label_original">Original work</string>
<string name="original_work_label_new">N</string>
<!-- Character detail --> <!-- Character detail -->
<string name="screen_character_detail_title">Character info</string> <string name="screen_character_detail_title">Character info</string>
<string name="screen_character_detail_tab_info">Details</string> <string name="screen_character_detail_tab_info">Details</string>

View File

@@ -166,6 +166,19 @@
<string name="common_error_unknown">不明なエラーが発生しました。もう一度お試しください。</string> <string name="common_error_unknown">不明なエラーが発生しました。もう一度お試しください。</string>
<string name="common_error_request">リクエスト処理中にエラーが発生しました。</string> <string name="common_error_request">リクエスト処理中にエラーが発生しました。</string>
<string name="common_error_network_retry">ネットワークエラーが発生しました。しばらくしてから再試行してください。</string> <string name="common_error_network_retry">ネットワークエラーが発生しました。しばらくしてから再試行してください。</string>
<!-- Original detail -->
<string name="screen_original_detail_tab_character">キャラクター</string>
<string name="screen_original_detail_tab_info">作品情報</string>
<string name="original_detail_error_invalid_request">無効なリクエストです。</string>
<string name="original_detail_link_content_description">原作%1$sのリンクを開く</string>
<string name="original_detail_link_fallback">リンク %1$d</string>
<string name="original_work_info_section_title">作品紹介</string>
<string name="original_work_info_link_title">原作を見に行く</string>
<string name="original_work_info_detail_title">詳細情報</string>
<string name="original_work_info_label_writer">作家</string>
<string name="original_work_info_label_studio">制作会社</string>
<string name="original_work_info_label_original">原作</string>
<string name="original_work_label_new">N</string>
<!-- Character detail --> <!-- Character detail -->
<string name="screen_character_detail_title">キャラクター情報</string> <string name="screen_character_detail_title">キャラクター情報</string>
<string name="screen_character_detail_tab_info">詳細</string> <string name="screen_character_detail_tab_info">詳細</string>

View File

@@ -165,6 +165,19 @@
<string name="common_error_unknown">알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.</string> <string name="common_error_unknown">알 수 없는 오류가 발생했습니다. 다시 시도해 주세요.</string>
<string name="common_error_request">요청 중 오류가 발생했습니다.</string> <string name="common_error_request">요청 중 오류가 발생했습니다.</string>
<string name="common_error_network_retry">네트워크 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.</string> <string name="common_error_network_retry">네트워크 오류가 발생했습니다. 잠시 후 다시 시도해 주세요.</string>
<!-- Original detail -->
<string name="screen_original_detail_tab_character">캐릭터</string>
<string name="screen_original_detail_tab_info">작품 정보</string>
<string name="original_detail_error_invalid_request">잘못된 요청입니다.</string>
<string name="original_detail_link_content_description">원작 %1$s 링크 열기</string>
<string name="original_detail_link_fallback">링크 %1$d</string>
<string name="original_work_info_section_title">작품 소개</string>
<string name="original_work_info_link_title">원작 보러 가기</string>
<string name="original_work_info_detail_title">상세 정보</string>
<string name="original_work_info_label_writer">작가</string>
<string name="original_work_info_label_studio">제작사</string>
<string name="original_work_info_label_original">원작</string>
<string name="original_work_label_new">N</string>
<!-- Character detail --> <!-- Character detail -->
<string name="screen_character_detail_title">캐릭터 정보</string> <string name="screen_character_detail_title">캐릭터 정보</string>
<string name="screen_character_detail_tab_info">상세</string> <string name="screen_character_detail_tab_info">상세</string>