mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Lagging as Hell
This commit is contained in:
parent
e6fcddae67
commit
8fb0731ebb
2 changed files with 68 additions and 37 deletions
|
|
@ -72,8 +72,8 @@ struct ContentView: View {
|
||||||
|
|
||||||
@State private var gestureProgress: CGFloat = .zero
|
@State private var gestureProgress: CGFloat = .zero
|
||||||
@State private var isMusicControlWindowVisible = false
|
@State private var isMusicControlWindowVisible = false
|
||||||
@State private var pendingMusicControlSync: DispatchWorkItem?
|
@State private var pendingMusicControlTask: Task<Void, Never>?
|
||||||
@State private var musicControlHideWorkItem: DispatchWorkItem?
|
@State private var musicControlHideTask: Task<Void, Never>?
|
||||||
@State private var musicControlVisibilityDeadline: Date?
|
@State private var musicControlVisibilityDeadline: Date?
|
||||||
|
|
||||||
@State private var haptics: Bool = false
|
@State private var haptics: Bool = false
|
||||||
|
|
@ -1005,7 +1005,9 @@ struct ContentView: View {
|
||||||
|
|
||||||
if isPlaying {
|
if isPlaying {
|
||||||
clearMusicControlVisibilityDeadline()
|
clearMusicControlVisibilityDeadline()
|
||||||
scheduleMusicControlWindowSync(forceRefresh: true)
|
if vm.notchState == .closed {
|
||||||
|
scheduleMusicControlWindowSync(forceRefresh: false)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
extendMusicControlVisibilityAfterPause()
|
extendMusicControlVisibilityAfterPause()
|
||||||
}
|
}
|
||||||
|
|
@ -1027,7 +1029,9 @@ struct ContentView: View {
|
||||||
let deadline = Date().addingTimeInterval(musicControlPauseGrace)
|
let deadline = Date().addingTimeInterval(musicControlPauseGrace)
|
||||||
musicControlVisibilityDeadline = deadline
|
musicControlVisibilityDeadline = deadline
|
||||||
scheduleMusicControlVisibilityCheck(deadline: deadline)
|
scheduleMusicControlVisibilityCheck(deadline: deadline)
|
||||||
scheduleMusicControlWindowSync(forceRefresh: true)
|
if vm.notchState == .closed {
|
||||||
|
scheduleMusicControlWindowSync(forceRefresh: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func clearMusicControlVisibilityDeadline() {
|
private func clearMusicControlVisibilityDeadline() {
|
||||||
|
|
@ -1038,24 +1042,31 @@ struct ContentView: View {
|
||||||
private func scheduleMusicControlVisibilityCheck(deadline: Date) {
|
private func scheduleMusicControlVisibilityCheck(deadline: Date) {
|
||||||
cancelMusicControlVisibilityTimer()
|
cancelMusicControlVisibilityTimer()
|
||||||
|
|
||||||
let workItem = DispatchWorkItem {
|
let interval = max(0, deadline.timeIntervalSinceNow)
|
||||||
musicControlHideWorkItem = nil
|
|
||||||
|
musicControlHideTask = Task { @MainActor [interval] in
|
||||||
|
defer { musicControlHideTask = nil }
|
||||||
|
|
||||||
|
if interval > 0 {
|
||||||
|
let nanoseconds = UInt64(interval * 1_000_000_000)
|
||||||
|
try? await Task.sleep(nanoseconds: nanoseconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !Task.isCancelled else { return }
|
||||||
|
|
||||||
if let currentDeadline = musicControlVisibilityDeadline, currentDeadline <= Date() {
|
if let currentDeadline = musicControlVisibilityDeadline, currentDeadline <= Date() {
|
||||||
musicControlVisibilityDeadline = nil
|
musicControlVisibilityDeadline = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleMusicControlWindowSync(forceRefresh: true)
|
if vm.notchState == .closed {
|
||||||
|
scheduleMusicControlWindowSync(forceRefresh: false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
musicControlHideWorkItem = workItem
|
|
||||||
let interval = max(0, deadline.timeIntervalSinceNow)
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + interval, execute: workItem)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func cancelMusicControlVisibilityTimer() {
|
private func cancelMusicControlVisibilityTimer() {
|
||||||
musicControlHideWorkItem?.cancel()
|
musicControlHideTask?.cancel()
|
||||||
musicControlHideWorkItem = nil
|
musicControlHideTask = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
private func musicControlVisibilityIsActive() -> Bool {
|
private func musicControlVisibilityIsActive() -> Bool {
|
||||||
|
|
@ -1089,8 +1100,16 @@ struct ContentView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
let syncDelay = max(0, delay)
|
let syncDelay = max(0, delay)
|
||||||
let workItem = DispatchWorkItem { [forceRefresh] in
|
|
||||||
pendingMusicControlSync = nil
|
pendingMusicControlTask = Task { @MainActor [forceRefresh, syncDelay] in
|
||||||
|
defer { pendingMusicControlTask = nil }
|
||||||
|
|
||||||
|
if syncDelay > 0 {
|
||||||
|
let nanoseconds = UInt64(syncDelay * 1_000_000_000)
|
||||||
|
try? await Task.sleep(nanoseconds: nanoseconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !Task.isCancelled else { return }
|
||||||
|
|
||||||
if shouldShowMusicControlWindow() {
|
if shouldShowMusicControlWindow() {
|
||||||
syncMusicControlWindow(forceRefresh: forceRefresh)
|
syncMusicControlWindow(forceRefresh: forceRefresh)
|
||||||
|
|
@ -1098,15 +1117,12 @@ struct ContentView: View {
|
||||||
hideMusicControlWindow()
|
hideMusicControlWindow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingMusicControlSync = workItem
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + syncDelay, execute: workItem)
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private func cancelMusicControlWindowSync() {
|
private func cancelMusicControlWindowSync() {
|
||||||
pendingMusicControlSync?.cancel()
|
pendingMusicControlTask?.cancel()
|
||||||
pendingMusicControlSync = nil
|
pendingMusicControlTask = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
#if os(macOS)
|
#if os(macOS)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ class MusicManager: ObservableObject {
|
||||||
private var cancellables = Set<AnyCancellable>()
|
private var cancellables = Set<AnyCancellable>()
|
||||||
private var controllerCancellables = Set<AnyCancellable>()
|
private var controllerCancellables = Set<AnyCancellable>()
|
||||||
private var debounceIdleTask: Task<Void, Never>?
|
private var debounceIdleTask: Task<Void, Never>?
|
||||||
|
@MainActor private var pendingOptimisticPlayState: Bool?
|
||||||
|
|
||||||
// Helper to check if macOS has removed support for NowPlayingController
|
// Helper to check if macOS has removed support for NowPlayingController
|
||||||
public private(set) var isNowPlayingDeprecated: Bool = false
|
public private(set) var isNowPlayingDeprecated: Bool = false
|
||||||
|
|
@ -193,20 +194,38 @@ class MusicManager: ObservableObject {
|
||||||
forceUpdate()
|
forceUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
private func applyPlayState(_ state: Bool, animation: Animation?) {
|
||||||
|
if let animation {
|
||||||
|
var transaction = Transaction()
|
||||||
|
transaction.animation = animation
|
||||||
|
withTransaction(transaction) {
|
||||||
|
self.isPlaying = state
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.isPlaying = state
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updateIdleState(state: state)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Update Methods
|
// MARK: - Update Methods
|
||||||
@MainActor
|
@MainActor
|
||||||
private func updateFromPlaybackState(_ state: PlaybackState) {
|
private func updateFromPlaybackState(_ state: PlaybackState) {
|
||||||
// Check for playback state changes (playing/paused)
|
// Check for playback state changes (playing/paused)
|
||||||
if state.isPlaying != self.isPlaying {
|
let eventIsPlaying = state.isPlaying
|
||||||
NSLog("Playback state changed: \(state.isPlaying ? "Playing" : "Paused")")
|
let expectedState = pendingOptimisticPlayState
|
||||||
withAnimation(.smooth) {
|
pendingOptimisticPlayState = nil
|
||||||
self.isPlaying = state.isPlaying
|
|
||||||
self.updateIdleState(state: state.isPlaying)
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.isPlaying && !state.title.isEmpty && !state.artist.isEmpty {
|
if eventIsPlaying != self.isPlaying {
|
||||||
self.updateSneakPeek()
|
let animation: Animation? = (expectedState == eventIsPlaying) ? .smooth(duration: 0.18) : .smooth
|
||||||
}
|
applyPlayState(eventIsPlaying, animation: animation)
|
||||||
|
} else {
|
||||||
|
self.updateIdleState(state: eventIsPlaying)
|
||||||
|
}
|
||||||
|
|
||||||
|
if eventIsPlaying && !state.title.isEmpty && !state.artist.isEmpty {
|
||||||
|
self.updateSneakPeek()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for changes in track metadata using last artwork change values
|
// Check for changes in track metadata using last artwork change values
|
||||||
|
|
@ -486,20 +505,16 @@ class MusicManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func togglePlay() {
|
func togglePlay() {
|
||||||
let controller = activeController
|
guard let controller = activeController else { return }
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
await MainActor.run {
|
await MainActor.run {
|
||||||
let newState = !isPlaying
|
let newState = !isPlaying
|
||||||
withAnimation(.smooth(duration: 0.18)) {
|
pendingOptimisticPlayState = newState
|
||||||
isPlaying = newState
|
applyPlayState(newState, animation: .smooth(duration: 0.18))
|
||||||
if newState {
|
|
||||||
isPlayerIdle = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await controller?.togglePlay()
|
await controller.togglePlay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue