Podcast UX baseline: mini player during generation, end-of-track reset, library view

- Mini player shows as soon as generation starts (not just when audio ready)
- Idempotency: tapping headphones again during generation is a no-op
- Playback resets to position 0 on completion (standard player behavior)
- Stop button in full player visible during generation
- PodcastLibraryView lists all generated podcasts
- Sparkles menu gains Podcasts entry
- Fix AnalyticsService Sendable error (serialize before Task.detached boundary)
This commit is contained in:
Krishna Kumar
2026-05-23 00:46:46 -05:00
parent 18423a7633
commit ab72611d7b
3 changed files with 113 additions and 16 deletions

View File

@@ -2,6 +2,10 @@ import Foundation
enum Analytics {
static func track(_ event: String, _ properties: [String: Any] = [:]) {
// Serialize before crossing the task boundary Data is Sendable, [String: Any] is not
var body: [String: Any] = ["event": event]
if !properties.isEmpty { body["properties"] = properties }
guard let payload = try? JSONSerialization.data(withJSONObject: body) else { return }
Task.detached {
do {
let token = try await MarksAuth.validToken()
@@ -10,9 +14,7 @@ enum Analytics {
request.httpMethod = "POST"
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
var body: [String: Any] = ["event": event]
if !properties.isEmpty { body["properties"] = properties }
request.httpBody = try JSONSerialization.data(withJSONObject: body)
request.httpBody = payload
let (_, response) = try await URLSession.shared.data(for: request)
let status = (response as? HTTPURLResponse)?.statusCode ?? 0
if status < 200 || status > 299 {