Conversation
* fix: 저전력 모드 영상 재생 대응 * fix: 저전력 모드 시 유튜브 재생 안됨 이슈 개선 * feat(FeedSection): 피드색션의 프로필카드 라우팅 추가 * feat: 팬덤,PICKS 바텀시트 추가 * feat(SocialMyCollectionDiary): 좋아요, 스크랩 기능 추가 * feat(FeedSection): 좋아요, 스크랩 refetch 추가 * feat(SocialMyCollectionDiary): 다이어리 페이지 좋아요,스크랩 refetch 추가 * feat: 좋아요목록 api연동 * feat(FriendSection): 나의 픽/나의 팬덤 UI 업데이트 * feat(FeedSection): 신고하기 API 연동 및 UI 구성 * feat(SocialFeedPageCardView): 신고하기 UI 업데이트 * fix: 신고하기 아이콘 변경 * feat(MyCollection): 팬덤/PICKS/좋아요 목록 바텀시트 추가 * feat(FeedSection): 좋아요, 스크랩 피드백 UI 추가 * feat(SocialFeed): 프로필 가장자리 색상 추가 스크롤 부분 킬링파트 일기 부분만 적용 * feat(1.1.1): 버전 업데이트
There was a problem hiding this comment.
Pull request overview
This PR updates the Social/My experiences for v1.1.1 by improving YouTube playback resiliency (incl. focus/active-state handling), adding new social interaction surfaces (like-users list, report), and enabling richer navigation between user collections.
Changes:
- Add “active/focus” propagation (
isRootTabSelected/isParentActive+playbackFocusToken) to stabilize/refresh playback when tabs/screens regain focus. - Add new sheets and interactions: like-users bottom sheet (search + pagination), diary report sheet, and fan/picks connection list sheets.
- Add navigation entry points to other users’ collections (from feed profile taps and from list sheets).
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| KillingPart/Views/Screens/Main/Social/SocialView.swift | Passes active-state down to feed section and injects collection VM factory. |
| KillingPart/Views/Screens/Main/Social/Shared/Components/SocialDiaryLikeUsersSheet.swift | New reusable bottom sheet UI for like-user listing + search/pagination states. |
| KillingPart/Views/Screens/Main/Social/FriendsSection/SocialMyCollection/[userId]/SocialMyCollectionView.swift | Adds fan/picks connection sheets and user-to-user collection navigation. |
| KillingPart/Views/Screens/Main/Social/FriendsSection/SocialMyCollection/[userId]/components/SocialMyCollectionProfileCard.swift | Makes fan/picks stat items tappable via injected callbacks. |
| KillingPart/Views/Screens/Main/Social/FriendsSection/SocialMyCollection/[userId]/[diaryId]/SocialMyCollectionDiary.swift | Adds toolbar like/store + like-users sheet + interaction refresh on focus. |
| KillingPart/Views/Screens/Main/Social/FriendsSection/FriendsSectionView.swift | Minor layout alignment adjustment. |
| KillingPart/Views/Screens/Main/Social/FriendsSection/Components/SocialFriendToggleTabsView.swift | Updates toggle tab styling/layout. |
| KillingPart/Views/Screens/Main/Social/FeedSection/FeedSectionView.swift | Adds navigation to profile, like-users/report sheets, interaction feedback overlay, focus-based playback control. |
| KillingPart/Views/Screens/Main/Social/FeedSection/Components/SocialFeedProfileView.swift | Adds profile image highlight stroke. |
| KillingPart/Views/Screens/Main/Social/FeedSection/Components/SocialFeedPageCardView.swift | Adds profile tap, like long-press, report menu, focused playback token, and scrollable diary subsection. |
| KillingPart/Views/Screens/Main/Social/FeedSection/Components/SocialDiaryReportSheet.swift | New report bottom sheet with validation + submission state UI. |
| KillingPart/Views/Screens/Main/My/PlayKillingPart/PlayKillingPartView.swift | Adds parent-active gating and focus token to improve playback stability. |
| KillingPart/Views/Screens/Main/My/PlayKillingPart/components/PlayKillingPartCurrentTrackContent.swift | Threads playback focus token into the player. |
| KillingPart/Views/Screens/Main/My/MyTabView.swift | Passes root-tab active state into PlayKillingPartView. |
| KillingPart/Views/Screens/Main/My/MyCollection/MyCollectionView.swift | Adds connection sheets + like-users sheet + navigation to other collections. |
| KillingPart/Views/Screens/Main/My/MyCollection/Components/ProfileCard/MyCollectionProfileCard.swift | Makes fan/picks stats tappable via callbacks. |
| KillingPart/Views/Screens/Main/My/MyCollection/Components/FeedCard/MyCollectionFeedCard.swift | Adds long-press gesture hook on like badge for like-users sheet entry. |
| KillingPart/Views/Screens/Main/My/MyCollection/[diaryId]/components/MyCollectionDiaryVideoSection.swift | Passes focus token into YoutubePlayerView to force recovery/seek on focus changes. |
| KillingPart/Views/Screens/Main/MainTabView.swift | Wires isRootTabSelected into My/Social tabs. |
| KillingPart/Views/Screens/Main/Add/AddSearchDetail/components/YoutubePlayerView.swift | Adds playback focus token + watchdog/retry JS + power/app-state observers for playback recovery. |
| KillingPart/Views/Screens/Main/Add/AddSearchDetail/components/AddSearchDetailVideoSection.swift | Supplies focus token to YoutubePlayerView during reloads. |
| KillingPart/ViewModels/Social/SocialViewModel.swift | Refactors collection VM creation to be reusable for multiple call sites. |
| KillingPart/ViewModels/Social/SocialMyCollectionViewModel.swift | Adds connection list loading/pagination and VM factory for nested navigation. |
| KillingPart/ViewModels/Social/FeedViewModel.swift | Adds like-users state, diary reporting, and interaction refresh on focus. |
| KillingPart/ViewModels/My/MyCollection/MyCollectionViewModel.swift | Adds connection list + like-users loading/pagination and shared subscribe service injection. |
| KillingPart/ViewModels/My/MyCollection/MyCollectionDiaryViewModel.swift | Adds interaction refresh, like/store toggles, and like-users loading/pagination for diary detail. |
| KillingPart/Services/DiaryService.swift | Adds like-users fetch endpoint, report endpoint, and improved server error message normalization. |
| KillingPart/Models/DiaryModel.swift | Adds request model for diary reporting payload. |
| KillingPart.xcodeproj/project.pbxproj | Bumps build/marketing versions and updates app category. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| private func applyAutoplayPolicyForCurrentPowerMode(forceSeek: Bool) { | ||
| guard let webView, let isPlaying = lastSyncedIsPlaying else { return } | ||
|
|
||
| let preferMutedAutoplay = false |
There was a problem hiding this comment.
applyAutoplayPolicyForCurrentPowerMode is called when Low Power Mode changes, but preferMutedAutoplay is currently hardcoded to false here (and also in updateUIView). This makes the Low Power Mode observer effectively a no-op for autoplay policy, which is likely not intended given the low-power playback issue being addressed. Consider deriving preferMutedAutoplay from ProcessInfo.processInfo.isLowPowerModeEnabled (or removing the observer/policy plumbing if muted autoplay is intentionally never used).
| let preferMutedAutoplay = false | |
| let preferMutedAutoplay = ProcessInfo.processInfo.isLowPowerModeEnabled |
| MyCollectionFeedLikeBadgeView(isLiked: feed.isLiked, likeCount: feed.likeCount) | ||
| .contentShape(Rectangle()) | ||
| .highPriorityGesture( | ||
| LongPressGesture(minimumDuration: 0.45) | ||
| .onEnded { _ in | ||
| onLikeLongPress() | ||
| } | ||
| ) |
There was a problem hiding this comment.
The long-press gesture on the like badge triggers onLikeLongPress(), but this card is used as the label of a NavigationLink (MyCollectionView.swift:213+). Without a tap-suppression mechanism, a long-press can still end up activating the navigation when the finger is released. Consider adding the same "ignore next tap" pattern used elsewhere (e.g., Social feed like button) or moving the long-press handling to the parent link to prevent unintended navigation.
| for _ in 0..<loadedPageCount { | ||
| let response = try await diaryService.fetchMyFeeds( | ||
| page: page, | ||
| size: DiaryService.defaultSize | ||
| ) |
There was a problem hiding this comment.
refreshLoadedFeedInteractionsIfNeeded refetches loadedPageCount pages sequentially via fetchMyFeeds (one network request per page). As the feed grows, returning focus to this screen can trigger a burst of network calls and delay UI responsiveness. Consider limiting refresh to the currently visible page/items, introducing an API that returns interaction states in bulk, or reducing the number of pages refreshed per activation.
| private let diaryService: DiaryServicing | ||
| private var isRefreshingInteractionState = false | ||
| private let maxRefreshScanPageCount = 100 | ||
| private let likeUsersPageSize = 20 | ||
| private var activeLikeUsersSearchCond: String? | ||
| private var likeUsersNextPage = DiaryService.defaultPage | ||
| private var hasNextLikeUsersPage = true | ||
| private var likeUsersRequestID = 0 |
There was a problem hiding this comment.
maxRefreshScanPageCount = 100 can lead to up to 100 paginated network calls when refreshing interaction state (see loops in findInteractionInUserFeeds/findInteractionInMyFeeds). Since this refresh runs on appear/foreground, it can be very expensive in poor network conditions. Consider lowering the cap, caching the last-known page for a diaryId, or adding a dedicated endpoint to fetch a diary's interaction state directly by diaryId.
업데이트 내용