mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-07-30 15:45:14 +02:00
Rewrite of object model to use Unrealm
This addresses issues with JSON serialization
This commit is contained in:
parent
0b46a9c9b1
commit
f6c43e479d
12 changed files with 297 additions and 662 deletions
|
@ -8,49 +8,12 @@
|
|||
import Foundation
|
||||
|
||||
extension LocalLibraryItem {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case basePath
|
||||
case absolutePath
|
||||
case contentUrl
|
||||
case isInvalid
|
||||
case mediaType
|
||||
case media
|
||||
case localFiles
|
||||
case coverContentUrl
|
||||
case coverAbsolutePath
|
||||
case isLocal
|
||||
case serverConnectionConfigId
|
||||
case serverAddress
|
||||
case serverUserId
|
||||
case libraryItemId
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(basePath, forKey: .basePath)
|
||||
try container.encode(absolutePath, forKey: .absolutePath)
|
||||
try container.encode(contentUrl, forKey: .contentUrl)
|
||||
try container.encode(isInvalid, forKey: .isInvalid)
|
||||
try container.encode(mediaType, forKey: .mediaType)
|
||||
try container.encode(media, forKey: .media)
|
||||
try container.encode(localFiles, forKey: .localFiles)
|
||||
try container.encode(coverContentUrl, forKey: .coverContentUrl)
|
||||
try container.encode(coverAbsolutePath, forKey: .coverAbsolutePath)
|
||||
try container.encode(isLocal, forKey: .isLocal)
|
||||
try container.encode(serverConnectionConfigId, forKey: .serverConnectionConfigId)
|
||||
try container.encode(serverAddress, forKey: .serverAddress)
|
||||
try container.encode(serverUserId, forKey: .serverUserId)
|
||||
try container.encode(libraryItemId, forKey: .libraryItemId)
|
||||
}
|
||||
|
||||
convenience init(_ item: LibraryItem, localUrl: URL, server: ServerConnectionConfig, files: [LocalFile]) {
|
||||
init(_ item: LibraryItem, localUrl: URL, server: ServerConnectionConfig, files: [LocalFile]) {
|
||||
self.init()
|
||||
self.contentUrl = localUrl.absoluteString
|
||||
self.mediaType = item.mediaType
|
||||
self.media = LocalMediaType(item.media, coverPath: "", files: files)
|
||||
self.localFiles.append(objectsIn: files)
|
||||
self.media = item.media
|
||||
self.localFiles = files
|
||||
// TODO: self.coverContentURL
|
||||
// TODO: self.converAbsolutePath
|
||||
self.libraryItemId = item.id
|
||||
|
@ -61,7 +24,7 @@ extension LocalLibraryItem {
|
|||
|
||||
func getDuration() -> Double {
|
||||
var total = 0.0
|
||||
self.media?.tracks.forEach { track in total += track.duration }
|
||||
self.media?.tracks?.forEach { track in total += track.duration }
|
||||
return total
|
||||
}
|
||||
|
||||
|
@ -107,315 +70,14 @@ extension LocalLibraryItem {
|
|||
}
|
||||
}
|
||||
|
||||
extension LocalMediaType {
|
||||
enum CodingKeys: CodingKey {
|
||||
case libraryItemId
|
||||
case metadata
|
||||
case coverPath
|
||||
case tags
|
||||
case audioFiles
|
||||
case chapters
|
||||
case tracks
|
||||
case size
|
||||
case duration
|
||||
case episodes
|
||||
case autoDownloadEpisodes
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(libraryItemId, forKey: .libraryItemId)
|
||||
try container.encode(metadata, forKey: .metadata)
|
||||
try container.encode(coverPath, forKey: .coverPath)
|
||||
try container.encode(tags, forKey: .tags)
|
||||
try container.encode(audioFiles, forKey: .audioFiles)
|
||||
try container.encode(chapters, forKey: .chapters)
|
||||
try container.encode(tracks, forKey: .tracks)
|
||||
try container.encode(size, forKey: .size)
|
||||
try container.encode(duration, forKey: .duration)
|
||||
try container.encode(episodes, forKey: .episodes)
|
||||
try container.encode(autoDownloadEpisodes, forKey: .autoDownloadEpisodes)
|
||||
}
|
||||
|
||||
convenience init(_ mediaType: MediaType, coverPath: String, files: [LocalFile]) {
|
||||
self.init()
|
||||
self.libraryItemId = mediaType.libraryItemId
|
||||
self.metadata = LocalMetadata(mediaType.metadata)
|
||||
self.coverPath = coverPath
|
||||
self.tags.append(objectsIn: mediaType.tags ?? [])
|
||||
self.audioFiles.append(objectsIn: mediaType.audioFiles!.enumerated().map() {
|
||||
i, audioFile -> LocalAudioFile in LocalAudioFile(audioFile)
|
||||
})
|
||||
self.chapters.append(objectsIn: mediaType.chapters!.enumerated().map() {
|
||||
i, chapter -> LocalChapter in LocalChapter(chapter)
|
||||
})
|
||||
self.tracks.append(objectsIn: mediaType.tracks!.enumerated().map() {
|
||||
i, track in LocalAudioTrack(track, libraryItemId: self.libraryItemId ?? "", filename: files[i].filename ?? "")
|
||||
})
|
||||
self.size = mediaType.size
|
||||
self.duration = mediaType.duration
|
||||
// TODO: self.episodes
|
||||
// TODO: Handle podcast auto downloads
|
||||
self.autoDownloadEpisodes = mediaType.autoDownloadEpisodes
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalMetadata {
|
||||
enum CodingKeys: CodingKey {
|
||||
case title
|
||||
case subtitle
|
||||
case authors
|
||||
case narrators
|
||||
case genres
|
||||
case publishedYear
|
||||
case publishedDate
|
||||
case publisher
|
||||
case desc
|
||||
case isbn
|
||||
case asin
|
||||
case language
|
||||
case explicit
|
||||
case authorName
|
||||
case authorNameLF
|
||||
case narratorName
|
||||
case seriesName
|
||||
case feedUrl
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(subtitle, forKey: .subtitle)
|
||||
try container.encode(authors, forKey: .authors)
|
||||
try container.encode(narrators, forKey: .narrators)
|
||||
try container.encode(genres, forKey: .genres)
|
||||
try container.encode(publishedYear, forKey: .publishedYear)
|
||||
try container.encode(publishedDate, forKey: .publishedDate)
|
||||
try container.encode(publisher, forKey: .publisher)
|
||||
try container.encode(desc, forKey: .desc)
|
||||
try container.encode(isbn, forKey: .isbn)
|
||||
try container.encode(asin, forKey: .asin)
|
||||
try container.encode(language, forKey: .language)
|
||||
try container.encode(explicit, forKey: .explicit)
|
||||
try container.encode(authorName, forKey: .authorName)
|
||||
try container.encode(authorNameLF, forKey: .authorNameLF)
|
||||
try container.encode(narratorName, forKey: .narratorName)
|
||||
try container.encode(seriesName, forKey: .seriesName)
|
||||
try container.encode(feedUrl, forKey: .feedUrl)
|
||||
}
|
||||
|
||||
convenience init(_ metadata: Metadata) {
|
||||
self.init()
|
||||
self.title = metadata.title
|
||||
self.subtitle = metadata.subtitle
|
||||
self.narrators.append(objectsIn: metadata.narrators ?? [])
|
||||
self.genres.append(objectsIn: metadata.genres)
|
||||
self.publishedYear = metadata.publishedYear
|
||||
self.publishedDate = metadata.publishedDate
|
||||
self.publisher = metadata.publisher
|
||||
self.desc = metadata.description
|
||||
self.isbn = metadata.isbn
|
||||
self.asin = metadata.asin
|
||||
self.language = metadata.language
|
||||
self.explicit = metadata.explicit
|
||||
self.authorName = metadata.authorName
|
||||
self.authorNameLF = metadata.authorNameLF
|
||||
self.narratorName = metadata.narratorName
|
||||
self.seriesName = metadata.seriesName
|
||||
self.feedUrl = metadata.feedUrl
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalPodcastEpisode {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case index
|
||||
case episode
|
||||
case episodeType
|
||||
case title
|
||||
case subtitle
|
||||
case desc
|
||||
case audioFile
|
||||
case audioTrack
|
||||
case duration
|
||||
case size
|
||||
case serverEpisodeId
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(index, forKey: .index)
|
||||
try container.encode(episode, forKey: .episode)
|
||||
try container.encode(episodeType, forKey: .episodeType)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(subtitle, forKey: .subtitle)
|
||||
try container.encode(desc, forKey: .desc)
|
||||
try container.encode(audioFile, forKey: .audioFile)
|
||||
try container.encode(audioTrack, forKey: .audioTrack)
|
||||
try container.encode(duration, forKey: .duration)
|
||||
try container.encode(size, forKey: .size)
|
||||
try container.encode(serverEpisodeId, forKey: .serverEpisodeId)
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalAudioFile {
|
||||
enum CodingKeys: CodingKey {
|
||||
case index
|
||||
case ino
|
||||
case metadata
|
||||
}
|
||||
|
||||
convenience init(_ audioFile: AudioFile) {
|
||||
self.init()
|
||||
self.index = audioFile.index
|
||||
self.ino = audioFile.ino
|
||||
// self.metadata
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(index, forKey: .index)
|
||||
try container.encode(ino, forKey: .ino)
|
||||
try container.encode(metadata, forKey: .metadata)
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalAuthor {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case name
|
||||
case coverPath
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(name, forKey: .name)
|
||||
try container.encode(coverPath, forKey: .coverPath)
|
||||
}
|
||||
|
||||
convenience init(_ author: Author) {
|
||||
self.init()
|
||||
self.id = author.id
|
||||
self.name = author.name
|
||||
// self.coverPath
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalChapter {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case start
|
||||
case end
|
||||
case title
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(start, forKey: .start)
|
||||
try container.encode(end, forKey: .end)
|
||||
try container.encode(title, forKey: .title)
|
||||
}
|
||||
|
||||
convenience init(_ chapter: Chapter) {
|
||||
self.init()
|
||||
self.id = chapter.id
|
||||
self.start = chapter.start
|
||||
self.end = chapter.end
|
||||
self.title = chapter.title
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalAudioTrack {
|
||||
enum CodingKeys: CodingKey {
|
||||
case index
|
||||
case startOffset
|
||||
case duration
|
||||
case title
|
||||
case contentUrl
|
||||
case mimeType
|
||||
case metadata
|
||||
case isLocal
|
||||
case localFileId
|
||||
case serverIndex
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(index, forKey: .index)
|
||||
try container.encode(startOffset, forKey: .startOffset)
|
||||
try container.encode(duration, forKey: .duration)
|
||||
try container.encode(title, forKey: .title)
|
||||
try container.encode(contentUrl, forKey: .contentUrl)
|
||||
try container.encode(mimeType, forKey: .mimeType)
|
||||
try container.encode(metadata, forKey: .metadata)
|
||||
try container.encode(isLocal, forKey: .isLocal)
|
||||
try container.encode(localFileId, forKey: .localFileId)
|
||||
try container.encode(serverIndex, forKey: .serverIndex)
|
||||
}
|
||||
|
||||
convenience init(_ track: AudioTrack, libraryItemId: String, filename: String) {
|
||||
self.init()
|
||||
self.index = track.index
|
||||
self.startOffset = track.startOffset
|
||||
self.duration = track.duration
|
||||
self.title = track.title
|
||||
self.contentUrl = "" // TODO: Different URL
|
||||
self.mimeType = track.mimeType
|
||||
// TODO: self.metadata
|
||||
self.localFileId = "\(libraryItemId)_\(filename.toBase64())"
|
||||
self.serverIndex = track.serverIndex
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalFileMetadata {
|
||||
enum CodingKeys: CodingKey {
|
||||
case filename
|
||||
case ext
|
||||
case path
|
||||
case relPath
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(filename, forKey: .filename)
|
||||
try container.encode(ext, forKey: .ext)
|
||||
try container.encode(path, forKey: .path)
|
||||
try container.encode(relPath, forKey: .relPath)
|
||||
}
|
||||
|
||||
/* TODO: Can we skip this object? */
|
||||
}
|
||||
|
||||
extension LocalFile {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case filename
|
||||
case contentUrl
|
||||
case absolutePath
|
||||
case mimeType
|
||||
case size
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
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)
|
||||
}
|
||||
|
||||
convenience init(_ libraryItemId: String, _ filename: String, _ mimeType: String, _ localUrl: URL) {
|
||||
init(_ libraryItemId: String, _ filename: String, _ mimeType: String, _ localUrl: URL) {
|
||||
self.init()
|
||||
self.id = "\(libraryItemId)_\(filename.toBase64())"
|
||||
self.filename = filename
|
||||
self.contentUrl = localUrl.absoluteString
|
||||
self.absolutePath = localUrl.path
|
||||
self.size = localUrl.fileSize
|
||||
self.size = Int(localUrl.fileSize)
|
||||
}
|
||||
|
||||
func isAudioFile() -> Bool {
|
||||
|
@ -428,42 +90,3 @@ extension LocalFile {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension LocalMediaProgress {
|
||||
enum CodingKeys: CodingKey {
|
||||
case id
|
||||
case localLibraryItemId
|
||||
case localEpisodeId
|
||||
case duration
|
||||
case progress
|
||||
case currentTime
|
||||
case isFinished
|
||||
case lastUpdate
|
||||
case startedAt
|
||||
case finishedAt
|
||||
case serverConnectionConfigId
|
||||
case serverAddress
|
||||
case serverUserId
|
||||
case libraryItemId
|
||||
case episodeId
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(id, forKey: .id)
|
||||
try container.encode(localLibraryItemId, forKey: .localLibraryItemId)
|
||||
try container.encode(localEpisodeId, forKey: .localEpisodeId)
|
||||
try container.encode(duration, forKey: .duration)
|
||||
try container.encode(progress, forKey: .progress)
|
||||
try container.encode(currentTime, forKey: .currentTime)
|
||||
try container.encode(isFinished, forKey: .isFinished)
|
||||
try container.encode(lastUpdate, forKey: .lastUpdate)
|
||||
try container.encode(startedAt, forKey: .startedAt)
|
||||
try container.encode(finishedAt, forKey: .finishedAt)
|
||||
try container.encode(serverConnectionConfigId, forKey: .serverConnectionConfigId)
|
||||
try container.encode(serverAddress, forKey: .serverAddress)
|
||||
try container.encode(serverUserId, forKey: .serverUserId)
|
||||
try container.encode(libraryItemId, forKey: .libraryItemId)
|
||||
try container.encode(episodeId, forKey: .episodeId)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue