Conversation
* feat(1.1.3): 버전 업데이트 * feat: 데이터 refetch 추가 * Merge pull request #74 from ApptiveDev/feat/72 feat - QA 반영
There was a problem hiding this comment.
Pull request overview
QA 요청사항을 반영해 소셜/추가 탭 UX를 개선하고(여백, 기본 탭, 더블탭 좋아요 피드백), 소셜 친구/팬덤 페이징과 iTunes 기반 음악 검색 로직을 보강한 변경입니다.
Changes:
- 소셜 탭 기본 진입을 피드 탭으로 변경하고, 친구/피드 화면의 하단 여백(인셋) 계산을 개선
- 더블탭 좋아요 + 공통 인터랙션 피드백(토스트) 오버레이/프리젠터 도입
- 소셜 구독/팬덤 페이징 보강 및 Add 탭 음악 검색(Spotify+iTunes 병합, iTunes 쿼리 변형) 개선
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| KillingPart/Views/Screens/Main/Social/SocialView.swift | 소셜 기본 탭을 피드로 변경, 친구 섹션 하단 인셋 전달, 루트 탭 선택 시 갱신 task 추가 |
| KillingPart/Views/Screens/Main/Social/Shared/Components/SocialInteractionFeedbackOverlay.swift | 좋아요/보관함 인터랙션 피드백 오버레이 + 프리젠터 신규 추가 |
| KillingPart/Views/Screens/Main/Social/FriendsSection/SocialMyCollection/[userId]/[diaryId]/SocialMyCollectionDiary.swift | 더블탭 좋아요/피드백 오버레이 적용, like/store 탭 핸들러 리팩터링 |
| KillingPart/Views/Screens/Main/Social/FriendsSection/FriendsSectionView.swift | 친구 리스트 하단 인셋 전달 및 pagination 트리거 가드 강화 |
| KillingPart/Views/Screens/Main/Social/FriendsSection/Components/SocialFriendListView.swift | 리스트 하단 인셋 반영 및 마지막 아이템 sentinel onAppear 추가 |
| KillingPart/Views/Screens/Main/Social/FeedSection/FeedSectionView.swift | 피드 인터랙션 피드백을 공통 프리젠터로 교체 + 더블탭 좋아요 처리 추가 |
| KillingPart/Views/Screens/Main/Social/FeedSection/Components/SocialFeedPageCardView.swift | 카드 전체 더블탭 제스처 콜백 추가 |
| KillingPart/Views/Screens/Main/MainTabView.swift | SocialViewModel/FeedViewModel을 탭 상위에서 유지하도록 소유권 변경 |
| KillingPart/Views/Screens/Main/Add/Components/AddTrackListView.swift | Add 트랙 리스트 하단 인셋 파라미터 추가 |
| KillingPart/Views/Screens/Main/Add/Components/AddSearchContentView.swift | AddTrackListView에 하단 인셋 전달 |
| KillingPart/Views/Screens/Main/Add/AddTabView.swift | 안전영역 기반 리스트 하단 인셋 계산/전달 |
| KillingPart/Views/Screens/Main/Add/AddSearchDetail/components/AddSearchDetailVideoCandidateSection.swift | “다른 검색 결과” 섹션 접기/펼치기 UI 추가 |
| KillingPart/Views/Screens/Main/Add/AddSearchDetail/AddSearchDetailView.swift | 비디오 후보 섹션 노출 로직 복구 |
| KillingPart/ViewModels/Social/SocialViewModel.swift | 구독/팬덤 pagination 복원/보강 및 자동 프리로드 로직 추가 |
| KillingPart/ViewModels/Add/AddTabViewModel.swift | Spotify+iTunes 병렬 검색/병합 및 중복 제거/에러 메시지 보강 |
| KillingPart/Services/ITunesService.swift | iTunes 검색 변형(쿼리/attribute/country/lang) 시도 및 결과 병합/중복 제거 |
| KillingPart.xcodeproj/project.pbxproj | 빌드/마케팅 버전 업데이트 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .simultaneousGesture( | ||
| TapGesture(count: 2) | ||
| .onEnded { | ||
| handleDoubleTapLike() | ||
| } | ||
| ) |
There was a problem hiding this comment.
TapGesture(count: 2) is attached via simultaneousGesture to the whole screen. If the user double-taps on the like button itself, the button’s single-tap action can still fire (often twice) in addition to handleDoubleTapLike(), causing multiple toggleLike() calls and ending up in the wrong like state/count. Consider using an exclusive/high-priority double-tap gesture (so subview taps don’t trigger) or scoping the double-tap area to non-interactive content only.
| private func handleLikeTap() { | ||
| guard !isLikeInteractionDisabled else { return } | ||
| let feedback: SocialInteractionFeedbackKind = viewModel.diary.isLiked ? .likeRemoved : .likeAdded | ||
| interactionFeedbackPresenter.show(feedback) | ||
| Task { | ||
| let isSuccess = await viewModel.toggleLike() | ||
| guard isSuccess else { return } | ||
| onDiaryUpdated?() | ||
| } |
There was a problem hiding this comment.
Interaction feedback is presented before the async toggleLike()/toggleStore() result is known. Since these methods return Bool for success, failures will still show “좋아요 했어요/보관함에 저장했어요” even though the state didn’t change. Show success feedback only after isSuccess is true (and optionally present a failure message when false), and apply the same pattern to the double-tap handler.
| .simultaneousGesture( | ||
| TapGesture(count: 2) | ||
| .onEnded { | ||
| onDoubleTap() | ||
| } |
There was a problem hiding this comment.
The card-level simultaneousGesture(TapGesture(count: 2)) can coexist with the like/store buttons’ tap gestures. Double-tapping on a button can trigger the button action (possibly twice) plus onDoubleTap(), leading to duplicate like requests and incorrect final state. Prefer an exclusive/high-priority double-tap gesture that prevents subview taps, or attach the double-tap recognizer only to a non-interactive overlay/background area.
| .simultaneousGesture( | |
| TapGesture(count: 2) | |
| .onEnded { | |
| onDoubleTap() | |
| } | |
| .highPriorityGesture( | |
| TapGesture(count: 2) | |
| .onEnded { | |
| onDoubleTap() | |
| }, | |
| including: .subviews |
| updateMyPickPaging(from: subscribeResponse, requestedPage: initialPage) | ||
| updateMyFandomPaging(from: subscriberResponse, requestedPage: initialPage) | ||
| hasLoadedInitialData = true | ||
| await preloadAllDefaultPagesIfNeeded() | ||
| } catch { |
There was a problem hiding this comment.
refreshDefaultLists() now awaits preloadAllDefaultPagesIfNeeded(), which loops pagination until hasNext... is false. This can trigger many back-to-back network requests on every refresh (and in the duplicate-content case can still issue multiple pages per attempt), delaying the UI and increasing backend load. Consider removing this preloading, limiting it to at most 1 extra page / only when the list doesn’t fill the viewport, or running it in a detached/background task so the initial refresh can complete quickly.
| .background(Color.white.opacity(0.08)) | ||
| .clipShape(RoundedRectangle(cornerRadius: 8)) | ||
| } | ||
| .buttonStyle(.plain) |
There was a problem hiding this comment.
The expand/collapse control is an icon-only button (chevron) with no accessibility label/value, so VoiceOver users won’t know what it does or its current state. Add an accessibilityLabel (e.g., “다른 검색 결과 펼치기/접기”) and consider an accessibilityValue reflecting isExpanded.
| .buttonStyle(.plain) | |
| .buttonStyle(.plain) | |
| .accessibilityLabel("다른 검색 결과 펼치기 또는 접기") | |
| .accessibilityValue(isExpanded ? "펼쳐짐" : "접힘") |
작업내용