Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show proper hierarchy when there is restored state #718

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion ZShare/ViewModels/ExtensionViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,13 @@ final class ExtensionViewModel {

recents = recentCollections
library = _library
collection = _collection
switch self.state.selectedCollectionId {
case .collection:
collection = _collection

default:
break
}
})

guard let library = library else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ struct ReadCollectionAndLibraryDbRequest: DbResponseRequest {
let rCollection = try ReadCollectionDbRequest(libraryId: self.libraryId, key: key).process(in: database)
let collection = Collection(object: rCollection, itemCount: 0)
return (collection, library)


case .custom(let type):
let collection = Collection(custom: type)
return (collection, library)

default:
return (nil, library)
}
Expand Down
24 changes: 20 additions & 4 deletions Zotero/Extensions/NSUserActivity+Activities.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Foundation
struct RestoredStateData {
let key: String
let libraryId: LibraryIdentifier
let collectionId: CollectionIdentifier
}

extension NSUserActivity {
Expand All @@ -21,9 +22,13 @@ extension NSUserActivity {
return NSUserActivity(activityType: self.mainId)
}

static func pdfActivity(for key: String, libraryId: LibraryIdentifier) -> NSUserActivity {
static func pdfActivity(for key: String, libraryId: LibraryIdentifier, collectionId: CollectionIdentifier) -> NSUserActivity {
let activity = NSUserActivity(activityType: self.pdfId)
activity.addUserInfoEntries(from: ["key": key, "libraryId": self.libraryIdToString(libraryId)])
var pdfUserInfo: [AnyHashable: Any] = ["key": key, "libraryId": libraryIdToString(libraryId)]
if let collectionIdData = try? JSONEncoder().encode(collectionId) {
pdfUserInfo["collectionId"] = collectionIdData
}
activity.addUserInfoEntries(from: pdfUserInfo)
return activity
}

Expand Down Expand Up @@ -54,7 +59,18 @@ extension NSUserActivity {

var restoredStateData: RestoredStateData? {
guard self.activityType == NSUserActivity.pdfId,
let key = self.userInfo?["key"] as? String, let libraryString = self.userInfo?["libraryId"] as? String, let libraryId = self.stringToLibraryId(libraryString) else { return nil }
return RestoredStateData(key: key, libraryId: libraryId)
let userInfo,
let key = userInfo["key"] as? String,
let libraryString = userInfo["libraryId"] as? String,
let libraryId = stringToLibraryId(libraryString)
else { return nil }
var collectionId: CollectionIdentifier
if let collectionIdData = userInfo["collectionId"] as? Data,
let decodedCollectionId = try? JSONDecoder().decode(CollectionIdentifier.self, from: collectionIdData) {
collectionId = decodedCollectionId
} else {
collectionId = Defaults.shared.selectedCollectionId
}
return RestoredStateData(key: key, libraryId: libraryId, collectionId: collectionId)
}
}
50 changes: 38 additions & 12 deletions Zotero/Scenes/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ final class AppCoordinator: NSObject {
guard let window = self.window else { return }

let viewController: UIViewController
var urlContext: UIOpenURLContext?
var data: RestoredStateData?
if !isLogged {
let controller = OnboardingViewController(size: window.frame.size, htmlConverter: self.controllers.htmlAttributedStringConverter)
controller.coordinatorDelegate = self
Expand All @@ -107,6 +109,7 @@ final class AppCoordinator: NSObject {
self.conflictAlertQueueController = nil
self.controllers.userControllers?.syncScheduler.syncController.set(coordinator: nil)
} else {
(urlContext, data) = preprocess(connectionOptions: connectionOptions, session: session)
let controller = MainViewController(controllers: self.controllers)
viewController = controller

Expand All @@ -117,12 +120,24 @@ final class AppCoordinator: NSObject {

DDLogInfo("AppCoordinator: show main screen logged \(isLogged ? "in" : "out"); animated=\(animated)")
self.show(viewController: viewController, in: window, animated: animated)
guard let options = connectionOptions, let session = session else { return }
self.process(connectionOptions: options, session: session)
process(urlContext: urlContext, data: data)
}

private func process(connectionOptions: UIScene.ConnectionOptions, session: UISceneSession) {
if let urlContext = connectionOptions.urlContexts.first, let urlController = self.controllers.userControllers?.customUrlController {
private func preprocess(connectionOptions: UIScene.ConnectionOptions?, session: UISceneSession?) -> (UIOpenURLContext?, RestoredStateData?) {
let urlContext = connectionOptions?.urlContexts.first
let userActivity = connectionOptions?.userActivities.first ?? session?.stateRestorationActivity
let data = userActivity?.restoredStateData
if let data {
// If scene had state stored, check if defaults need to be updated first
DDLogInfo("AppCoordinator: Preprocessing restored state - \(data)")
Defaults.shared.selectedLibrary = data.libraryId
Defaults.shared.selectedCollectionId = data.collectionId
}
return (urlContext, data)
}

private func process(urlContext: UIOpenURLContext?, data: RestoredStateData?) {
if let urlContext, let urlController = self.controllers.userControllers?.customUrlController {
// If scene was started from custom URL
let sourceApp = urlContext.options.sourceApplication ?? "unknown"
DDLogInfo("AppCoordinator: App launched by \(urlContext.url.absoluteString) from \(sourceApp)")
Expand All @@ -133,8 +148,8 @@ final class AppCoordinator: NSObject {
}
}

if let userActivity = connectionOptions.userActivities.first ?? session.stateRestorationActivity, let data = userActivity.restoredStateData {
DDLogInfo("AppCoordinator: Restored state - \(data)")
if let data {
DDLogInfo("AppCoordinator: Processing restored state - \(data)")
// If scene had state stored, restore state
self.showRestoredState(for: data)
}
Expand Down Expand Up @@ -218,9 +233,17 @@ final class AppCoordinator: NSObject {

private func showRestoredState(for data: RestoredStateData) {
guard let mainController = self.window?.rootViewController as? MainViewController,
let (url, library) = self.loadRestoredStateData(forKey: data.key, libraryId: data.libraryId) else { return }
DDLogInfo("AppCoordinator: show restored state - \(data.key); \(data.libraryId); \(url.relativePath)")

let (url, library, collection) = self.loadRestoredStateData(forKey: data.key, libraryId: data.libraryId, collectionId: data.collectionId) else { return }
if let collection {
DDLogInfo("AppCoordinator: show restored state - \(data.key); \(data.libraryId); \(data.collectionId); \(url.relativePath)")
mainController.showItems(for: collection, in: library, isInitial: false)
} else {
DDLogWarn("AppCoordinator: show restored state using all items collection - \(data.key); \(data.libraryId); \(url.relativePath)")
// Collection is missing, show all items instead
let collection = Collection(custom: .all)
mainController.showItems(for: collection, in: library, isInitial: true)
michalrentka marked this conversation as resolved.
Show resolved Hide resolved
}

mainController.getDetailCoordinator { [weak self] coordinator in
guard let self = self, let window = self.window else { return }
let controller = self.pdfController(key: data.key, library: library, url: url, page: nil, preselectedAnnotationKey: nil, detailCoordinator: coordinator)
Expand All @@ -240,11 +263,12 @@ final class AppCoordinator: NSObject {
return navigationController
}

private func loadRestoredStateData(forKey key: String, libraryId: LibraryIdentifier) -> (URL, Library)? {
private func loadRestoredStateData(forKey key: String, libraryId: LibraryIdentifier, collectionId: CollectionIdentifier) -> (URL, Library, Collection?)? {
guard let dbStorage = self.controllers.userControllers?.dbStorage else { return nil }

var url: URL?
var library: Library?
var collection: Collection?

do {
try dbStorage.perform(on: .main, with: { coordinator in
Expand All @@ -258,7 +282,9 @@ final class AppCoordinator: NSObject {
case .local, .localAndChangedRemotely:
let file = Files.attachmentFile(in: libraryId, key: key, filename: filename, contentType: contentType)
url = file.createUrl()
library = try coordinator.perform(request: ReadLibraryDbRequest(libraryId: libraryId))
let (_collection, _library) = try coordinator.perform(request: ReadCollectionAndLibraryDbRequest(collectionId: collectionId, libraryId: libraryId))
mvasilak marked this conversation as resolved.
Show resolved Hide resolved
collection = _collection
library = _library

case .remote, .remoteMissing: break
}
Expand All @@ -272,7 +298,7 @@ final class AppCoordinator: NSObject {
}

if let url = url, let library = library {
return (url, library)
return (url, library, collection)
}
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class PDFReaderViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

self.set(userActivity: .pdfActivity(for: self.viewModel.state.key, libraryId: self.viewModel.state.library.identifier))
self.set(userActivity: .pdfActivity(for: self.viewModel.state.key, libraryId: self.viewModel.state.library.identifier, collectionId: Defaults.shared.selectedCollectionId))

self.view.backgroundColor = .systemGray6
self.setupViews()
Expand Down
48 changes: 3 additions & 45 deletions Zotero/Scenes/Main/Views/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,8 @@ protocol MainCoordinatorSyncToolbarDelegate: AnyObject {
}

final class MainViewController: UISplitViewController {
private struct InitialLoadData {
let collection: Collection
let library: Library
}

// Constants
private let controllers: Controllers
private let defaultCollection: Collection
private let disposeBag: DisposeBag
// Variables
private var didAppear: Bool = false
Expand All @@ -54,7 +48,6 @@ final class MainViewController: UISplitViewController {

init(controllers: Controllers) {
self.controllers = controllers
self.defaultCollection = Collection(custom: .all)
self.disposeBag = DisposeBag()

super.init(nibName: nil, bundle: nil)
Expand Down Expand Up @@ -109,44 +102,6 @@ final class MainViewController: UISplitViewController {
self.showDetailViewController(navigationController, sender: nil)
}

private func loadInitialDetailData(collectionId: CollectionIdentifier, libraryId: LibraryIdentifier) -> InitialLoadData? {
guard let dbStorage = self.controllers.userControllers?.dbStorage else { return nil }

DDLogInfo("MainViewController: load initial detail data collectionId=\(collectionId); libraryId=\(libraryId)")

var collection: Collection?
var library: Library?

do {
try dbStorage.perform(on: .main, with: { coordinator in
switch collectionId {
case .collection(let key):
let rCollection = try coordinator.perform(request: ReadCollectionDbRequest(libraryId: libraryId, key: key))
collection = Collection(object: rCollection, itemCount: 0)

case .search(let key):
let rSearch = try coordinator.perform(request: ReadSearchDbRequest(libraryId: libraryId, key: key))
collection = Collection(object: rSearch)

case .custom(let type):
collection = Collection(custom: type)
}
library = try coordinator.perform(request: ReadLibraryDbRequest(libraryId: libraryId))
})
} catch let error {
DDLogError("MainViewController: can't load initial data - \(error)")
return nil
}

if let collection = collection, let library = library {
return InitialLoadData(collection: collection, library: library)
}

DDLogWarn("MainViewController: returning default library and collection")
return InitialLoadData(collection: Collection(custom: .all),
library: Library(identifier: .custom(.myLibrary), name: "My Library", metadataEditable: true, filesEditable: true))
}

// MARK: - Setups

private func setupControllers() {
Expand Down Expand Up @@ -178,6 +133,9 @@ extension MainViewController: UISplitViewControllerDelegate {

extension MainViewController: MainCoordinatorDelegate {
func showItems(for collection: Collection, in library: Library, isInitial: Bool) {
if !isInitial {
Defaults.shared.selectedCollectionId = collection.identifier
}
guard !self.isSplit || self.detailCoordinator?.library != library || self.detailCoordinator?.collection.identifier != collection.identifier else { return }
self.showItems(for: collection, in: library, searchItemKeys: nil)
}
Expand Down
3 changes: 0 additions & 3 deletions Zotero/Scenes/Master/MasterTopCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,6 @@ extension MasterTopCoordinator: MasterCollectionsCoordinatorDelegate {

func showItems(for collection: Collection, in library: Library, isInitial: Bool) {
self.visibleLibraryId = library.identifier
if !isInitial {
Defaults.shared.selectedCollectionId = collection.identifier
}
self.mainCoordinatorDelegate.showItems(for: collection, in: library, isInitial: isInitial)
}

Expand Down
Loading