@neoskola/auto-play 0.3.14 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -188,13 +188,6 @@ class HybridAutoPlay: HybridAutoPlaySpec {
188
188
  )
189
189
  }
190
190
 
191
- // NowPlayingTemplate: inject custom UIKit view into CPWindow
192
- if let nowPlaying = template as? NowPlayingTemplate {
193
- try await MainActor.run {
194
- try nowPlaying.injectCustomView()
195
- }
196
- }
197
-
198
191
  if let autoDismissMs = TemplateStore.getTemplate(
199
192
  templateId: templateId
200
193
  )?.autoDismissMs {
@@ -2,18 +2,13 @@ import CarPlay
2
2
  import MediaPlayer
3
3
  import AVFoundation
4
4
 
5
- class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
6
- var template: CPMapTemplate
5
+ class NowPlayingTemplate: NSObject, AutoPlayTemplate {
7
6
  var config: NowPlayingTemplateConfig
8
7
  private var loadedImage: UIImage?
9
8
  private var isSetupComplete = false
10
9
  private var currentElapsedTime: Double = 0
11
10
  private var currentDuration: Double = 0
12
11
 
13
- // Custom UIKit view
14
- private var customViewController: NeoSkolaNowPlayingViewController?
15
- private var previousRootVC: UIViewController?
16
-
17
12
  // Native audio player
18
13
  private var player: AVPlayer?
19
14
  private var playerItem: AVPlayerItem?
@@ -32,17 +27,16 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
32
27
  }
33
28
 
34
29
  func getTemplate() -> CPTemplate {
35
- return template
30
+ return CPNowPlayingTemplate.shared
36
31
  }
37
32
 
38
33
  init(config: NowPlayingTemplateConfig) {
39
34
  self.config = config
40
- template = CPMapTemplate(id: config.id)
41
35
 
42
36
  super.init()
43
37
 
44
- template.mapDelegate = self
45
- template.mapButtons = Self.buildMapButtons(isPlaying: config.isPlaying, owner: self)
38
+ // Set the config ID on the shared singleton so TemplateStore can find it
39
+ initTemplate(template: CPNowPlayingTemplate.shared, id: config.id)
46
40
 
47
41
  DispatchQueue.main.async { [weak self] in
48
42
  guard let self = self else { return }
@@ -57,102 +51,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
57
51
  }
58
52
  }
59
53
 
60
- // MARK: - CPMapButton Controls
61
-
62
- private static func buildMapButtons(isPlaying: Bool, owner: NowPlayingTemplate) -> [CPMapButton] {
63
- let buttonSize = CPButtonMaximumImageSize
64
-
65
- // Previous track button
66
- let prevImage = UIImage(systemName: "backward.end.fill")?
67
- .withTintColor(.white, renderingMode: .alwaysOriginal)
68
- .resized(to: buttonSize)
69
- let prevButton = CPMapButton(image: prevImage ?? UIImage()) { [weak owner] _ in
70
- owner?.config.onPreviousTrack?()
71
- }
72
-
73
- // Play/Pause button
74
- let playPauseIconName = isPlaying ? "pause.circle.fill" : "play.circle.fill"
75
- let playPauseImage = UIImage(systemName: playPauseIconName)?
76
- .withTintColor(.white, renderingMode: .alwaysOriginal)
77
- .resized(to: buttonSize)
78
- let playPauseButton = CPMapButton(image: playPauseImage ?? UIImage()) { [weak owner] _ in
79
- guard let owner = owner else { return }
80
- DispatchQueue.main.async {
81
- if owner.config.isPlaying {
82
- owner.pauseAudio()
83
- owner.config.onPause?()
84
- } else {
85
- owner.resumeAudio()
86
- owner.config.onPlay?()
87
- }
88
- }
89
- }
90
-
91
- // Next track button
92
- let nextImage = UIImage(systemName: "forward.end.fill")?
93
- .withTintColor(.white, renderingMode: .alwaysOriginal)
94
- .resized(to: buttonSize)
95
- let nextButton = CPMapButton(image: nextImage ?? UIImage()) { [weak owner] _ in
96
- owner?.config.onNextTrack?()
97
- }
98
-
99
- return [prevButton, playPauseButton, nextButton]
100
- }
101
-
102
- private func updateMapButtons() {
103
- template.mapButtons = Self.buildMapButtons(isPlaying: config.isPlaying, owner: self)
104
- }
105
-
106
- // MARK: - Custom View Injection
107
-
108
- @MainActor
109
- func injectCustomView() throws {
110
- guard let scene = SceneStore.getRootScene(),
111
- let window = scene.window else {
112
- throw AutoPlayError.noUiWindow("NowPlaying: window nil")
113
- }
114
-
115
- previousRootVC = window.rootViewController
116
-
117
- let customVC = NeoSkolaNowPlayingViewController()
118
-
119
- let titleText = Parser.parseText(text: config.title) ?? "Now Playing"
120
- let subtitleText = config.subtitle.flatMap { Parser.parseText(text: $0) } ?? ""
121
- customVC.updateInfo(courseName: subtitleText, lessonName: titleText)
122
- customVC.updatePlaybackState(isPlaying: config.isPlaying)
123
-
124
- window.rootViewController = customVC
125
- window.makeKeyAndVisible()
126
-
127
- self.customViewController = customVC
128
- }
129
-
130
- @MainActor
131
- private func restoreOriginalView() {
132
- guard let scene = SceneStore.getRootScene(),
133
- let window = scene.window else { return }
134
-
135
- if let previousRootVC = previousRootVC {
136
- window.rootViewController = previousRootVC
137
- window.makeKeyAndVisible()
138
- }
139
- self.previousRootVC = nil
140
- self.customViewController = nil
141
- }
142
-
143
- // MARK: - Player UI
144
-
145
- private func updatePlayerUI() {
146
- guard let customVC = customViewController else { return }
147
-
148
- let titleText = Parser.parseText(text: config.title) ?? ""
149
- let subtitleText = config.subtitle.flatMap { Parser.parseText(text: $0) } ?? ""
150
- customVC.updateInfo(courseName: subtitleText, lessonName: titleText)
151
- customVC.updatePlaybackState(isPlaying: config.isPlaying)
152
- customVC.updateTime(elapsed: currentElapsedTime, duration: currentDuration)
153
- updateMapButtons()
154
- }
155
-
156
54
  // MARK: - Native Audio Playback
157
55
 
158
56
  @MainActor
@@ -170,7 +68,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
170
68
  NowPlayingSessionManager.shared.ensureSessionActive()
171
69
  config.isPlaying = true
172
70
  updateNowPlayingInfo()
173
- updatePlayerUI()
174
71
  MPNowPlayingInfoCenter.default().playbackState = .playing
175
72
 
176
73
  print("[NowPlayingTemplate] Downloading audio: \(url)")
@@ -229,7 +126,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
229
126
  if !duration.isNaN && !duration.isInfinite && duration > 0 {
230
127
  self.currentDuration = duration
231
128
  self.updateNowPlayingInfo()
232
- self.updatePlayerUI()
233
129
  print("[NowPlayingTemplate] Duration resolved via KVO: \(duration)s")
234
130
  }
235
131
  }
