From ae37861f7db9a9fdf47237cb508b775b82045aca Mon Sep 17 00:00:00 2001 From: advplyr Date: Sun, 18 Jun 2023 15:34:56 -0500 Subject: [PATCH] Add:iOS support offline episode chapters #675 --- ios/App/App/AppDelegate.swift | 2 +- ios/App/Shared/models/local/LocalLibraryItem.swift | 1 + ios/App/Shared/models/local/LocalPodcastEpisode.swift | 1 + ios/App/Shared/models/server/PodcastEpisode.swift | 7 +++++++ ios/App/Shared/util/Extensions.swift | 6 ++++++ 5 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift index 1cf787d0..65495314 100644 --- a/ios/App/App/AppDelegate.swift +++ b/ios/App/App/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Override point for customization after application launch. let configuration = Realm.Configuration( - schemaVersion: 8, + schemaVersion: 9, migrationBlock: { [weak self] migration, oldSchemaVersion in if (oldSchemaVersion < 1) { self?.logger.log("Realm schema version was \(oldSchemaVersion)") diff --git a/ios/App/Shared/models/local/LocalLibraryItem.swift b/ios/App/Shared/models/local/LocalLibraryItem.swift index f1fc815f..b6c4e858 100644 --- a/ios/App/Shared/models/local/LocalLibraryItem.swift +++ b/ios/App/Shared/models/local/LocalLibraryItem.swift @@ -177,6 +177,7 @@ extension LocalLibraryItem { audioTracks.append(AudioTrack.detachCopy(of: track)!) duration = track.duration displayTitle = episode.title + episode.chapters.forEach { chapter in chapters.append(Chapter.detachCopy(of: chapter)!) } } else if let tracks = self.media?.tracks { tracks.forEach { t in audioTracks.append(AudioTrack.detachCopy(of: t)!) } } diff --git a/ios/App/Shared/models/local/LocalPodcastEpisode.swift b/ios/App/Shared/models/local/LocalPodcastEpisode.swift index 28fec0a4..21d2adee 100644 --- a/ios/App/Shared/models/local/LocalPodcastEpisode.swift +++ b/ios/App/Shared/models/local/LocalPodcastEpisode.swift @@ -18,6 +18,7 @@ class LocalPodcastEpisode: Object, Codable { @Persisted var desc: String? @Persisted var audioFile: AudioFile? @Persisted var audioTrack: AudioTrack? + @Persisted var chapters = List() @Persisted var duration: Double = 0 @Persisted var size: Int = 0 @Persisted(indexed: true) var serverEpisodeId: String? diff --git a/ios/App/Shared/models/server/PodcastEpisode.swift b/ios/App/Shared/models/server/PodcastEpisode.swift index c480c07d..b1037392 100644 --- a/ios/App/Shared/models/server/PodcastEpisode.swift +++ b/ios/App/Shared/models/server/PodcastEpisode.swift @@ -18,6 +18,7 @@ class PodcastEpisode: EmbeddedObject, Codable { @Persisted var desc: String? @Persisted var audioFile: AudioFile? @Persisted var audioTrack: AudioTrack? + @Persisted var chapters = List() @Persisted var duration: Double? @Persisted var size: Int? var serverEpisodeId: String { self.id } @@ -32,6 +33,7 @@ class PodcastEpisode: EmbeddedObject, Codable { desc = "description", // Fixes a collision with the base Swift object's field "description" audioFile, audioTrack, + chapters, duration, size, serverEpisodeId @@ -40,6 +42,7 @@ class PodcastEpisode: EmbeddedObject, Codable { override init() {} required init(from decoder: Decoder) throws { + super.init() let values = try decoder.container(keyedBy: CodingKeys.self) id = try values.decode(String.self, forKey: .id) index = try? values.decode(Int.self, forKey: .index) @@ -50,6 +53,9 @@ class PodcastEpisode: EmbeddedObject, Codable { desc = try? values.decode(String.self, forKey: .desc) audioFile = try? values.decode(AudioFile.self, forKey: .audioFile) audioTrack = try? values.decode(AudioTrack.self, forKey: .audioTrack) + if let chapterList = try? values.decode([Chapter].self, forKey: .chapters) { + chapters.append(objectsIn: chapterList) + } duration = try? values.decode(Double.self, forKey: .duration) size = try? values.decode(Int.self, forKey: .size) } @@ -65,6 +71,7 @@ class PodcastEpisode: EmbeddedObject, Codable { try container.encode(desc, forKey: .desc) try container.encode(audioFile, forKey: .audioFile) try container.encode(audioTrack, forKey: .audioTrack) + try container.encode(Array(chapters), forKey: .chapters) try container.encode(duration, forKey: .duration) try container.encode(size, forKey: .size) try container.encode(serverEpisodeId, forKey: .serverEpisodeId) diff --git a/ios/App/Shared/util/Extensions.swift b/ios/App/Shared/util/Extensions.swift index da7a28aa..ca4c6bc7 100644 --- a/ios/App/Shared/util/Extensions.swift +++ b/ios/App/Shared/util/Extensions.swift @@ -50,6 +50,12 @@ extension KeyedDecodingContainer { return Int(stringValue) ?? 0 } } + + // This will be called when any @Persisted List<> is decoded + func decode(_ type: Persisted>.Type, forKey key: Key) throws -> Persisted> { + // Use decode if present, falling back to an empty list + try decodeIfPresent(type, forKey: key) ?? Persisted>(wrappedValue: List()) + } } extension CAPPluginCall {