Add:iOS offline ebooks

This commit is contained in:
advplyr 2023-06-19 17:42:15 -05:00
parent 8b39ba9c92
commit 147f89f870
13 changed files with 157 additions and 26 deletions

View file

@ -17,6 +17,7 @@ class DownloadItemPart: Object, Codable {
@Persisted var serverPath: String?
@Persisted var audioTrack: AudioTrack?
@Persisted var episode: PodcastEpisode?
@Persisted var ebookFile: EBookFile?
@Persisted var completed: Bool = false
@Persisted var moved: Bool = false
@Persisted var failed: Bool = false
@ -63,7 +64,7 @@ class DownloadItemPart: Object, Codable {
}
extension DownloadItemPart {
convenience init(downloadItemId: String, filename: String, destination: String, itemTitle: String, serverPath: String, audioTrack: AudioTrack?, episode: PodcastEpisode?, size: Double) {
convenience init(downloadItemId: String, filename: String, destination: String, itemTitle: String, serverPath: String, audioTrack: AudioTrack?, episode: PodcastEpisode?, ebookFile: EBookFile?, size: Double) {
self.init()
self.id = destination.toBase64()
@ -74,6 +75,7 @@ extension DownloadItemPart {
self.serverPath = serverPath
self.audioTrack = AudioTrack.detachCopy(of: audioTrack)
self.episode = PodcastEpisode.detachCopy(of: episode)
self.ebookFile = EBookFile.detachCopy(of: ebookFile)
let config = Store.serverConfig!
var downloadUrl = "\(config.address)\(serverPath)?token=\(config.token)"
@ -101,6 +103,6 @@ extension DownloadItemPart {
}
func mimeType() -> String? {
audioTrack?.mimeType ?? episode?.audioTrack?.mimeType
audioTrack?.mimeType ?? episode?.audioTrack?.mimeType ?? ebookFile?.mimeType()
}
}

View file

@ -130,6 +130,12 @@ extension LocalLibraryItem {
for i in fromMedia.tracks.indices {
_ = fromMedia.tracks[i].setLocalInfo(filenameIdMap: fileIdByFilename, serverIndex: i)
}
if fromMedia.ebookFile != nil {
let ebookLocalFile = files.first(where: { $0.filename == fromMedia.ebookFile?.metadata?.filename ?? "" })
if ebookLocalFile != nil {
_ = fromMedia.ebookFile?.setLocalInfo(localFile: ebookLocalFile!)
}
}
} else if ( self.isPodcast ) {
let episodes = List<PodcastEpisode>()
for episode in fromMedia.episodes {

View file

@ -0,0 +1,78 @@
//
// EBookFile.swift
// Audiobookshelf
//
// Created by Advplyr on 6/19/23.
//
import Foundation
import RealmSwift
class EBookFile: EmbeddedObject, Codable {
@Persisted var ino: String = ""
@Persisted var metadata: FileMetadata?
@Persisted var ebookFormat: String
@Persisted var contentUrl: String?
@Persisted var localFileId: String?
private enum CodingKeys : String, CodingKey {
case ino, metadata, ebookFormat, contentUrl, localFileId
}
override init() {
super.init()
}
required init(from decoder: Decoder) throws {
super.init()
let values = try decoder.container(keyedBy: CodingKeys.self)
ino = try values.decode(String.self, forKey: .ino)
metadata = try values.decode(FileMetadata.self, forKey: .metadata)
ebookFormat = try values.decode(String.self, forKey: .ebookFormat)
contentUrl = try? values.decode(String.self, forKey: .contentUrl)
localFileId = try? values.decodeIfPresent(String.self, forKey: .localFileId)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(ino, forKey: .ino)
try container.encode(metadata, forKey: .metadata)
try container.encode(ebookFormat, forKey: .ebookFormat)
try container.encode(contentUrl, forKey: .contentUrl)
try container.encode(localFileId, forKey: .localFileId)
}
}
extension EBookFile {
func setLocalInfo(localFile: LocalFile) -> Bool {
self.localFileId = localFile.id
self.contentUrl = localFile.contentUrl
return false
}
func getLocalFile() -> LocalFile? {
guard let localFileId = self.localFileId else { return nil }
return Database.shared.getLocalFile(localFileId: localFileId)
}
func mimeType() -> String? {
var mimeType = ""
switch ebookFormat {
case "epub":
mimeType = "application/epub+zip"
case "pdf":
mimeType = "application/pdf"
case "mobi":
mimeType = "application/x-mobipocket-ebook"
case "azw3":
mimeType = "application/vnd.amazon.mobi8-ebook"
case "cbr":
mimeType = "application/vnd.comicbook-rar"
case "cbz":
mimeType = "application/vnd.comicbook+zip"
default:
mimeType = "application/epub+zip"
}
return mimeType
}
}

View file

@ -16,12 +16,14 @@ class MediaProgress: EmbeddedObject, Codable {
@Persisted var progress: Double = 0
@Persisted var currentTime: Double = 0
@Persisted var isFinished: Bool = false
@Persisted var ebookLocation: String?
@Persisted var ebookProgress: Double?
@Persisted var lastUpdate: Double = 0
@Persisted var startedAt: Double = 0
@Persisted var finishedAt: Double?
private enum CodingKeys : String, CodingKey {
case id, libraryItemId, episodeId, duration, progress, currentTime, isFinished, lastUpdate, startedAt, finishedAt
case id, libraryItemId, episodeId, duration, progress, currentTime, isFinished, ebookLocation, ebookProgress, lastUpdate, startedAt, finishedAt
}
override init() {
@ -37,6 +39,8 @@ class MediaProgress: EmbeddedObject, Codable {
progress = try values.doubleOrStringDecoder(key: .progress)
currentTime = try values.doubleOrStringDecoder(key: .currentTime)
isFinished = try values.decode(Bool.self, forKey: .isFinished)
ebookLocation = try values.decodeIfPresent(String.self, forKey: .ebookLocation)
ebookProgress = try values.doubleOrStringDecoder(key: .ebookProgress)
lastUpdate = try values.doubleOrStringDecoder(key: .lastUpdate)
startedAt = try values.doubleOrStringDecoder(key: .startedAt)
finishedAt = try? values.doubleOrStringDecoder(key: .finishedAt)
@ -51,6 +55,8 @@ class MediaProgress: EmbeddedObject, Codable {
try container.encode(progress, forKey: .progress)
try container.encode(currentTime, forKey: .currentTime)
try container.encode(isFinished, forKey: .isFinished)
try container.encode(ebookLocation, forKey: .ebookLocation)
try container.encode(ebookProgress, forKey: .ebookProgress)
try container.encode(lastUpdate, forKey: .lastUpdate)
try container.encode(startedAt, forKey: .startedAt)
try container.encode(finishedAt, forKey: .finishedAt)

View file

@ -14,6 +14,7 @@ class MediaType: EmbeddedObject, Codable {
@Persisted var coverPath: String?
@Persisted var tags = List<String>()
@Persisted var audioFiles = List<AudioFile>()
@Persisted var ebookFile: EBookFile?
@Persisted var chapters = List<Chapter>()
@Persisted var tracks = List<AudioTrack>()
@Persisted var size: Int?
@ -22,7 +23,7 @@ class MediaType: EmbeddedObject, Codable {
@Persisted var autoDownloadEpisodes: Bool?
private enum CodingKeys : String, CodingKey {
case libraryItemId, metadata, coverPath, tags, audioFiles, chapters, tracks, size, duration, episodes, autoDownloadEpisodes
case libraryItemId, metadata, coverPath, tags, audioFiles, ebookFile, chapters, tracks, size, duration, episodes, autoDownloadEpisodes
}
override init() {
@ -41,6 +42,7 @@ class MediaType: EmbeddedObject, Codable {
if let fileList = try? values.decode([AudioFile].self, forKey: .audioFiles) {
audioFiles.append(objectsIn: fileList)
}
ebookFile = try? values.decode(EBookFile.self, forKey: .ebookFile)
if let chapterList = try? values.decode([Chapter].self, forKey: .chapters) {
chapters.append(objectsIn: chapterList)
}
@ -62,6 +64,7 @@ class MediaType: EmbeddedObject, Codable {
try container.encode(coverPath, forKey: .coverPath)
try container.encode(Array(tags), forKey: .tags)
try container.encode(Array(audioFiles), forKey: .audioFiles)
try container.encode(ebookFile, forKey: .ebookFile)
try container.encode(Array(chapters), forKey: .chapters)
try container.encode(Array(tracks), forKey: .tracks)
try container.encode(size, forKey: .size)