@@ -8,7 +8,28 @@ class PlaybackQueue: NSObject {
88 private var topEpisode : BaseEpisode ?
99
1010 private let syncTimerDelay : TimeInterval = 5
11+ private let interactionGracePeriod : TimeInterval = 10
1112 private var syncTimer : Timer ?
13+ private var lastUserInteractionTime : Date ?
14+
15+ // MARK: - User Interaction Tracking
16+
17+ func recordUpNextUserInteraction( at date: Date = Date ( ) ) {
18+ lastUserInteractionTime = date
19+ }
20+
21+ func recentUserInteraction( now: Date = Date ( ) ) -> Bool {
22+ remainingInteractionDelay ( now: now) != nil
23+ }
24+
25+ private func remainingInteractionDelay( now: Date = Date ( ) ) -> TimeInterval ? {
26+ guard let lastUserInteractionTime else { return nil }
27+
28+ let elapsed = now. timeIntervalSince ( lastUserInteractionTime)
29+ let remaining = interactionGracePeriod - elapsed
30+
31+ return remaining > 0 ? remaining : nil
32+ }
1233
1334 // MARK: - Editing
1435
@@ -400,27 +421,40 @@ class PlaybackQueue: NSObject {
400421
401422 // MARK: - Sync Timer
402423
403- private func startSyncTimer( ) {
424+ private func cancelSyncTimer( ) {
425+ syncTimer? . invalidate ( )
426+ syncTimer = nil
427+ }
428+
429+ private func startSyncTimer( after delay: TimeInterval ? = nil ) {
404430 cancelSyncTimer ( )
431+ scheduleSyncTimer ( after: delay ?? syncTimerDelay)
432+ }
433+
434+ private func scheduleSyncTimer( after delay: TimeInterval ) {
435+ let scheduleTimer : ( ) -> Void = { [ weak self] in
436+ guard let self else { return }
437+
438+ self . syncTimer = Timer . scheduledTimer ( timeInterval: delay, target: self , selector: #selector( self . syncTimerFired) , userInfo: nil , repeats: false )
439+ }
405440
406441 // schedule the timer on a thread that has a run loop, the main thread being a good option
407442 if Thread . isMainThread {
408- syncTimer = Timer . scheduledTimer ( timeInterval : syncTimerDelay , target : self , selector : #selector ( syncTimerFired ) , userInfo : nil , repeats : false )
443+ scheduleTimer ( )
409444 } else {
410- DispatchQueue . main. sync { [ weak self] ( ) in
411- guard let self else { return }
412-
413- self . syncTimer = Timer . scheduledTimer ( timeInterval: self . syncTimerDelay, target: self , selector: #selector( self . syncTimerFired) , userInfo: nil , repeats: false )
445+ DispatchQueue . main. sync {
446+ scheduleTimer ( )
414447 }
415448 }
416449 }
417450
418- private func cancelSyncTimer( ) {
419- syncTimer? . invalidate ( )
420- syncTimer = nil
421- }
422-
423451 @objc private func syncTimerFired( ) {
452+ if let remainingDelay = remainingInteractionDelay ( ) {
453+ FileLog . shared. addMessage ( " PlaybackQueue: Delaying Up Next sync for \( Int ( remainingDelay. rounded ( . up) ) ) seconds due to recent interaction " )
454+ startSyncTimer ( after: remainingDelay)
455+ return
456+ }
457+
424458 RefreshManager . shared. syncUpNext ( )
425459 }
426460}
0 commit comments