From 9b115f3339c24b994928b8326a442925b96d6808 Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Mon, 13 Jul 2026 16:15:19 +0900 Subject: [PATCH] =?UTF-8?q?fix(main):=20=ED=8C=94=EB=A1=9C=EC=9E=89=20?= =?UTF-8?q?=EB=B9=88=20=EC=84=B9=EC=85=98=EC=9D=84=20=EC=88=A8=EA=B8=B4?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SodaLive/Sources/I18n/I18n.swift | 6 ++-- .../MainHomeFollowingEmptyStateView.swift | 2 +- .../Following/MainHomeFollowingView.swift | 12 ++++--- docs/20260630_메인_홈_팔로잉_탭/plan-task.md | 34 +++++++++++++++---- docs/20260630_메인_홈_팔로잉_탭/prd.md | 9 ++--- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/SodaLive/Sources/I18n/I18n.swift b/SodaLive/Sources/I18n/I18n.swift index b3c07ffd..984472f0 100644 --- a/SodaLive/Sources/I18n/I18n.swift +++ b/SodaLive/Sources/I18n/I18n.swift @@ -3255,9 +3255,9 @@ If you block this user, the following features will be restricted. enum HomeFollowing { static var emptyStateMessage: String { pick( - ko: "팔로잉 소식이 아직 없어요.\n관심 있는 크리에이터를 팔로우해 보세요.", - en: "No following updates yet.\nFollow creators you care about.", - ja: "フォロー中の新着情報はまだありません。\n気になるクリエイターをフォローしてみましょう。" + ko: "아직 팔로잉 소식이 없어요.\n관심 있는 크리에이터를 팔로우해 보세요.", + en: "There are no following updates yet.\nFollow creators you're interested in.", + ja: "まだフォロー中の新着情報がありません。\n気になるクリエイターをフォローしてみましょう。" ) } diff --git a/SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingEmptyStateView.swift b/SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingEmptyStateView.swift index 2042669e..f0e132e1 100644 --- a/SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingEmptyStateView.swift +++ b/SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingEmptyStateView.swift @@ -14,7 +14,7 @@ struct MainHomeFollowingEmptyStateView: View { Spacer() Text(message) - .appFont(.body5) + .appFont(.body3) .foregroundColor(Color.gray500) .multilineTextAlignment(.center) diff --git a/SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift b/SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift index 3c04ffee..6c43e55d 100644 --- a/SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift +++ b/SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift @@ -61,11 +61,13 @@ struct MainHomeFollowingView: View { } else if let response = viewModel.response { ScrollView(.vertical, showsIndicators: false) { VStack(spacing: 0) { - MainHomeFollowingCreatorSection( - followingCreators: response.followingCreators, - onTapCreator: onTapCreator, - onTapAll: onTapFollowingAll - ) + if !response.followingCreators.isEmpty { + MainHomeFollowingCreatorSection( + followingCreators: response.followingCreators, + onTapCreator: onTapCreator, + onTapAll: onTapFollowingAll + ) + } if !response.onAirLives.isEmpty { MainHomeFollowingLiveSection( diff --git a/docs/20260630_메인_홈_팔로잉_탭/plan-task.md b/docs/20260630_메인_홈_팔로잉_탭/plan-task.md index 21d28bef..83c82392 100644 --- a/docs/20260630_메인_홈_팔로잉_탭/plan-task.md +++ b/docs/20260630_메인_홈_팔로잉_탭/plan-task.md @@ -17,9 +17,9 @@ - 여러 화면에서 재사용할 근거가 생기기 전까지 팔로잉 전용 UI는 `SodaLive/Sources/V2/Main/Home/Following/Components/**`에 둔다. - 기존 추천/랭킹 탭의 `TargetType`, Repository, ViewModel, `ApiResponse` 디코딩 패턴을 따른다. - 홈 상단 `팔로잉` 탭 터치 시 로그인 guard를 먼저 적용한다. 비로그인 상태에서는 탭 전환과 API 호출을 하지 않고 로그인 화면으로 이동한다. -- 팔로잉 탭 전체 empty 문구는 `팔로잉 소식이 아직 없어요.\n관심 있는 크리에이터를 팔로우해 보세요.`를 사용한다. +- 팔로잉 탭 전체 empty 문구는 `팔로잉 소식이 아직 없어요.\n관심 있는 크리에이터를 팔로우해 보세요.`를 사용하고 `I18n.HomeFollowing.emptyStateMessage`로 다국어 처리한다. - API 실패 문구는 `팔로잉 정보를 불러오지 못했습니다.\n잠시 후 다시 시도해 주세요.`를 사용한다. -- 섹션별 배열이 비어 있으면 해당 섹션은 숨긴다. +- 섹션별 배열이 비어 있으면 해당 섹션은 숨긴다. 팔로잉 크리에이터 섹션도 예외 없이 `followingCreators`가 비어 있으면 `전체` 버튼까지 함께 숨긴다. - 모든 뷰의 루트 container와 섹션 container에는 불필요한 고정 숫자 width/height를 사용하지 않는다. - 프로필 이미지, 썸네일, 아이콘, tag, 최소 터치 영역처럼 UI 의미상 크기가 정해진 요소에만 고정 크기를 사용한다. - 외부 라이브러리는 추가하지 않는다. @@ -183,15 +183,15 @@ - `followingCreators`를 가로 스크롤 목록으로 표시한다. - 각 creator item은 프로필 이미지와 닉네임을 표시한다. - creator item 탭 시 `onTapCreator(creatorId)`를 호출한다. - - 목록 마지막에는 항상 `전체` 버튼을 표시한다. - - `전체` 버튼은 `followingCreators`가 비어 있어도 표시한다. + - `followingCreators`가 비어 있으면 섹션을 렌더링하지 않는다. + - 목록 마지막에는 `followingCreators`가 있을 때만 `전체` 버튼을 표시한다. - `전체` 버튼 text는 `I18n.HomeFollowing.allButtonTitle`, 색상은 `Color.soda400`을 사용한다. - `전체` 버튼 horizontal padding은 16으로 둔다. - `전체` 버튼 높이는 creator item 높이와 동일하게 맞춘다. - `전체` 버튼 탭 시 `onTapAll()`을 호출한다. - 검증 기준: - 실행 명령: `rg "struct MainHomeFollowingCreatorSection|ScrollView\\(\\.horizontal|followingCreators|onTapCreator|onTapAll|allButtonTitle|Color.soda400|padding\\(\\.horizontal, 16\\)" SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingCreatorSection.swift` - - 기대 결과: 가로 creator 목록과 마지막 `전체` 버튼 요구사항이 확인된다. + - 기대 결과: 가로 creator 목록, 비어 있을 때 섹션 숨김, 마지막 `전체` 버튼 요구사항이 확인된다. - [x] **Task 3.2: 전체 팔로잉 목록 진입 연결** - 대상 파일: @@ -480,7 +480,7 @@ - 작업 내용: - 비로그인 상태에서 홈 `팔로잉` 탭을 탭하면 로그인 화면으로 이동하는지 확인한다. - 로그인 상태에서 홈 `팔로잉` 탭 진입 시 API 호출과 섹션 표시가 동작하는지 확인한다. - - 팔로잉 크리에이터 섹션 마지막에 `전체` 버튼이 항상 표시되는지 확인한다. + - 팔로잉 크리에이터가 있으면 섹션 마지막에 `전체` 버튼이 표시되고, 팔로잉 크리에이터가 없으면 섹션과 `전체` 버튼이 표시되지 않는지 확인한다. - `전체` 버튼 text color가 `Color.soda400`로 보이는지 확인한다. - `CREATOR_RANKING`, `CONTENT_RANKING`, `COMMUNITY_POST`, `AUDIO_CONTENT`, `PHOTO_CONTENT`가 타입별 UI로 표시되는지 확인한다. - 루트/섹션 container가 고정 width/height 때문에 작은 화면에서 깨지지 않는지 확인한다. @@ -515,6 +515,23 @@ - 실행 명령: `rg "onTapCommunityPost|handleRecommendationCommunityPostTap|creatorChannelCommunityPostDetail|CommunityPostCard" SodaLive/Sources/V2/Main/Home/Following SodaLive/Sources/V2/Main/Home/MainHomeView.swift SodaLive/Sources/V2/Main/MainView.swift` - 기대 결과: 최근 소식 `COMMUNITY_POST` card tap이 기존 커뮤니티 게시글 상세 route로 연결된다. +### Phase 14: 팔로잉 크리에이터 빈 섹션 후속 정리 + +- [x] **Task 14.1: 팔로잉 크리에이터 빈 섹션과 전체 버튼 숨김** + - 대상 파일: + - 수정: `docs/20260630_메인_홈_팔로잉_탭/prd.md` + - 수정: `docs/20260630_메인_홈_팔로잉_탭/plan-task.md` + - 수정: `SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift` + - 확인: `SodaLive/Sources/I18n/I18n.swift` + - 작업 내용: + - 전체 empty 문구가 `I18n.HomeFollowing.emptyStateMessage`로 다국어 처리되어 있음을 확인한다. + - 기존 문서의 “크리에이터가 없어도 `전체` 버튼 표시” 요구를 “크리에이터가 있을 때만 섹션과 `전체` 버튼 표시”로 갱신한다. + - `MainHomeFollowingView`에서 `response.followingCreators`가 비어 있으면 `MainHomeFollowingCreatorSection`을 렌더링하지 않는다. + - 검증 기준: + - 실행 명령: `rg "emptyStateMessage|팔로잉 소식이 아직 없어요|No following updates yet|フォロー中の新着情報" SodaLive/Sources/I18n/I18n.swift` + - 실행 명령: `rg "if !response\\.followingCreators\\.isEmpty|MainHomeFollowingCreatorSection" SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift` + - 기대 결과: empty 문구의 ko/en/ja 다국어 처리와 팔로잉 크리에이터 빈 배열 시 섹션 렌더링 차단이 확인된다. + ## 검증 기록 - 2026-06-30: `docs/agent-guides/documentation-policy.md`, `build-test-verification.md`, `code-style.md`를 확인해 계획 문서 경로, Phase/checklist 형식, 검증 명령 기준을 반영했다. @@ -610,3 +627,8 @@ - 2026-07-12: `git diff --check -- SodaLive/Sources/V2/Main/Home/Following/Components/MainHomeFollowingNewsSection.swift SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift SodaLive/Sources/V2/Main/Home/MainHomeView.swift docs/20260630_메인_홈_팔로잉_탭/prd.md docs/20260630_메인_홈_팔로잉_탭/plan-task.md` 실행 결과 출력 없이 종료되어 변경 파일 공백 오류가 없음을 확인했다. - 2026-07-12: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug -derivedDataPath "/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/SodaLiveDerivedDataFollowingCommunityPost" build`는 로컬에 team `3A8QGPMRXM`용 iOS Development signing certificate이 없어 코드 서명 단계에서 실패했다. - 2026-07-12: `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug -destination "generic/platform=iOS Simulator" -derivedDataPath "/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/SodaLiveDerivedDataFollowingCommunityPostSimulator" CODE_SIGNING_ALLOWED=NO build`는 의존성 컴파일 중 600초 제한으로 `BUILD INTERRUPTED`되어 완료 여부를 확인하지 못했다. +- 2026-07-13: 사용자 요청에 따라 전체 empty 문구가 `I18n.HomeFollowing.emptyStateMessage`로 ko/en/ja 다국어 처리되어 있음을 `rg "emptyStateMessage|팔로잉 소식이 아직 없어요|No following updates yet|フォロー中の新着情報" SodaLive/Sources/I18n/I18n.swift`로 확인했다. +- 2026-07-13: `MainHomeFollowingView`에서 `response.followingCreators`가 비어 있으면 `MainHomeFollowingCreatorSection`을 렌더링하지 않도록 수정해, 팔로잉 크리에이터가 없을 때 상단 `전체` 버튼도 표시되지 않게 했다. +- 2026-07-13: PRD와 plan-task의 기존 “크리에이터가 없어도 `전체` 버튼 표시” 요구사항을 “크리에이터가 있을 때만 섹션과 `전체` 버튼 표시”로 갱신했다. +- 2026-07-13: `git diff --check -- SodaLive/Sources/V2/Main/Home/Following/MainHomeFollowingView.swift docs/20260630_메인_홈_팔로잉_탭/prd.md docs/20260630_메인_홈_팔로잉_탭/plan-task.md` 실행 결과 출력 없이 종료되어 변경 파일 공백 오류가 없음을 확인했다. +- 2026-07-13: 샌드박스 안의 `xcodebuild`는 Xcode/CoreSimulator/DerivedData/SwiftPM 캐시 접근 제한으로 실패했으나, 승인 후 샌드박스 밖에서 `xcodebuild -workspace SodaLive.xcworkspace -scheme SodaLive -configuration Debug -destination generic/platform=iOS\ Simulator -derivedDataPath /private/tmp/SodaLiveDerivedDataFollowingEmpty CODE_SIGNING_ALLOWED=NO build`를 실행해 `BUILD SUCCEEDED`를 확인했다. 기존 duplicate build file/dependency scan warning과 `LiveRoomViewModel`의 unused variable warning은 남아 있으나 컴파일 오류는 없었다. diff --git a/docs/20260630_메인_홈_팔로잉_탭/prd.md b/docs/20260630_메인_홈_팔로잉_탭/prd.md index 7d4d0d14..89e90ede 100644 --- a/docs/20260630_메인_홈_팔로잉_탭/prd.md +++ b/docs/20260630_메인_홈_팔로잉_탭/prd.md @@ -26,7 +26,7 @@ Figma 전체 화면 기준 섹션 순서는 아래를 따른다. - 기존 V2 공용 컴포넌트와 추천/랭킹 탭 패턴을 우선 재사용한다. - 홈 상단 `팔로잉` 탭 터치 시 로그인 guard를 먼저 적용해 로그인된 사용자만 탭으로 이동한다. - `isLoginRequired == true`이면 팔로잉 기반 콘텐츠 대신 로그인 필요 상태를 표시하고, 사용자가 로그인 화면으로 이동할 수 있어야 한다. -- 팔로잉 크리에이터 섹션의 가로 목록 마지막 item에는 항상 `전체` 버튼을 추가한다. +- 팔로잉 크리에이터가 있을 때만 팔로잉 크리에이터 섹션을 표시하고, 가로 목록 마지막 item에는 `전체` 버튼을 추가한다. - 최근 소식은 `FollowingNewsType`별로 다른 View를 표시한다. - 각 섹션은 이후 `plan-task.md` 작성 시 Figma Design 기준 섹션당 1개의 Phase로 나눌 수 있도록 요구사항을 분리한다. - 뷰 전체는 반드시 필요한 경우를 제외하고 고정 숫자 width/height를 갖지 않는다. @@ -350,8 +350,8 @@ Figma 참조: - `followingCreators`를 가로 스크롤 목록으로 표시한다. - 각 item은 프로필 이미지와 크리에이터 닉네임을 표시한다. - 크리에이터 item 탭 시 `creatorId`로 기존 크리에이터 상세 화면에 진입한다. -- 목록 마지막 item에는 항상 `전체` 버튼을 추가한다. -- `전체` 버튼은 서버 데이터가 비어 있어도 표시한다. +- `followingCreators`가 비어 있으면 팔로잉 크리에이터 섹션을 표시하지 않는다. +- 목록 마지막 item에는 `followingCreators`가 있을 때만 `전체` 버튼을 추가한다. - `전체` 버튼의 width는 버튼이 차지하는 콘텐츠 크기 기준으로 잡고, 고정 화면 width를 강제하지 않는다. - `전체` 버튼 height는 크리에이터 item 높이와 동일하게 표시한다. - `전체` 버튼은 `paddingHorizontal = 16`을 적용한다. @@ -541,7 +541,8 @@ Figma 참조: - `isLoginRequired == false`이면 Figma 순서대로 팔로잉 크리에이터, On Air, 최근 대화, 이달의 스케줄, 최근 소식 섹션이 표시된다. - 비어 있는 섹션은 표시되지 않는다. - 모든 섹션 데이터가 비어 있으면 전체 empty state가 표시된다. -- 팔로잉 크리에이터 가로 목록 마지막에는 항상 `전체` 버튼이 표시된다. +- 팔로잉 크리에이터가 있으면 가로 목록 마지막에 `전체` 버튼이 표시된다. +- 팔로잉 크리에이터가 없으면 팔로잉 크리에이터 섹션과 `전체` 버튼은 표시되지 않는다. - `전체` 버튼은 크리에이터 item 높이와 동일하고, horizontal padding 16, `Color.soda400` 텍스트를 사용한다. - 최근 소식의 `CREATOR_RANKING`은 `creatorRanking` payload로 랭킹 소식 카드가 표시된다. - 최근 소식의 `CONTENT_RANKING`은 `contentRanking` payload로 랭킹 소식 카드가 표시된다.