fix: keep playlist reordering active while dragging

This commit is contained in:
2026-10-18 22:21:42 +02:00
parent 2e5255e194
commit ef3aae842d
5 changed files with 314 additions and 17 deletions
+44
View File
@@ -60,3 +60,47 @@ struct PlaybackQueue {
}
}
}
// Geometry stays in the unshifted content coordinate space throughout a gesture.
struct PlaybackQueueDrag {
let source: Int
let frames: [CGRect]
let initialScrollOffset: CGFloat
private(set) var scrollOffset: CGFloat
private(set) var translation: CGFloat = 0
private(set) var destination: Int
var pointerY: CGFloat = 0
init(source: Int, frames: [CGRect], scrollOffset: CGFloat) {
self.source = source
self.frames = frames
initialScrollOffset = scrollOffset
self.scrollOffset = scrollOffset
destination = source
}
var offset: CGFloat { translation + scrollOffset - initialScrollOffset }
func center(at index: Int) -> CGFloat {
if index < source { return frames[index].minY + frames[source].height / 2 }
if index > source { return frames[index].maxY - frames[source].height / 2 }
return frames[source].midY
}
mutating func update(translation: CGFloat, scrollOffset: CGFloat) {
self.translation = translation
self.scrollOffset = scrollOffset
let centerY = frames[source].midY + offset
destination = frames.indices.min { abs(center(at: $0) - centerY) < abs(center(at: $1) - centerY) }!
}
var insertionOffset: Int { destination > source ? destination + 1 : destination }
func offset(at index: Int) -> CGFloat {
if index == source { return offset }
let target = destination
if source < index && index <= target { return -frames[source].height }
if target <= index && index < source { return frames[source].height }
return 0
}
}