import Foundation /// Cross-process (main app ⇆ share extension) queue of podcast-generation /// requests, plus the user's "auto-generate for these tags" rule. Lives in the /// shared App Group so the share extension can enqueue work the main app runs — /// the extension itself is too short-lived to generate audio. enum PodcastRequests { private static let appGroupId = "group.com.magicive.marks" private static let pendingKey = "pendingPodcastRequests" private static let autoTagsKey = "podcastAutoTags" private static var defaults: UserDefaults? { UserDefaults(suiteName: appGroupId) } struct Request: Codable { let url: String let title: String } // MARK: - Pending queue /// Enqueue a request. De-duplicates on URL so repeated saves don't pile up. static func enqueue(url: String, title: String) { var list = pending() guard !list.contains(where: { $0.url == url }) else { return } list.append(Request(url: url, title: title)) save(list) } static func pending() -> [Request] { guard let data = defaults?.data(forKey: pendingKey), let list = try? JSONDecoder().decode([Request].self, from: data) else { return [] } return list } /// Return everything pending and clear the queue. static func drain() -> [Request] { let list = pending() defaults?.removeObject(forKey: pendingKey) return list } private static func save(_ list: [Request]) { guard let data = try? JSONEncoder().encode(list) else { return } defaults?.set(data, forKey: pendingKey) } // MARK: - Auto-tag rule /// Tags that auto-trigger podcast generation when a bookmark is saved. static var autoTags: [String] { get { defaults?.stringArray(forKey: autoTagsKey) ?? [] } set { defaults?.set(newValue, forKey: autoTagsKey) } } /// Whether saving a bookmark with `tags` should auto-generate a podcast. static func matchesAutoTag(_ tags: [String]) -> Bool { let auto = Set(autoTags.map { $0.lowercased() }) guard !auto.isEmpty else { return false } return tags.contains { auto.contains($0.lowercased()) } } }