@@ -299,8 +195,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
299
195
  nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = config.isPlaying ? 1.0 : 0.0
300
196
  MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
301
197
 
302
- updatePlayerUI()
303
-
304
198
  // 95% completion check
305
199
  if !completionFired && currentDuration > 0 && currentTime / currentDuration >= 0.95 {
306
200
  completionFired = true
@@ -318,7 +212,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
318
212
  private func handlePlaybackFinished() {
319
213
  config.isPlaying = false
320
214
  MPNowPlayingInfoCenter.default().playbackState = .stopped
321
- updatePlayerUI()
322
215
  if !completionFired {
323
216
  completionFired = true
324
217
  config.onComplete?()
@@ -331,7 +224,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
331
224
  player?.pause()
332
225
  config.isPlaying = false
333
226
  updatePlaybackState(isPlaying: false)
334
- updatePlayerUI()
335
227
  reportProgress()
336
228
  }
337
229
 
@@ -341,7 +233,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
341
233
  player?.play()
342
234
  config.isPlaying = true
343
235
  updatePlaybackState(isPlaying: true)
344
- updatePlayerUI()
345
236
  }
346
237
 
347
238
  @MainActor
@@ -366,7 +257,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
366
257
  cleanupPlayer()
367
258
  config.isPlaying = false
368
259
  MPNowPlayingInfoCenter.default().playbackState = .stopped
369
- updatePlayerUI()
370
260
  }
371
261
 
372
262
  private func cleanupPlayer() {
@@ -483,7 +373,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
483
373
  self.player?.seek(to: time)
484
374
  self.currentElapsedTime = positionEvent.positionTime
485
375
  self.updateNowPlayingInfo()
486
- self.updatePlayerUI()
487
376
  return .success
488
377
  }
489
378
  }
@@ -508,7 +397,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
508
397
 
509
398
  @MainActor
510
399
  func invalidate() {
511
- updatePlayerUI()
512
400
  updateNowPlayingInfo()
513
401
 
514
402
  if loadedImage == nil, let image = config.image {
@@ -535,7 +423,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
535
423
  func onPopped() {
536
424
  config.onPopped?()
537
425
  cleanupPlayer()
538
- restoreOriginalView()
539
426
 
540
427
  let commandCenter = MPRemoteCommandCenter.shared()
541
428
  commandCenter.playCommand.removeTarget(nil)
@@ -556,7 +443,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
556
443
  NowPlayingSessionManager.shared.ensureSessionActive()
557
444
 
558
445
  if !isSetupComplete {
559
- updatePlayerUI()
560
446
  updateNowPlayingInfo()
561
447
  isSetupComplete = true
562
448
  }
@@ -583,7 +469,6 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
583
469
  config.title = AutoText(text: title, distance: nil, duration: nil)
584
470
  config.subtitle = AutoText(text: subtitle, distance: nil, duration: nil)
585
471
  updateNowPlayingInfo()
586
- updatePlayerUI()
587
472
  }
588
473
 
589
474
  @MainActor
@@ -605,11 +490,5 @@ class NowPlayingTemplate: NSObject, AutoPlayTemplate, CPMapTemplateDelegate {
605
490
  nowPlayingInfo[MPNowPlayingInfoPropertyElapsedPlaybackTime] = elapsedTime
606
491
  nowPlayingInfo[MPNowPlayingInfoPropertyPlaybackRate] = config.isPlaying ? 1.0 : 0.0
607
492
  MPNowPlayingInfoCenter.default().nowPlayingInfo = nowPlayingInfo
608
-
609
- updatePlayerUI()
610
493
  }
611
-
612
- // MARK: - CPMapTemplateDelegate
613
-
614
- func mapTemplate(_ mapTemplate: CPMapTemplate, panWith direction: CPMapTemplate.PanDirection) {}
615
494
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoskola/auto-play",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "description": "Android Auto and Apple CarPlay for react-native",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",