mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-12 15:04:43 +02:00
Fix data model issues
This commit is contained in:
parent
e275aa1699
commit
446e54cb91
6 changed files with 65 additions and 69 deletions
|
@ -45,7 +45,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
|
||||
// Local library
|
||||
Realm.registerRealmables(LocalLibraryItem.self)
|
||||
Realm.registerRealmables(LocalPodcastEpisode.self)
|
||||
Realm.registerRealmables(LocalFile.self)
|
||||
Realm.registerRealmables(LocalMediaProgress.self)
|
||||
|
||||
|
|
|
@ -154,10 +154,8 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
|||
let files = downloadItem.downloadItemParts.compactMap { part -> LocalFile? in
|
||||
if part.filename == "cover.jpg" {
|
||||
coverFile = part.destinationUri
|
||||
return nil
|
||||
} else {
|
||||
return LocalFile(libraryItem.id, part.filename!, part.mimeType()!, part.destinationUri!, fileSize: Int(part.destinationURL!.fileSize))
|
||||
}
|
||||
return LocalFile(libraryItem.id, part.filename!, part.mimeType()!, part.destinationUri!, fileSize: Int(part.destinationURL!.fileSize))
|
||||
}
|
||||
let localLibraryItem = LocalLibraryItem(libraryItem, localUrl: localDirectory, server: Store.serverConfig!, files: files, coverPath: coverFile)
|
||||
|
||||
|
@ -165,8 +163,8 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
|||
statusNotification["localLibraryItem"] = try? localLibraryItem.asDictionary()
|
||||
|
||||
if let progress = libraryItem.userMediaProgress {
|
||||
// TODO: Handle podcast
|
||||
let localMediaProgress = LocalMediaProgress(localLibraryItem: localLibraryItem, episode: nil, progress: progress)
|
||||
let episode = downloadItem.media?.episodes?.first(where: { $0.id == downloadItem.episodeId })
|
||||
let localMediaProgress = LocalMediaProgress(localLibraryItem: localLibraryItem, episode: episode, progress: progress)
|
||||
Database.shared.saveLocalMediaProgress(localMediaProgress)
|
||||
statusNotification["localMediaProgress"] = try? localMediaProgress.asDictionary()
|
||||
}
|
||||
|
|
|
@ -199,8 +199,7 @@ struct AudioTrack: Realmable, Codable {
|
|||
var contentUrl: String?
|
||||
var mimeType: String
|
||||
var metadata: FileMetadata?
|
||||
// var isLocal: Bool
|
||||
// var localFileId: String?
|
||||
var localFileId: String?
|
||||
// var audioProbeResult: AudioProbeResult? Needed for local playback
|
||||
var serverIndex: Int?
|
||||
|
||||
|
@ -208,6 +207,13 @@ struct AudioTrack: Realmable, Codable {
|
|||
duration = 0
|
||||
mimeType = ""
|
||||
}
|
||||
|
||||
mutating func setLocalInfo(filenameIdMap: [String: String], serverIndex: Int) {
|
||||
if let localFileId = filenameIdMap[self.metadata?.filename ?? ""] {
|
||||
self.localFileId = localFileId
|
||||
self.serverIndex = serverIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FileMetadata: Realmable, Codable {
|
||||
|
|
|
@ -121,6 +121,14 @@ extension DownloadItemPart {
|
|||
}
|
||||
|
||||
func mimeType() -> String? {
|
||||
audioTrack?.mimeType ?? episode?.audioTrack?.mimeType
|
||||
if let track = audioTrack {
|
||||
return track.mimeType
|
||||
} else if let podcastTrack = episode?.audioTrack {
|
||||
return podcastTrack.mimeType
|
||||
} else if serverPath?.hasSuffix("/cover") ?? false {
|
||||
return "image/jpg"
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,12 +11,12 @@ import Unrealm
|
|||
struct LocalLibraryItem: Realmable, Codable {
|
||||
var id: String = "local_\(UUID().uuidString)"
|
||||
var basePath: String = ""
|
||||
dynamic var _contentUrl: String?
|
||||
var _contentUrl: String?
|
||||
var isInvalid: Bool = false
|
||||
var mediaType: String = ""
|
||||
var media: MediaType?
|
||||
var localFiles: [LocalFile] = []
|
||||
dynamic var _coverContentUrl: String?
|
||||
var _coverContentUrl: String?
|
||||
var isLocal: Bool = true
|
||||
var serverConnectionConfigId: String?
|
||||
var serverAddress: String?
|
||||
|
@ -24,30 +24,20 @@ struct LocalLibraryItem: Realmable, Codable {
|
|||
var libraryItemId: String?
|
||||
|
||||
var contentUrl: String? {
|
||||
set(url) {
|
||||
_contentUrl = url
|
||||
}
|
||||
get {
|
||||
if let path = _contentUrl {
|
||||
return AbsDownloader.downloadsDirectory.appendingPathComponent(path).absoluteString
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var coverContentUrl: String? {
|
||||
set(url) {
|
||||
_coverContentUrl = url
|
||||
}
|
||||
get {
|
||||
if let path = self._coverContentUrl {
|
||||
return AbsDownloader.downloadsDirectory.appendingPathComponent(path).absoluteString
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func primaryKey() -> String? {
|
||||
return "id"
|
||||
|
@ -63,17 +53,15 @@ struct LocalLibraryItem: Realmable, Codable {
|
|||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try values.decode(String.self, forKey: .id)
|
||||
basePath = try values.decode(String.self, forKey: .basePath)
|
||||
contentUrl = try values.decode(String.self, forKey: .contentUrl)
|
||||
isInvalid = try values.decode(Bool.self, forKey: .isInvalid)
|
||||
mediaType = try values.decode(String.self, forKey: .mediaType)
|
||||
media = try values.decode(MediaType.self, forKey: .media)
|
||||
localFiles = try values.decode([LocalFile].self, forKey: .localFiles)
|
||||
coverContentUrl = try values.decode(String.self, forKey: .coverContentUrl)
|
||||
isLocal = try values.decode(Bool.self, forKey: .isLocal)
|
||||
serverConnectionConfigId = try values.decode(String.self, forKey: .serverConnectionConfigId)
|
||||
serverAddress = try values.decode(String.self, forKey: .serverAddress)
|
||||
serverUserId = try values.decode(String.self, forKey: .serverUserId)
|
||||
libraryItemId = try values.decode(String.self, forKey: .libraryItemId)
|
||||
serverConnectionConfigId = try? values.decode(String.self, forKey: .serverConnectionConfigId)
|
||||
serverAddress = try? values.decode(String.self, forKey: .serverAddress)
|
||||
serverUserId = try? values.decode(String.self, forKey: .serverUserId)
|
||||
libraryItemId = try? values.decode(String.self, forKey: .libraryItemId)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
|
@ -94,41 +82,23 @@ struct LocalLibraryItem: Realmable, Codable {
|
|||
}
|
||||
}
|
||||
|
||||
struct LocalPodcastEpisode: Realmable, Codable {
|
||||
var id: String = UUID().uuidString
|
||||
var index: Int = 0
|
||||
var episode: String?
|
||||
var episodeType: String?
|
||||
var title: String = "Unknown"
|
||||
var subtitle: String?
|
||||
var desc: String?
|
||||
var audioFile: AudioFile?
|
||||
var audioTrack: AudioTrack?
|
||||
var duration: Double = 0
|
||||
var size: Int = 0
|
||||
var serverEpisodeId: String?
|
||||
|
||||
static func primaryKey() -> String? {
|
||||
return "id"
|
||||
}
|
||||
}
|
||||
|
||||
struct LocalFile: Realmable, Codable {
|
||||
var id: String = UUID().uuidString
|
||||
var filename: String?
|
||||
var contentUrl: String = ""
|
||||
var absolutePath: String {
|
||||
return AbsDownloader.downloadsDirectory.appendingPathComponent(self.contentUrl).absoluteString
|
||||
}
|
||||
var _contentUrl: String = ""
|
||||
var mimeType: String?
|
||||
var size: Int = 0
|
||||
|
||||
var contentUrl: String {
|
||||
return AbsDownloader.downloadsDirectory.appendingPathComponent(_contentUrl).absoluteString
|
||||
}
|
||||
|
||||
static func primaryKey() -> String? {
|
||||
return "id"
|
||||
}
|
||||
|
||||
private enum CodingKeys : String, CodingKey {
|
||||
case id, filename, contentUrl, absolutePath, mimeType, size
|
||||
case id, filename, contentUrl, mimeType, size
|
||||
}
|
||||
|
||||
init() {}
|
||||
|
@ -137,8 +107,7 @@ struct LocalFile: Realmable, Codable {
|
|||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try values.decode(String.self, forKey: .id)
|
||||
filename = try values.decode(String.self, forKey: .filename)
|
||||
contentUrl = try values.decode(String.self, forKey: .contentUrl)
|
||||
mimeType = try values.decode(String.self, forKey: .mimeType)
|
||||
mimeType = try? values.decode(String.self, forKey: .mimeType)
|
||||
size = try values.decode(Int.self, forKey: .size)
|
||||
}
|
||||
|
||||
|
@ -147,7 +116,6 @@ struct LocalFile: Realmable, Codable {
|
|||
try container.encode(id, forKey: .id)
|
||||
try container.encode(filename, forKey: .filename)
|
||||
try container.encode(contentUrl, forKey: .contentUrl)
|
||||
try container.encode(absolutePath, forKey: .absolutePath)
|
||||
try container.encode(mimeType, forKey: .mimeType)
|
||||
try container.encode(size, forKey: .size)
|
||||
}
|
||||
|
|
|
@ -10,15 +10,32 @@ import Foundation
|
|||
extension LocalLibraryItem {
|
||||
init(_ item: LibraryItem, localUrl: String, server: ServerConnectionConfig, files: [LocalFile], coverPath: String?) {
|
||||
self.init()
|
||||
self.contentUrl = localUrl
|
||||
self._contentUrl = localUrl
|
||||
self.mediaType = item.mediaType
|
||||
self.media = item.media
|
||||
self.localFiles = files
|
||||
self.coverContentUrl = coverPath
|
||||
self._coverContentUrl = coverPath
|
||||
self.libraryItemId = item.id
|
||||
self.serverConnectionConfigId = server.id
|
||||
self.serverAddress = server.address
|
||||
self.serverUserId = server.userId
|
||||
|
||||
// Link the audio tracks and files
|
||||
var media = item.media
|
||||
let fileIdByFilename = Dictionary(uniqueKeysWithValues: files.map { ($0.filename ?? "", $0.id) } )
|
||||
if ( item.mediaType == "book" ) {
|
||||
if let tracks = media.tracks {
|
||||
for i in tracks.indices {
|
||||
media.tracks?[i].setLocalInfo(filenameIdMap: fileIdByFilename, serverIndex: i)
|
||||
}
|
||||
}
|
||||
} else if ( item.mediaType == "podcast" ) {
|
||||
if let episodes = media.episodes {
|
||||
for i in episodes.indices {
|
||||
media.episodes?[i].audioTrack?.setLocalInfo(filenameIdMap: fileIdByFilename, serverIndex: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
self.media = media
|
||||
}
|
||||
|
||||
func getDuration() -> Double {
|
||||
|
@ -27,7 +44,7 @@ extension LocalLibraryItem {
|
|||
return total
|
||||
}
|
||||
|
||||
func getPlaybackSession(episode: LocalPodcastEpisode?) -> PlaybackSession {
|
||||
func getPlaybackSession(episode: PodcastEpisode?) -> PlaybackSession {
|
||||
let localEpisodeId = episode?.id
|
||||
let sessionId = "play_local_\(UUID().uuidString)"
|
||||
|
||||
|
@ -49,7 +66,7 @@ extension LocalLibraryItem {
|
|||
id: sessionId,
|
||||
userId: self.serverUserId,
|
||||
libraryItemId: self.libraryItemId,
|
||||
episodeId: episode?.serverEpisodeId,
|
||||
episodeId: episode?.id,
|
||||
mediaType: self.mediaType,
|
||||
chapters: [],
|
||||
displayTitle: mediaMetadata?.title,
|
||||
|
@ -75,7 +92,7 @@ extension LocalFile {
|
|||
self.id = "\(libraryItemId)_\(filename.toBase64())"
|
||||
self.filename = filename
|
||||
self.mimeType = mimeType
|
||||
self.contentUrl = localUrl
|
||||
self._contentUrl = localUrl
|
||||
self.size = fileSize
|
||||
}
|
||||
|
||||
|
@ -91,7 +108,7 @@ extension LocalFile {
|
|||
}
|
||||
|
||||
extension LocalMediaProgress {
|
||||
init(localLibraryItem: LocalLibraryItem, episode: LocalPodcastEpisode?, progress: MediaProgress) {
|
||||
init(localLibraryItem: LocalLibraryItem, episode: PodcastEpisode?, progress: MediaProgress) {
|
||||
self.id = localLibraryItem.id
|
||||
self.localLibraryItemId = localLibraryItem.id
|
||||
self.libraryItemId = localLibraryItem.libraryItemId
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue