diff --git a/Yattee/Services/Navigation/NavigationCoordinator.swift b/Yattee/Services/Navigation/NavigationCoordinator.swift index f4defc54..6a42c20c 100644 --- a/Yattee/Services/Navigation/NavigationCoordinator.swift +++ b/Yattee/Services/Navigation/NavigationCoordinator.swift @@ -120,6 +120,9 @@ final class NavigationCoordinator { /// Progress bar frame in screen coordinates (for gesture conflict resolution). var progressBarFrame: CGRect = .zero + /// Comments overlay frame in screen coordinates (for gesture conflict resolution). + var commentsFrame: CGRect = .zero + /// Current panscan value from UIKit pinch gesture (0.0 = fit, 1.0 = fill). /// Updated by ExpandedPlayerWindow's pinch gesture handler. var pinchPanscan: Double = 0.0 diff --git a/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift b/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift index be098197..3ef418d1 100644 --- a/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift +++ b/Yattee/Views/Player/ExpandedPlayerSheet+Layouts.swift @@ -481,6 +481,9 @@ extension ExpandedPlayerSheet { withTransaction(transaction) { isPortraitPanelVisible = false navigationCoordinator?.isPortraitPanelVisible = false + isCommentsExpanded = false + navigationCoordinator?.isCommentsExpanded = false + navigationCoordinator?.commentsFrame = .zero panelDragOffset = 0 videoYOffset = 0 // Reset offset (centerY is now the base) } diff --git a/Yattee/Views/Player/ExpandedPlayerSheet+VideoInfo.swift b/Yattee/Views/Player/ExpandedPlayerSheet+VideoInfo.swift index ce4d3948..a4ca8117 100644 --- a/Yattee/Views/Player/ExpandedPlayerSheet+VideoInfo.swift +++ b/Yattee/Views/Player/ExpandedPlayerSheet+VideoInfo.swift @@ -31,6 +31,7 @@ extension ExpandedPlayerSheet { /// Collapses the comments overlay. func collapseComments() { + navigationCoordinator?.commentsFrame = .zero // Use same animation as player sheet dismiss (0.3s, no bounce) withAnimation(.smooth(duration: 0.3)) { isCommentsExpanded = false diff --git a/Yattee/Views/Player/ExpandedPlayerSheet.swift b/Yattee/Views/Player/ExpandedPlayerSheet.swift index dcf99bc7..fed9f8e3 100644 --- a/Yattee/Views/Player/ExpandedPlayerSheet.swift +++ b/Yattee/Views/Player/ExpandedPlayerSheet.swift @@ -269,6 +269,23 @@ struct ExpandedPlayerSheet: View { } .opacity(isVisible ? 1 : 0) .allowsHitTesting(isVisible) + .background( + GeometryReader { commentsGeometry in + Color.clear + .onChange(of: commentsGeometry.frame(in: .global)) { _, newFrame in + if isCommentsExpanded { + navigationCoordinator?.commentsFrame = newFrame + } + } + .onChange(of: isCommentsExpanded) { _, expanded in + if expanded { + navigationCoordinator?.commentsFrame = commentsGeometry.frame(in: .global) + } else { + navigationCoordinator?.commentsFrame = .zero + } + } + } + ) } .ignoresSafeArea(edges: .bottom) } @@ -770,6 +787,7 @@ private struct PlayerEventHandlersModifier: ViewModifier { playerState?.commentsState = .idle playerState?.commentsContinuation = nil isCommentsExpanded = false + navigationCoordinator?.commentsFrame = .zero isPanelExpanded = false panelExpandOffset = 0 } diff --git a/Yattee/Views/Player/ExpandedPlayerWindow.swift b/Yattee/Views/Player/ExpandedPlayerWindow.swift index 2dfb611d..bd57c8a2 100644 --- a/Yattee/Views/Player/ExpandedPlayerWindow.swift +++ b/Yattee/Views/Player/ExpandedPlayerWindow.swift @@ -150,6 +150,8 @@ private final class DragToDismissGestureHandler: NSObject, UIGestureRecognizerDe var getProgressBarFrame: (() -> CGRect)? /// Returns true if a seek gesture is currently active (blocks pinch gesture) var isSeekGestureActive: (() -> Bool)? + /// Returns the comments overlay frame in screen coordinates (for gesture conflict resolution) + var getCommentsFrame: (() -> CGRect)? // Main window scaling callbacks (Apple Music-style effect) var onMainWindowScaleChanged: ((CGFloat) -> Void)? @@ -341,9 +343,17 @@ private final class DragToDismissGestureHandler: NSObject, UIGestureRecognizerDe return false } - // Don't begin dismiss gesture when comments are expanded (they handle their own dismiss) + // When comments are expanded, only block dismiss if touch is within comments frame if isCommentsExpanded?() == true { - return false + let commentsFrame = getCommentsFrame?() ?? .zero + if !commentsFrame.isEmpty { + let touchLocation = panGesture.location(in: nil) + if commentsFrame.contains(touchLocation) { + return false + } + } else { + return false // No frame info — fall back to blanket blocking + } } // Don't begin dismiss gesture when adjusting volume/brightness sliders @@ -840,6 +850,9 @@ final class ExpandedPlayerWindowManager { handler.isSeekGestureActive = { [weak self] in self?.appEnvironment?.navigationCoordinator.isSeekGestureActive ?? false } + handler.getCommentsFrame = { [weak self] in + self?.appEnvironment?.navigationCoordinator.commentsFrame ?? .zero + } // Main window scaling callbacks for interactive drag handler.onMainWindowScaleChanged = { [weak self] progress in guard let self else { return } diff --git a/Yattee/Views/Player/FloatingDetailsPanel.swift b/Yattee/Views/Player/FloatingDetailsPanel.swift index ddcc48e4..88c75828 100644 --- a/Yattee/Views/Player/FloatingDetailsPanel.swift +++ b/Yattee/Views/Player/FloatingDetailsPanel.swift @@ -495,6 +495,23 @@ struct FloatingDetailsPanel: View { } .opacity(expanded ? 1 : 0) .allowsHitTesting(expanded) + .background( + GeometryReader { commentsGeometry in + Color.clear + .onChange(of: commentsGeometry.frame(in: .global)) { _, newFrame in + if isCommentsExpanded { + appEnvironment?.navigationCoordinator.commentsFrame = newFrame + } + } + .onChange(of: isCommentsExpanded) { _, expanded in + if expanded { + appEnvironment?.navigationCoordinator.commentsFrame = commentsGeometry.frame(in: .global) + } else { + appEnvironment?.navigationCoordinator.commentsFrame = .zero + } + } + } + ) } // MARK: - Video Info @@ -558,6 +575,7 @@ struct FloatingDetailsPanel: View { } private func collapseComments() { + appEnvironment?.navigationCoordinator.commentsFrame = .zero // Use same animation as player sheet dismiss (0.3s, no bounce) withAnimation(.smooth(duration: 0.3)) { isCommentsExpanded = false diff --git a/Yattee/Views/Player/PortraitDetailsPanel.swift b/Yattee/Views/Player/PortraitDetailsPanel.swift index 2b33be1a..af1c0b0e 100644 --- a/Yattee/Views/Player/PortraitDetailsPanel.swift +++ b/Yattee/Views/Player/PortraitDetailsPanel.swift @@ -256,6 +256,23 @@ struct PortraitDetailsPanel: View { } .opacity(expanded ? 1 : 0) .allowsHitTesting(expanded) + .background( + GeometryReader { commentsGeometry in + Color.clear + .onChange(of: commentsGeometry.frame(in: .global)) { _, newFrame in + if isCommentsExpanded { + appEnvironment?.navigationCoordinator.commentsFrame = newFrame + } + } + .onChange(of: isCommentsExpanded) { _, expanded in + if expanded { + appEnvironment?.navigationCoordinator.commentsFrame = commentsGeometry.frame(in: .global) + } else { + appEnvironment?.navigationCoordinator.commentsFrame = .zero + } + } + } + ) } .animation(.smooth(duration: 0.3), value: isCommentsExpanded) .onChange(of: video.id) { _, _ in @@ -521,6 +538,7 @@ struct PortraitDetailsPanel: View { } private func collapseComments() { + appEnvironment?.navigationCoordinator.commentsFrame = .zero withAnimation(.smooth(duration: 0.3)) { isCommentsExpanded = false }