fix: play playlist entries on single click
This commit is contained in:
@@ -48,7 +48,7 @@ def check_queue_drag(root, app, fixtures):
|
|||||||
if result.returncode != 0 or not report.get("passed"):
|
if result.returncode != 0 or not report.get("passed"):
|
||||||
log = diagnostics.read_text(errors="replace") if diagnostics.exists() else ""
|
log = diagnostics.read_text(errors="replace") if diagnostics.exists() else ""
|
||||||
raise RuntimeError(f"native queue drag failed: {report}; {result.stdout}{result.stderr}{log}")
|
raise RuntimeError(f"native queue drag failed: {report}; {result.stdout}{result.stderr}{log}")
|
||||||
print("PASS native queue drag: slide down/up, hold without pointer events, release to nearest slot, current item preserved")
|
print("PASS native queue: drag down/up without changing playback, release to nearest slot, single click plays without reordering")
|
||||||
|
|
||||||
|
|
||||||
def check_window_layout(root, app, fixtures):
|
def check_window_layout(root, app, fixtures):
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ private enum QueueDragCheck {
|
|||||||
|
|
||||||
static func run(result: URL) {
|
static func run(result: URL) {
|
||||||
resultURL = result
|
resultURL = result
|
||||||
|
_ = NSApplication.shared
|
||||||
_ = NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown, .leftMouseDragged, .leftMouseUp]) {
|
_ = NSEvent.addLocalMonitorForEvents(matching: [.leftMouseDown, .leftMouseDragged, .leftMouseUp]) {
|
||||||
NSLog("[DEBUG-queue-drag] received %@", String(describing: $0))
|
NSLog("[DEBUG-queue-drag] received %@", String(describing: $0))
|
||||||
return $0
|
return $0
|
||||||
@@ -42,6 +43,8 @@ private enum QueueDragCheck {
|
|||||||
timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { _ in
|
timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { _ in
|
||||||
MainActor.assumeIsolated { advance() }
|
MainActor.assumeIsolated { advance() }
|
||||||
}
|
}
|
||||||
|
// Keep injecting mouse events while SwiftUI tracks a pressed row.
|
||||||
|
RunLoop.main.add(timer!, forMode: .common)
|
||||||
terebiAppMain()
|
terebiAppMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,13 +71,17 @@ private enum QueueDragCheck {
|
|||||||
|
|
||||||
static func advance() {
|
static func advance() {
|
||||||
let model = PlayerModel.shared
|
let model = PlayerModel.shared
|
||||||
guard ContinuousClock.now < deadline else { finish("Queue drag did not complete at step \(step)"); return }
|
guard ContinuousClock.now < deadline else {
|
||||||
|
finish("Queue interaction did not complete at step \(step): status \(model.state.status), media \(model.fileName ?? "none"), windows \(NSApp.windows.count)")
|
||||||
|
return
|
||||||
|
}
|
||||||
guard model.canTogglePlayback,
|
guard model.canTogglePlayback,
|
||||||
let window = NSApp.windows.first(where: { $0.canBecomeMain && !($0 is NSPanel) }),
|
let window = NSApp.windows.first(where: { $0.canBecomeMain && !($0 is NSPanel) }),
|
||||||
let content = window.contentView else { return }
|
let content = window.contentView else { return }
|
||||||
if step == 0 {
|
if step == 0 {
|
||||||
model.setVolume(0)
|
model.setVolume(0)
|
||||||
model.addToQueue(["B", "C"].map { URL(fileURLWithPath: "/queue-drag-check/\($0).mp4") })
|
let fixtures = model.queue.currentURL!.deletingLastPathComponent()
|
||||||
|
model.addToQueue(["av.mp4", "cache.mp4"].map { fixtures.appendingPathComponent($0) })
|
||||||
current = model.queue.currentID
|
current = model.queue.currentID
|
||||||
original = model.queue.items.map(\.id)
|
original = model.queue.items.map(\.id)
|
||||||
NSApp.activate(ignoringOtherApps: true)
|
NSApp.activate(ignoringOtherApps: true)
|
||||||
@@ -124,6 +131,16 @@ private enum QueueDragCheck {
|
|||||||
guard model.queue.items.map(\.id) == original, model.queue.currentID == current else {
|
guard model.queue.items.map(\.id) == original, model.queue.currentID == current else {
|
||||||
finish("Stationary upward release did not restore the original order"); return
|
finish("Stationary upward release did not restore the original order"); return
|
||||||
}
|
}
|
||||||
|
let secondRow = NSPoint(x: start.x, y: start.y - 60)
|
||||||
|
mouse(.leftMouseDown, at: secondRow, in: window)
|
||||||
|
} else if step == 28 {
|
||||||
|
mouse(.leftMouseUp, at: NSPoint(x: start.x, y: start.y - 60), in: window)
|
||||||
|
} else if step == 35 {
|
||||||
|
guard model.queue.currentID == original[1],
|
||||||
|
model.queue.items.map(\.id) == original,
|
||||||
|
model.state.status == PLAYER_PLAYING else {
|
||||||
|
finish("Single click did not play the second row without reordering"); return
|
||||||
|
}
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ Active playback prevents idle system sleep. Local video also keeps the display a
|
|||||||
|
|
||||||
### Local-file queue
|
### Local-file queue
|
||||||
|
|
||||||
Use the **Queue** icon immediately left of the compact-mode button in the playback controls, or **View → Show Queue**, to show the editable sidebar. The **+** button beside the queue count opens **Add to Queue…**; it and dropping files onto the sidebar append without replacing the queue or interrupting the current item. Drag rows to reorder, remove them with the minus button, and double-click a row to play it. The current item is marked; context menus also offer Play, Remove and Move Up/Down.
|
Use the **Queue** icon immediately left of the compact-mode button in the playback controls, or **View → Show Queue**, to show the editable sidebar. The **+** button beside the queue count opens **Add to Queue…**; it and dropping files onto the sidebar append without replacing the queue or interrupting the current item. Drag rows to reorder, remove them with the minus button, and click a row to play it. Dragging does not change playback. The current item is marked; context menus also offer Play, Remove and Move Up/Down.
|
||||||
|
|
||||||
The fixed bottom row holds the queue label/count and **+** on the left, with previous/next controls on the right. Its text matches the rows' 13-point medium-weight filenames, and its icons match the rows' 12-point icons. The **+** is a 20-point rounded-square button with an accent-tinted background and an 8-point gap after the queue count; navigation buttons retain their 24-point hit areas.
|
The fixed bottom row holds the queue label/count and **+** on the left, with previous/next controls on the right. Its text matches the rows' 13-point medium-weight filenames, and its icons match the rows' 12-point icons. The **+** is a 20-point rounded-square button with an accent-tinted background and an 8-point gap after the queue count; navigation buttons retain their 24-point hit areas.
|
||||||
|
|
||||||
|
|||||||
@@ -2454,8 +2454,8 @@ private struct PlayerContent: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture(count: 2) { model.selectQueueItem(item.id) }
|
.onTapGesture { model.selectQueueItem(item.id) }
|
||||||
.help(item.url.path + "\nDouble-click to play; drag to reorder.")
|
.help(item.url.path + "\nClick to play; drag to reorder.")
|
||||||
.contextMenu {
|
.contextMenu {
|
||||||
Button("Play") { model.selectQueueItem(item.id) }
|
Button("Play") { model.selectQueueItem(item.id) }
|
||||||
Button("Remove from Queue") { model.removeQueueItem(item.id) }
|
Button("Remove from Queue") { model.removeQueueItem(item.id) }
|
||||||
|
|||||||
Reference in New Issue
Block a user