@neoskola/auto-play 0.3.6 → 0.3.8

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.
@@ -37,14 +37,16 @@ class NowPlayingTemplate: AutoPlayTemplate {
37
37
  let titleText = Parser.parseText(text: config.title) ?? "Now Playing"
38
38
  let subtitleText = config.subtitle.flatMap { Parser.parseText(text: $0) } ?? ""
39
39
 
40
- // Section 1: Bilgi — ders ve kurs adi
40
+ // Section 1: Bilgi — ders ve kurs adi + progress bar accessory
41
41
  let infoItem = CPListItem(
42
42
  text: titleText,
43
43
  detailText: subtitleText,
44
- image: UIImage(systemName: "music.note"),
44
+ image: UIImage(systemName: "music.note")?
45
+ .withTintColor(.systemPurple, renderingMode: .alwaysOriginal),
45
46
  accessoryImage: nil,
46
47
  accessoryType: .none
47
48
  )
49
+ infoItem.isEnabled = false
48
50
  let infoSection = CPListSection(
49
51
  items: [infoItem],
50
52
  header: "Şimdi Oynatılıyor",
@@ -55,35 +57,40 @@ class NowPlayingTemplate: AutoPlayTemplate {
55
57
  let timeItem = CPListItem(
56
58
  text: "Yükleniyor...",
57
59
  detailText: nil,
58
- image: UIImage(systemName: "clock"),
60
+ image: UIImage(systemName: "clock")?
61
+ .withTintColor(.systemGray, renderingMode: .alwaysOriginal),
59
62
  accessoryImage: nil,
60
63
  accessoryType: .none
61
64
  )
65
+ timeItem.isEnabled = false
62
66
  let timeSection = CPListSection(
63
67
  items: [timeItem],
64
68
  header: nil,
65
69
  sectionIndexTitle: nil
66
70
  )
67
71
 
68
- // Section 3: Kontroller — onceki, oynat/duraklat, sonraki
72
+ // Section 3: Kontroller — renkli ikonlar
69
73
  let prevItem = CPListItem(
70
74
  text: "Önceki Bölüm",
71
75
  detailText: nil,
72
- image: UIImage(systemName: "backward.end.fill"),
76
+ image: UIImage(systemName: "backward.end.fill")?
77
+ .withTintColor(.systemBlue, renderingMode: .alwaysOriginal),
73
78
  accessoryImage: nil,
74
79
  accessoryType: .none
75
80
  )
76
81
  let playPauseItem = CPListItem(
77
82
  text: "Oynat",
78
83
  detailText: nil,
79
- image: UIImage(systemName: "play.circle.fill"),
84
+ image: UIImage(systemName: "play.circle.fill")?
85
+ .withTintColor(.systemGreen, renderingMode: .alwaysOriginal),
80
86
  accessoryImage: nil,
81
87
  accessoryType: .none
82
88
  )
83
89
  let nextItem = CPListItem(
84
90
  text: "Sonraki Bölüm",
85
91
  detailText: nil,
86
- image: UIImage(systemName: "forward.end.fill"),
92
+ image: UIImage(systemName: "forward.end.fill")?
93
+ .withTintColor(.systemBlue, renderingMode: .alwaysOriginal),
87
94
  accessoryImage: nil,
88
95
  accessoryType: .none
89
96
  )
@@ -94,7 +101,7 @@ class NowPlayingTemplate: AutoPlayTemplate {
94
101
  )
95
102
 
96
103
  template = CPListTemplate(
97
- title: "Now Playing",
104
+ title: titleText,
98
105
  sections: [infoSection, timeSection, controlSection],
99
106
  assistantCellConfiguration: nil,
100
107
  id: config.id
@@ -125,15 +132,17 @@ class NowPlayingTemplate: AutoPlayTemplate {
125
132
  }
126
133
 
127
134
  playPauseItem.handler = { [weak self] _, completion in
128
- guard let self = self else { completion(); return }
129
- if self.config.isPlaying {
130
- self.pauseAudio()
131
- self.config.onPause?()
132
- } else {
133
- self.resumeAudio()
134
- self.config.onPlay?()
135
+ DispatchQueue.main.async {
136
+ guard let self = self else { completion(); return }
137
+ if self.config.isPlaying {
138
+ self.pauseAudio()
139
+ self.config.onPause?()
140
+ } else {
141
+ self.resumeAudio()
142
+ self.config.onPlay?()
143
+ }
144
+ completion()
135
145
  }
136
- completion()
137
146
  }
138
147
 
139
148
  nextItem.handler = { [weak self] _, completion in
@@ -148,60 +157,79 @@ class NowPlayingTemplate: AutoPlayTemplate {
148
157
  let titleText = Parser.parseText(text: config.title) ?? "Now Playing"
149
158
  let subtitleText = config.subtitle.flatMap { Parser.parseText(text: $0) } ?? ""
150
159
 
151
- // Section 1: Bilgi
160
+ // Progress hesapla
161
+ let progress = currentDuration > 0 ? currentElapsedTime / currentDuration : 0
162
+
163
+ // Section 1: Bilgi + progress bar accessory
152
164
  let infoItem = CPListItem(
153
165
  text: titleText,
154
166
  detailText: subtitleText,
155
- image: loadedImage ?? UIImage(systemName: "music.note"),
156
- accessoryImage: nil,
167
+ image: loadedImage ?? UIImage(systemName: "music.note")?
168
+ .withTintColor(.systemPurple, renderingMode: .alwaysOriginal),
169
+ accessoryImage: drawProgressBarImage(progress: progress),
157
170
  accessoryType: .none
158
171
  )
172
+ infoItem.isEnabled = false
159
173
  let infoSection = CPListSection(
160
174
  items: [infoItem],
161
175
  header: "Şimdi Oynatılıyor",
162
176
  sectionIndexTitle: nil
163
177
  )
164
178
 
165
- // Section 2: Sure
179
+ // Section 2: Sure + yuzde detay
166
180
  let elapsed = formatTime(currentElapsedTime)
167
181
  let total = currentDuration > 0 ? formatTime(currentDuration) : "--:--"
168
182
  let timeText: String
169
- let timeIcon: String
183
+ let timeIcon: UIImage?
170
184
  if config.isPlaying {
171
185
  timeText = "\(elapsed) / \(total)"
172
- timeIcon = "waveform"
186
+ timeIcon = UIImage(systemName: "waveform")?
187
+ .withTintColor(.systemGreen, renderingMode: .alwaysOriginal)
173
188
  } else {
174
189
  timeText = "Duraklatıldı \(elapsed) / \(total)"
175
- timeIcon = "pause.circle"
190
+ timeIcon = UIImage(systemName: "pause.circle")?
191
+ .withTintColor(.systemGray, renderingMode: .alwaysOriginal)
176
192
  }
193
+
194
+ let progressPercent = currentDuration > 0
195
+ ? Int((currentElapsedTime / currentDuration) * 100)
196
+ : 0
197
+ let timeDetailText: String? = currentDuration > 0 ? "%\(progressPercent) tamamlandı" : nil
198
+
177
199
  let timeItem = CPListItem(
178
200
  text: timeText,
179
- detailText: nil,
180
- image: UIImage(systemName: timeIcon),
201
+ detailText: timeDetailText,
202
+ image: timeIcon,
181
203
  accessoryImage: nil,
182
204
  accessoryType: .none
183
205
  )
206
+ timeItem.isEnabled = false
184
207
  let timeSection = CPListSection(
185
208
  items: [timeItem],
186
209
  header: nil,
187
210
  sectionIndexTitle: nil
188
211
  )
189
212
 
190
- // Section 3: Kontroller
213
+ // Section 3: Kontroller — renkli ikonlar
191
214
  let prevItem = CPListItem(
192
215
  text: "Önceki Bölüm",
193
216
  detailText: nil,
194
- image: UIImage(systemName: "backward.end.fill"),
217
+ image: UIImage(systemName: "backward.end.fill")?
218
+ .withTintColor(.systemBlue, renderingMode: .alwaysOriginal),
195
219
  accessoryImage: nil,
196
220
  accessoryType: .none
197
221
  )
198
222
 
199
223
  let playPauseText = config.isPlaying ? "Duraklat" : "Oynat"
200
- let playPauseIcon = config.isPlaying ? "pause.circle.fill" : "play.circle.fill"
224
+ let playPauseIcon: UIImage? = config.isPlaying
225
+ ? UIImage(systemName: "pause.circle.fill")?
226
+ .withTintColor(.systemOrange, renderingMode: .alwaysOriginal)
227
+ : UIImage(systemName: "play.circle.fill")?
228
+ .withTintColor(.systemGreen, renderingMode: .alwaysOriginal)
201
229
  let playPauseItem = CPListItem(
202
230
  text: playPauseText,
203
231
  detailText: nil,
204
- image: UIImage(systemName: playPauseIcon),
232
+ image: playPauseIcon,
205
233
  accessoryImage: nil,
206
234
  accessoryType: .none
207
235
  )
@@ -209,7 +237,8 @@ class NowPlayingTemplate: AutoPlayTemplate {
209
237
  let nextItem = CPListItem(
210
238
  text: "Sonraki Bölüm",
211
239
  detailText: nil,
212
- image: UIImage(systemName: "forward.end.fill"),
240
+ image: UIImage(systemName: "forward.end.fill")?
241
+ .withTintColor(.systemBlue, renderingMode: .alwaysOriginal),
213
242
  accessoryImage: nil,
214
243
  accessoryType: .none
215
244
  )
@@ -232,6 +261,35 @@ class NowPlayingTemplate: AutoPlayTemplate {
232
261
  return String(format: "%d:%02d", mins, secs)
233
262
  }
234
263
 
264
+ private func drawProgressBarImage(progress: Double) -> UIImage? {
265
+ let size = CPListItem.maximumImageSize
266
+ let renderer = UIGraphicsImageRenderer(size: size)
267
+ return renderer.image { _ in
268
+ let barHeight: CGFloat = 6
269
+ let barY = (size.height - barHeight) / 2
270
+ let cornerRadius = barHeight / 2
271
+
272
+ // Arka plan (gri track)
273
+ let trackPath = UIBezierPath(
274
+ roundedRect: CGRect(x: 2, y: barY, width: size.width - 4, height: barHeight),
275
+ cornerRadius: cornerRadius
276
+ )
277
+ UIColor.systemGray4.setFill()
278
+ trackPath.fill()
279
+
280
+ // Ilerleme (yesil fill)
281
+ let progressWidth = max(0, (size.width - 4) * CGFloat(min(progress, 1.0)))
282
+ if progressWidth > 0 {
283
+ let progressPath = UIBezierPath(
284
+ roundedRect: CGRect(x: 2, y: barY, width: progressWidth, height: barHeight),
285
+ cornerRadius: cornerRadius
286
+ )
287
+ UIColor.systemGreen.setFill()
288
+ progressPath.fill()
289
+ }
290
+ }
291
+ }
292
+
235
293
  // MARK: - Native Audio Playback
236
294
 
237
295
  @MainActor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoskola/auto-play",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Android Auto and Apple CarPlay for react-native",
5
5
  "main": "lib/index",
6
6
  "module": "lib/index",