mirror of
https://github.com/yattee/yattee.git
synced 2026-02-19 09:19:46 +00:00
Fix player dismiss gesture stuck after panel dismiss with comments expanded
Reset isCommentsExpanded and commentsFrame on the NavigationCoordinator directly when the portrait panel is dismissed, since PortraitDetailsPanel owns its own @State that doesn't sync back through .onChange during dismiss. Also track comments overlay frame via GeometryReader so the dismiss gesture can allow swipes outside the comments area instead of blanket-blocking.
This commit is contained in:
@@ -120,6 +120,9 @@ final class NavigationCoordinator {
|
|||||||
/// Progress bar frame in screen coordinates (for gesture conflict resolution).
|
/// Progress bar frame in screen coordinates (for gesture conflict resolution).
|
||||||
var progressBarFrame: CGRect = .zero
|
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).
|
/// Current panscan value from UIKit pinch gesture (0.0 = fit, 1.0 = fill).
|
||||||
/// Updated by ExpandedPlayerWindow's pinch gesture handler.
|
/// Updated by ExpandedPlayerWindow's pinch gesture handler.
|
||||||
var pinchPanscan: Double = 0.0
|
var pinchPanscan: Double = 0.0
|
||||||
|
|||||||
@@ -481,6 +481,9 @@ extension ExpandedPlayerSheet {
|
|||||||
withTransaction(transaction) {
|
withTransaction(transaction) {
|
||||||
isPortraitPanelVisible = false
|
isPortraitPanelVisible = false
|
||||||
navigationCoordinator?.isPortraitPanelVisible = false
|
navigationCoordinator?.isPortraitPanelVisible = false
|
||||||
|
isCommentsExpanded = false
|
||||||
|
navigationCoordinator?.isCommentsExpanded = false
|
||||||
|
navigationCoordinator?.commentsFrame = .zero
|
||||||
panelDragOffset = 0
|
panelDragOffset = 0
|
||||||
videoYOffset = 0 // Reset offset (centerY is now the base)
|
videoYOffset = 0 // Reset offset (centerY is now the base)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ extension ExpandedPlayerSheet {
|
|||||||
|
|
||||||
/// Collapses the comments overlay.
|
/// Collapses the comments overlay.
|
||||||
func collapseComments() {
|
func collapseComments() {
|
||||||
|
navigationCoordinator?.commentsFrame = .zero
|
||||||
// Use same animation as player sheet dismiss (0.3s, no bounce)
|
// Use same animation as player sheet dismiss (0.3s, no bounce)
|
||||||
withAnimation(.smooth(duration: 0.3)) {
|
withAnimation(.smooth(duration: 0.3)) {
|
||||||
isCommentsExpanded = false
|
isCommentsExpanded = false
|
||||||
|
|||||||
@@ -269,6 +269,23 @@ struct ExpandedPlayerSheet: View {
|
|||||||
}
|
}
|
||||||
.opacity(isVisible ? 1 : 0)
|
.opacity(isVisible ? 1 : 0)
|
||||||
.allowsHitTesting(isVisible)
|
.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)
|
.ignoresSafeArea(edges: .bottom)
|
||||||
}
|
}
|
||||||
@@ -770,6 +787,7 @@ private struct PlayerEventHandlersModifier: ViewModifier {
|
|||||||
playerState?.commentsState = .idle
|
playerState?.commentsState = .idle
|
||||||
playerState?.commentsContinuation = nil
|
playerState?.commentsContinuation = nil
|
||||||
isCommentsExpanded = false
|
isCommentsExpanded = false
|
||||||
|
navigationCoordinator?.commentsFrame = .zero
|
||||||
isPanelExpanded = false
|
isPanelExpanded = false
|
||||||
panelExpandOffset = 0
|
panelExpandOffset = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,6 +150,8 @@ private final class DragToDismissGestureHandler: NSObject, UIGestureRecognizerDe
|
|||||||
var getProgressBarFrame: (() -> CGRect)?
|
var getProgressBarFrame: (() -> CGRect)?
|
||||||
/// Returns true if a seek gesture is currently active (blocks pinch gesture)
|
/// Returns true if a seek gesture is currently active (blocks pinch gesture)
|
||||||
var isSeekGestureActive: (() -> Bool)?
|
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)
|
// Main window scaling callbacks (Apple Music-style effect)
|
||||||
var onMainWindowScaleChanged: ((CGFloat) -> Void)?
|
var onMainWindowScaleChanged: ((CGFloat) -> Void)?
|
||||||
@@ -341,9 +343,17 @@ private final class DragToDismissGestureHandler: NSObject, UIGestureRecognizerDe
|
|||||||
return false
|
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 {
|
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
|
// Don't begin dismiss gesture when adjusting volume/brightness sliders
|
||||||
@@ -840,6 +850,9 @@ final class ExpandedPlayerWindowManager {
|
|||||||
handler.isSeekGestureActive = { [weak self] in
|
handler.isSeekGestureActive = { [weak self] in
|
||||||
self?.appEnvironment?.navigationCoordinator.isSeekGestureActive ?? false
|
self?.appEnvironment?.navigationCoordinator.isSeekGestureActive ?? false
|
||||||
}
|
}
|
||||||
|
handler.getCommentsFrame = { [weak self] in
|
||||||
|
self?.appEnvironment?.navigationCoordinator.commentsFrame ?? .zero
|
||||||
|
}
|
||||||
// Main window scaling callbacks for interactive drag
|
// Main window scaling callbacks for interactive drag
|
||||||
handler.onMainWindowScaleChanged = { [weak self] progress in
|
handler.onMainWindowScaleChanged = { [weak self] progress in
|
||||||
guard let self else { return }
|
guard let self else { return }
|
||||||
|
|||||||
@@ -495,6 +495,23 @@ struct FloatingDetailsPanel: View {
|
|||||||
}
|
}
|
||||||
.opacity(expanded ? 1 : 0)
|
.opacity(expanded ? 1 : 0)
|
||||||
.allowsHitTesting(expanded)
|
.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
|
// MARK: - Video Info
|
||||||
@@ -558,6 +575,7 @@ struct FloatingDetailsPanel: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func collapseComments() {
|
private func collapseComments() {
|
||||||
|
appEnvironment?.navigationCoordinator.commentsFrame = .zero
|
||||||
// Use same animation as player sheet dismiss (0.3s, no bounce)
|
// Use same animation as player sheet dismiss (0.3s, no bounce)
|
||||||
withAnimation(.smooth(duration: 0.3)) {
|
withAnimation(.smooth(duration: 0.3)) {
|
||||||
isCommentsExpanded = false
|
isCommentsExpanded = false
|
||||||
|
|||||||
@@ -256,6 +256,23 @@ struct PortraitDetailsPanel: View {
|
|||||||
}
|
}
|
||||||
.opacity(expanded ? 1 : 0)
|
.opacity(expanded ? 1 : 0)
|
||||||
.allowsHitTesting(expanded)
|
.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)
|
.animation(.smooth(duration: 0.3), value: isCommentsExpanded)
|
||||||
.onChange(of: video.id) { _, _ in
|
.onChange(of: video.id) { _, _ in
|
||||||
@@ -521,6 +538,7 @@ struct PortraitDetailsPanel: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func collapseComments() {
|
private func collapseComments() {
|
||||||
|
appEnvironment?.navigationCoordinator.commentsFrame = .zero
|
||||||
withAnimation(.smooth(duration: 0.3)) {
|
withAnimation(.smooth(duration: 0.3)) {
|
||||||
isCommentsExpanded = false
|
isCommentsExpanded = false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user