Skip to content

Commit

Permalink
Implemented state restoration for html/epub reader
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka committed Aug 14, 2024
1 parent 79f868d commit 12e696c
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 18 deletions.
25 changes: 23 additions & 2 deletions Zotero/Controllers/OpenItemsController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ final class OpenItemsController {
struct Item: Hashable, Equatable, Codable {
enum Kind: Hashable, Equatable, Codable {
case pdf(libraryId: LibraryIdentifier, key: String)
case html(libraryId: LibraryIdentifier, key: String)
case epub(libraryId: LibraryIdentifier, key: String)
case note(libraryId: LibraryIdentifier, key: String)

// MARK: Properties
var libraryId: LibraryIdentifier {
switch self {
case .pdf(let libraryId, _), .note(let libraryId, _):
case .pdf(let libraryId, _), .note(let libraryId, _), .html(let libraryId, _), .epub(let libraryId, _):
return libraryId
}
}

var key: String {
switch self {
case .pdf(_, let key), .note(_, let key):
case .pdf(_, let key), .note(_, let key), .html(_, let key), .epub(_, let key):
return key
}
}
Expand All @@ -42,6 +44,12 @@ final class OpenItemsController {
case .pdf:
return Asset.Images.ItemTypes.pdf.image

case .html:
return Asset.Images.ItemTypes.webPageSnapshot.image

case .epub:
return Asset.Images.ItemTypes.document.image

case .note:
return Asset.Images.ItemTypes.note.image
}
Expand All @@ -51,6 +59,8 @@ final class OpenItemsController {
enum CodingKeys: CodingKey {
case pdfKind
case noteKind
case epubKind
case htmlKind
case libraryId
case key
}
Expand All @@ -61,6 +71,12 @@ final class OpenItemsController {
case .pdf:
try container.encode(true, forKey: .pdfKind)

case .epub:
try container.encode(true, forKey: .epubKind)

case .html:
try container.encode(true, forKey: .htmlKind)

case .note:
try container.encode(true, forKey: .noteKind)
}
Expand All @@ -77,6 +93,10 @@ final class OpenItemsController {
self = .pdf(libraryId: libraryId, key: key)
} else if (try? container.decode(Bool.self, forKey: .noteKind)) == true {
self = .note(libraryId: libraryId, key: key)
} else if (try? container.decode(Bool.self, forKey: .epubKind)) == true {
self = .epub(libraryId: libraryId, key: key)
} else if (try? container.decode(Bool.self, forKey: .htmlKind)) == true {
self = .html(libraryId: libraryId, key: key)
} else {
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [CodingKeys.pdfKind, CodingKeys.noteKind], debugDescription: "Item kind key not found"))
}
Expand All @@ -96,6 +116,7 @@ final class OpenItemsController {

enum Presentation {
case pdf(library: Library, key: String, parentKey: String?, url: URL)
case htmlEpub(library: Library, key: String, parentKey: String?, url: URL)
case note(library: Library, key: String, text: String, tags: [Tag], parentTitleData: NoteEditorState.TitleData?, title: String)
}
}
34 changes: 32 additions & 2 deletions Zotero/Scenes/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ extension AppCoordinator: AppDelegateCoordinatorDelegate {
case .pdf(let libraryId, let key):
presentation = try loadPDFPresentation(key: key, libraryId: libraryId, coordinator: coordinator)

case .html(let libraryId, let key), .epub(let libraryId, let key):
presentation = try loadEpubHtmlPresentation(key: key, libraryId: libraryId, coordinator: coordinator)

case .note(let libraryId, let key):
presentation = try loadNotePresentation(key: key, libraryId: libraryId, coordinator: coordinator)
}
Expand Down Expand Up @@ -279,6 +282,30 @@ extension AppCoordinator: AppDelegateCoordinatorDelegate {
guard let note else { return nil }
return .note(library: library, key: note.key, text: note.text, tags: note.tags, parentTitleData: parentTitleData, title: note.title)
}

func loadEpubHtmlPresentation(key: String, libraryId: LibraryIdentifier, coordinator: DbCoordinator) throws -> ItemPresentation? {
let library: Library = try coordinator.perform(request: ReadLibraryDbRequest(libraryId: libraryId))
let rItem = try coordinator.perform(request: ReadItemDbRequest(libraryId: libraryId, key: key))
let parentKey = rItem.parent?.key
guard let attachment = AttachmentCreator.attachment(for: rItem, fileStorage: controllers.fileStorage, urlDetector: nil) else { return nil }
var url: URL?
switch attachment.type {
case .file(let filename, let contentType, let location, _, _):
switch location {
case .local, .localAndChangedRemotely:
let file = Files.attachmentFile(in: libraryId, key: key, filename: filename, contentType: contentType)
url = file.createUrl()

case .remote, .remoteMissing:
break
}

case .url:
break
}
guard let url else { return nil }
return .htmlEpub(library: library, key: key, parentKey: parentKey, url: url)
}
}
}
}
Expand Down Expand Up @@ -408,7 +435,7 @@ extension AppCoordinator: AppDelegateCoordinatorDelegate {
let url = file.createUrl()
show(
viewControllerProvider: {
detailCoordinator.createPDFController(key: attachment.key, parentKey: parentKey, libraryId: libraryId, url: url, page: page, preselectedAnnotationKey: annotation)
detailCoordinator.createPdfController(key: attachment.key, parentKey: parentKey, libraryId: libraryId, url: url, page: page, preselectedAnnotationKey: annotation)
},
by: presenter,
in: window,
Expand Down Expand Up @@ -909,7 +936,10 @@ extension AppCoordinator: OpenItemsPresenter {
viewControllerProvider: {
switch presentation {
case .pdf(let library, let key, let parentKey, let url):
return coordinator.createPDFController(key: key, parentKey: parentKey, libraryId: library.identifier, url: url)
return coordinator.createPdfController(key: key, parentKey: parentKey, libraryId: library.identifier, url: url)

case .htmlEpub(let library, let key, let parentKey, let url):
return coordinator.createHtmlEpubController(key: key, parentKey: parentKey, libraryId: library.identifier, url: url)

case .note(let library, let key, let text, let tags, let parentTitleData, let title):
let kind: NoteEditorKind = library.metadataEditable ? .edit(key: key) : .readOnly(key: key)
Expand Down
25 changes: 14 additions & 11 deletions Zotero/Scenes/Detail/DetailCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ final class DetailCoordinator: Coordinator {

case "text/html", "application/epub+zip":
DDLogInfo("DetailCoordinator: show HTML / EPUB \(attachment.key)")
showHtmlEpubReader(for: url, key: attachment.key, libraryId: libraryId)
showHtmlEpubReader(for: url, key: attachment.key, parentKey: parentKey, libraryId: libraryId)

case "text/plain":
let text = try? String(contentsOf: url, encoding: .utf8)
Expand Down Expand Up @@ -286,7 +286,7 @@ final class DetailCoordinator: Coordinator {
navigationController.present(controller, animated: true, completion: nil)
}

func createPDFController(key: String, parentKey: String?, libraryId: LibraryIdentifier, url: URL, page: Int? = nil, preselectedAnnotationKey: String? = nil) -> NavigationViewController {
func createPdfController(key: String, parentKey: String?, libraryId: LibraryIdentifier, url: URL, page: Int? = nil, preselectedAnnotationKey: String? = nil) -> NavigationViewController {
let navigationController = NavigationViewController()
navigationController.modalPresentationStyle = .fullScreen

Expand All @@ -306,22 +306,25 @@ final class DetailCoordinator: Coordinator {

return navigationController
}

private func showPDF(at url: URL, key: String, parentKey: String?, libraryId: LibraryIdentifier) {
let controller = createPDFController(key: key, parentKey: parentKey, libraryId: libraryId, url: url)
navigationController?.present(controller, animated: true, completion: nil)
}

private func showHtmlEpubReader(for url: URL, key: String, libraryId: LibraryIdentifier) {
func createHtmlEpubController(key: String, parentKey: String?, libraryId: LibraryIdentifier, url: URL) -> NavigationViewController {
let navigationController = NavigationViewController()
navigationController.modalPresentationStyle = .fullScreen

let coordinator = HtmlEpubCoordinator(key: key, libraryId: libraryId, url: url, navigationController: navigationController, controllers: controllers)
let coordinator = HtmlEpubCoordinator(key: key, parentKey: parentKey, libraryId: libraryId, url: url, navigationController: navigationController, controllers: controllers)
coordinator.parentCoordinator = self
self.childCoordinators.append(coordinator)
coordinator.start(animated: false)
return navigationController
}

self.navigationController?.present(navigationController, animated: true, completion: nil)
private func showPdf(at url: URL, key: String, parentKey: String?, libraryId: LibraryIdentifier) {
let controller = createPdfController(key: key, parentKey: parentKey, libraryId: libraryId, url: url)
navigationController?.present(controller, animated: true, completion: nil)
}

private func showHtmlEpubReader(for url: URL, key: String, parentKey: String?, libraryId: LibraryIdentifier) {
let controller = createHtmlEpubController(key: key, parentKey: parentKey, libraryId: libraryId, url: url)
self.navigationController?.present(controller, animated: true, completion: nil)
}

private func showWebView(for url: URL) {
Expand Down
15 changes: 13 additions & 2 deletions Zotero/Scenes/Detail/HTML:EPUB/HtmlEpubCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ final class HtmlEpubCoordinator: Coordinator {
weak var navigationController: UINavigationController?

private let key: String
private let parentKey: String?
private let libraryId: LibraryIdentifier
private let url: URL
private unowned let controllers: Controllers
private let disposeBag: DisposeBag

init(key: String, libraryId: LibraryIdentifier, url: URL, navigationController: NavigationViewController, controllers: Controllers) {
init(key: String, parentKey: String?, libraryId: LibraryIdentifier, url: URL, navigationController: NavigationViewController, controllers: Controllers) {
self.key = key
self.parentKey = parentKey
self.libraryId = libraryId
self.url = url
self.navigationController = navigationController
Expand Down Expand Up @@ -90,7 +92,16 @@ final class HtmlEpubCoordinator: Coordinator {
fileStorage: controllers.fileStorage,
idleTimerController: controllers.idleTimerController
)
let state = HtmlEpubReaderState(url: url, key: key, settings: Defaults.shared.htmlEpubSettings, libraryId: libraryId, userId: userId, username: username)
let state = HtmlEpubReaderState(
url: url,
key: key,
parentKey: parentKey,
title: try? dbStorage.perform(request: ReadFilenameDbRequest(libraryId: libraryId, key: key), on: .main),
settings: Defaults.shared.htmlEpubSettings,
libraryId: libraryId,
userId: userId,
username: username
)
let controller = HtmlEpubReaderViewController(
viewModel: ViewModel(initialState: state, handler: handler),
compactSize: UIDevice.current.isCompactWidth(size: parentNavigationController.view.frame.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ struct HtmlEpubReaderState: ViewModelState {
let readerFile: File
let documentFile: File
let key: String
let parentKey: String?
let library: Library
let title: String?
let userId: Int
let username: String
let commentFont: UIFont
Expand Down Expand Up @@ -95,13 +97,15 @@ struct HtmlEpubReaderState: ViewModelState {
var notificationToken: NotificationToken?
var deletionEnabled: Bool

init(url: URL, key: String, settings: HtmlEpubSettings, libraryId: LibraryIdentifier, userId: Int, username: String) {
init(url: URL, key: String, parentKey: String?, title: String?, settings: HtmlEpubSettings, libraryId: LibraryIdentifier, userId: Int, username: String) {
let originalFile = Files.file(from: url)
let temporaryDirectory = Files.tmpReaderDirectory
self.originalFile = originalFile
readerFile = temporaryDirectory.copy(withName: "view", ext: "html")
documentFile = temporaryDirectory.appending(relativeComponent: "content").copy(withName: originalFile.name, ext: originalFile.ext)
self.key = key
self.parentKey = parentKey
self.title = title
self.settings = settings
self.userId = userId
self.username = username
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ class HtmlEpubReaderViewController: UIViewController, ParentWithSidebarControlle
override func viewDidLoad() {
super.viewDidLoad()

setActivity()
view.backgroundColor = .systemBackground
observeViewModel()
setupNavigationBar()
Expand Down Expand Up @@ -220,6 +221,22 @@ class HtmlEpubReaderViewController: UIViewController, ParentWithSidebarControlle
controller.didMove(toParent: self)
}
}

func setActivity() {
let kind: OpenItem.Kind
switch viewModel.state.documentFile.ext.lowercased() {
case "epub":
kind = .epub(libraryId: viewModel.state.library.identifier, key: viewModel.state.key)

case "html", "htm":
kind = .html(libraryId: viewModel.state.library.identifier, key: viewModel.state.key)

default:
return
}
let openItem = OpenItem(kind: kind, userIndex: 0)
set(userActivity: .contentActivity(with: [openItem], libraryId: viewModel.state.library.identifier, collectionId: Defaults.shared.selectedCollectionId).set(title: viewModel.state.title))
}
}

override func viewIsAppearing(_ animated: Bool) {
Expand Down

0 comments on commit 12e696c

Please sign in to comment.