feat(creator): FanTalk empty 위치를 보정한다

This commit is contained in:
2026-06-23 00:16:00 +09:00
parent 7e1e453a6b
commit 6ebd59ff9c
3 changed files with 70 additions and 45 deletions

View File

@@ -61,9 +61,8 @@ class CreatorChannelFanTalkFragment : BaseFragment<FragmentCreatorChannelFantalk
viewModel.refreshFanTalks() viewModel.refreshFanTalks()
} }
fun onCreatorChannelFanTalkViewportHeightChanged(minHeight: Int) { @Suppress("UNUSED_PARAMETER")
binding.root.minimumHeight = minHeight fun onCreatorChannelFanTalkViewportHeightChanged(minHeight: Int) = Unit
}
fun onCreatorChannelFanTalkDeleteConfirmed(fanTalkId: Long) { fun onCreatorChannelFanTalkDeleteConfirmed(fanTalkId: Long) {
viewModel.deleteFanTalk(fanTalkId) viewModel.deleteFanTalk(fanTalkId)

View File

@@ -50,59 +50,67 @@
tools:itemCount="3" tools:itemCount="3"
tools:listitem="@layout/item_creator_channel_fantalk" /> tools:listitem="@layout/item_creator_channel_fantalk" />
<LinearLayout <FrameLayout
android:id="@+id/layout_creator_channel_fantalk_empty" android:id="@+id/layout_creator_channel_fantalk_empty"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="wrap_content"
android:gravity="center" android:paddingTop="@dimen/spacing_48"
android:orientation="vertical" android:paddingBottom="@dimen/spacing_32"
android:paddingHorizontal="@dimen/spacing_14"
android:visibility="gone" android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"
tools:visibility="visible"> tools:visibility="visible">
<TextView <LinearLayout
android:id="@+id/tv_creator_channel_fantalk_empty_message" android:id="@+id/layout_creator_channel_fantalk_empty_content"
style="@style/Typography.Body3"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:gravity="center" android:gravity="center"
android:includeFontPadding="false" android:orientation="vertical"
android:lineSpacingMultiplier="1.45" android:paddingHorizontal="@dimen/spacing_14"
android:text="@string/creator_channel_fantalk_empty_message" tools:ignore="UselessParent">
android:textColor="@color/gray_500" />
<LinearLayout
android:id="@+id/layout_creator_channel_fantalk_empty_write_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginTop="@dimen/spacing_20"
android:background="@drawable/bg_creator_channel_fantalk_empty_button"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/spacing_12">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:contentDescription="@null"
android:src="@drawable/ic_new_fantalk_plus" />
<TextView <TextView
android:id="@+id/tv_creator_channel_fantalk_empty_write_button" android:id="@+id/tv_creator_channel_fantalk_empty_message"
style="@style/Typography.Body2" style="@style/Typography.Body3"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_4" android:gravity="center"
android:includeFontPadding="false" android:includeFontPadding="false"
android:text="@string/creator_channel_fantalk_support_action" android:lineSpacingMultiplier="1.45"
android:textColor="@color/white" /> android:text="@string/creator_channel_fantalk_empty_message"
android:textColor="@color/gray_500" />
<LinearLayout
android:id="@+id/layout_creator_channel_fantalk_empty_write_button"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_marginTop="@dimen/spacing_14"
android:background="@drawable/bg_creator_channel_fantalk_empty_button"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="@dimen/spacing_12">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:contentDescription="@null"
android:src="@drawable/ic_plus_no_bg" />
<TextView
android:id="@+id/tv_creator_channel_fantalk_empty_write_button"
style="@style/Typography.Body2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/spacing_6"
android:includeFontPadding="false"
android:text="@string/creator_channel_fantalk_support_action"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </FrameLayout>
<TextView <TextView
android:id="@+id/tv_creator_channel_fantalk_error_message" android:id="@+id/tv_creator_channel_fantalk_error_message"

View File

@@ -4,8 +4,10 @@ import android.app.Application
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.R
@@ -28,11 +30,16 @@ class CreatorChannelFanTalkFragmentLayoutTest {
fun `팬톡 fragment layout은 count list empty error retry floating write를 제공하고 sort UI는 제외한다`() { fun `팬톡 fragment layout은 count list empty error retry floating write를 제공하고 sort UI는 제외한다`() {
val root = inflateView(R.layout.fragment_creator_channel_fantalk) val root = inflateView(R.layout.fragment_creator_channel_fantalk)
val layout = projectFile("app/src/main/res/layout/fragment_creator_channel_fantalk.xml").readText() val layout = projectFile("app/src/main/res/layout/fragment_creator_channel_fantalk.xml").readText()
val emptyContainerBlock = layout
.substringAfter("<FrameLayout\n android:id=\"@+id/layout_creator_channel_fantalk_empty\"")
.substringBefore("</FrameLayout>")
val countBar = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_count_bar)) val countBar = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_count_bar))
val fanTalkList = requireNotNull(root.findViewById<RecyclerView>(R.id.rv_creator_channel_fantalk)) val fanTalkList = requireNotNull(root.findViewById<RecyclerView>(R.id.rv_creator_channel_fantalk))
val emptyContainer = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty)) val emptyContainer = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty))
val emptyContent = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty_content))
val emptyMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_empty_message)) val emptyMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_empty_message))
val emptyButton = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty_write_button)) val emptyButton = requireNotNull(root.findViewById<View>(R.id.layout_creator_channel_fantalk_empty_write_button))
val emptyButtonLabel = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_empty_write_button))
val errorMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_error_message)) val errorMessage = requireNotNull(root.findViewById<TextView>(R.id.tv_creator_channel_fantalk_error_message))
val retryButton = requireNotNull(root.findViewById<TextView>(R.id.btn_creator_channel_fantalk_retry)) val retryButton = requireNotNull(root.findViewById<TextView>(R.id.btn_creator_channel_fantalk_retry))
val floatingWriteButton = requireNotNull(root.findViewById<View>(R.id.btn_creator_channel_fantalk_write)) val floatingWriteButton = requireNotNull(root.findViewById<View>(R.id.btn_creator_channel_fantalk_write))
@@ -40,8 +47,9 @@ class CreatorChannelFanTalkFragmentLayoutTest {
assertSame(root, countBar.parent) assertSame(root, countBar.parent)
assertSame(root, fanTalkList.parent) assertSame(root, fanTalkList.parent)
assertSame(root, emptyContainer.parent) assertSame(root, emptyContainer.parent)
assertSame(emptyContainer, emptyMessage.parent) assertSame(emptyContainer, emptyContent.parent)
assertSame(emptyContainer, emptyButton.parent) assertSame(emptyContent, emptyMessage.parent)
assertSame(emptyContent, emptyButton.parent)
assertSame(root, errorMessage.parent) assertSame(root, errorMessage.parent)
assertSame(root, retryButton.parent) assertSame(root, retryButton.parent)
assertSame(root, floatingWriteButton.parent) assertSame(root, floatingWriteButton.parent)
@@ -54,11 +62,20 @@ class CreatorChannelFanTalkFragmentLayoutTest {
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_all_label\"")) assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_all_label\""))
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_empty_message\"")) assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_empty_message\""))
assertTrue(layout.contains("android:gravity=\"center\"")) assertTrue(layout.contains("android:gravity=\"center\""))
assertTrue(layout.contains("android:layout_height=\"0dp\"")) assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, emptyContainer.layoutParams.height)
assertTrue(layout.contains("app:layout_constraintBottom_toBottomOf=\"parent\"")) assertTrue(layout.contains("android:paddingTop=\"@dimen/spacing_48\""))
assertTrue(layout.contains("android:paddingBottom=\"@dimen/spacing_32\""))
assertTrue(layout.contains("android:layout_gravity=\"top|center_horizontal\""))
assertFalse(emptyContainerBlock.contains("app:layout_constraintBottom_toBottomOf=\"parent\""))
assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_support_action\"")) assertTrue(layout.contains("android:text=\"@string/creator_channel_fantalk_support_action\""))
assertTrue(layout.contains("android:layout_marginTop=\"@dimen/spacing_14\""))
assertTrue(layout.contains("android:background=\"@drawable/bg_creator_channel_fantalk_empty_button\""))
assertTrue(layout.contains("android:layout_marginStart=\"@dimen/spacing_6\""))
assertTrue(layout.contains("tools:listitem=\"@layout/item_creator_channel_fantalk\"")) assertTrue(layout.contains("tools:listitem=\"@layout/item_creator_channel_fantalk\""))
assertTrue(layout.contains("@drawable/ic_new_fantalk_plus")) assertTrue(layout.contains("@drawable/ic_new_fantalk_plus"))
assertEquals(ContextCompat.getColor(root.context, R.color.gray_500), emptyMessage.currentTextColor)
assertEquals(ContextCompat.getColor(root.context, R.color.white), emptyButtonLabel.currentTextColor)
assertTrue(projectFile("app/src/main/res/drawable/bg_creator_channel_fantalk_empty_button.xml").readText().contains("@color/gray_800"))
assertLocaleString("values/strings.xml", "아직 응원이 없습니다.\\n처음으로 크리에이터를 응원해 보세요!") assertLocaleString("values/strings.xml", "아직 응원이 없습니다.\\n처음으로 크리에이터를 응원해 보세요!")
assertLocaleString("values-en/strings.xml", "No cheers yet.\\nBe the first to cheer for the creator!") assertLocaleString("values-en/strings.xml", "No cheers yet.\\nBe the first to cheer for the creator!")
assertLocaleString("values-ja/strings.xml", "まだ応援がありません。\\n最初にクリエイターを応援してみましょう") assertLocaleString("values-ja/strings.xml", "まだ応援がありません。\\n最初にクリエイターを応援してみましょう")
@@ -157,7 +174,8 @@ class CreatorChannelFanTalkFragmentLayoutTest {
assertTrue(fragment.contains("onCreatorChannelFanTalkRefreshRequested()")) assertTrue(fragment.contains("onCreatorChannelFanTalkRefreshRequested()"))
assertTrue(fragment.contains("viewModel.refreshFanTalks()")) assertTrue(fragment.contains("viewModel.refreshFanTalks()"))
assertTrue(fragment.contains("onCreatorChannelFanTalkViewportHeightChanged(minHeight: Int)")) assertTrue(fragment.contains("onCreatorChannelFanTalkViewportHeightChanged(minHeight: Int)"))
assertTrue(fragment.contains("binding.root.minimumHeight = minHeight")) assertTrue(fragment.contains("@Suppress(\"UNUSED_PARAMETER\")"))
assertFalse(fragment.contains("binding.root.minimumHeight = minHeight"))
assertTrue(fragment.contains("onCreatorChannelFanTalkDeleteConfirmed(fanTalkId: Long)")) assertTrue(fragment.contains("onCreatorChannelFanTalkDeleteConfirmed(fanTalkId: Long)"))
assertTrue(fragment.contains("viewModel.deleteFanTalk(fanTalkId)")) assertTrue(fragment.contains("viewModel.deleteFanTalk(fanTalkId)"))
assertTrue(fragment.contains("CheersReportDialog(requireActivity(), layoutInflater)")) assertTrue(fragment.contains("CheersReportDialog(requireActivity(), layoutInflater)"))