diff --git a/Zotero/Controllers/OpenItemsController.swift b/Zotero/Controllers/OpenItemsController.swift index ecbf0da73..7876595e7 100644 --- a/Zotero/Controllers/OpenItemsController.swift +++ b/Zotero/Controllers/OpenItemsController.swift @@ -99,7 +99,7 @@ final class OpenItemsController { enum Presentation { case pdf(library: Library, key: String, parentKey: String?, url: URL) - case note(library: Library, key: String, text: String, tags: [Tag], title: NoteEditorState.TitleData?) + case note(library: Library, key: String, text: String, tags: [Tag], parentTitleData: NoteEditorState.TitleData?, title: String) } // MARK: Properties @@ -440,12 +440,9 @@ final class OpenItemsController { let library = try coordinator.perform(request: ReadLibraryDbRequest(libraryId: libraryId)) let rItem = try coordinator.perform(request: ReadItemDbRequest(libraryId: libraryId, key: key)) let note = Note(item: rItem) - var title: NoteEditorState.TitleData? - if let parent = rItem.parent { - title = NoteEditorState.TitleData(type: parent.rawType, title: parent.displayTitle) - } + let parentTitleData: NoteEditorState.TitleData? = rItem.parent.flatMap { .init(type: $0.rawType, title: $0.displayTitle) } guard let note else { return nil } - return .note(library: library, key: note.key, text: note.text, tags: note.tags, title: title) + return .note(library: library, key: note.key, text: note.text, tags: note.tags, parentTitleData: parentTitleData, title: note.title) } } diff --git a/Zotero/Scenes/AppCoordinator.swift b/Zotero/Scenes/AppCoordinator.swift index bbeef66fb..787e87a34 100644 --- a/Zotero/Scenes/AppCoordinator.swift +++ b/Zotero/Scenes/AppCoordinator.swift @@ -866,10 +866,10 @@ extension AppCoordinator: OpenItemsPresenter { case .pdf(let library, let key, let parentKey, let url): return coordinator.createPDFController(key: key, parentKey: parentKey, libraryId: library.identifier, url: url) - case .note(let library, let key, let text, let tags, let title): + 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) // TODO: Check if a callback is required - return coordinator.createNoteController(library: library, kind: kind, text: text, tags: tags, title: title) { _, _ in + return coordinator.createNoteController(library: library, kind: kind, text: text, tags: tags, parentTitleData: parentTitleData, title: title) { _, _ in } } }, diff --git a/Zotero/Scenes/Detail/DetailCoordinator.swift b/Zotero/Scenes/Detail/DetailCoordinator.swift index 4134e9938..451390245 100644 --- a/Zotero/Scenes/Detail/DetailCoordinator.swift +++ b/Zotero/Scenes/Detail/DetailCoordinator.swift @@ -67,7 +67,7 @@ protocol DetailItemDetailCoordinatorDelegate: AnyObject { } protocol DetailNoteEditorCoordinatorDelegate: AnyObject { - func showNote(library: Library, kind: NoteEditorKind, text: String, tags: [Tag], title: NoteEditorState.TitleData?, saveCallback: @escaping NoteEditorSaveCallback) + func showNote(library: Library, kind: NoteEditorKind, text: String, tags: [Tag], parentTitleData: NoteEditorState.TitleData?, title: String?, saveCallback: @escaping NoteEditorSaveCallback) } protocol ItemsTagFilterDelegate: AnyObject { @@ -528,7 +528,8 @@ extension DetailCoordinator: DetailItemsCoordinatorDelegate { kind: NoteEditorKind, text: String, tags: [Tag], - title: NoteEditorState.TitleData?, + parentTitleData: NoteEditorState.TitleData?, + title: String?, saveCallback: @escaping NoteEditorSaveCallback ) -> DetailNavigationViewController { let navigationController = DetailNavigationViewController() @@ -540,6 +541,7 @@ extension DetailCoordinator: DetailItemsCoordinatorDelegate { kind: kind, text: text, tags: tags, + parentTitleData: parentTitleData, title: title, saveCallback: saveCallback, navigationController: navigationController, @@ -1002,7 +1004,8 @@ extension DetailCoordinator: DetailNoteEditorCoordinatorDelegate { kind: NoteEditorKind, text: String = "", tags: [Tag] = [], - title: NoteEditorState.TitleData? = nil, + parentTitleData: NoteEditorState.TitleData? = nil, + title: String? = nil, saveCallback: @escaping NoteEditorSaveCallback = { _, _ in } ) { guard let navigationController else { return } @@ -1037,7 +1040,7 @@ extension DetailCoordinator: DetailNoteEditorCoordinatorDelegate { } showDetail(presentedBy: navigationController) { - self.createNoteController(library: library, kind: kind, text: text, tags: tags, title: title, saveCallback: amendedSaveCallback) + self.createNoteController(library: library, kind: kind, text: text, tags: tags, parentTitleData: parentTitleData, title: title, saveCallback: amendedSaveCallback) } } } @@ -1077,10 +1080,10 @@ extension DetailCoordinator: OpenItemsPresenter { case .pdf(let library, let key, let parentKey, let url): showPDF(at: url, key: key, parentKey: parentKey, libraryId: library.identifier) - case .note(let library, let key, let text, let tags, let title): + 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) // TODO: Check if a callback is required - showNote(library: library, kind: kind, text: text, tags: tags, title: title) + showNote(library: library, kind: kind, text: text, tags: tags, parentTitleData: parentTitleData, title: title) case .none: navigationController?.dismiss(animated: true) diff --git a/Zotero/Scenes/Detail/ItemDetail/Views/ItemDetailViewController.swift b/Zotero/Scenes/Detail/ItemDetail/Views/ItemDetailViewController.swift index 72bf205c5..3813d22bc 100644 --- a/Zotero/Scenes/Detail/ItemDetail/Views/ItemDetailViewController.swift +++ b/Zotero/Scenes/Detail/ItemDetail/Views/ItemDetailViewController.swift @@ -125,7 +125,8 @@ final class ItemDetailViewController: UIViewController { var kind: NoteEditorKind = .itemCreation(parentKey: viewModel.state.key) var text: String = "" var tags: [Tag] = [] - let title = NoteEditorState.TitleData(type: viewModel.state.data.type, title: viewModel.state.data.title) + var title: String? + let parentTitleData = NoteEditorState.TitleData(type: viewModel.state.data.type, title: viewModel.state.data.title) if let note { if library.metadataEditable { kind = .edit(key: note.key) @@ -134,8 +135,9 @@ final class ItemDetailViewController: UIViewController { } text = note.text tags = note.tags + title = note.title } - coordinatorDelegate?.showNote(library: library, kind: kind, text: text, tags: tags, title: title) { [weak self] key, result in + coordinatorDelegate?.showNote(library: library, kind: kind, text: text, tags: tags, parentTitleData: parentTitleData, title: title) { [weak self] key, result in self?.viewModel.process(action: .processNoteSaveResult(key: key, result: result)) } diff --git a/Zotero/Scenes/Detail/Items/Views/ItemsViewController.swift b/Zotero/Scenes/Detail/Items/Views/ItemsViewController.swift index 80081788b..4f51331a5 100644 --- a/Zotero/Scenes/Detail/Items/Views/ItemsViewController.swift +++ b/Zotero/Scenes/Detail/Items/Views/ItemsViewController.swift @@ -221,7 +221,7 @@ final class ItemsViewController: UIViewController { guard let note = Note(item: item) else { return } let tags = Array(item.tags.map({ Tag(tag: $0) })) let library = self.viewModel.state.library - coordinatorDelegate?.showNote(library: library, kind: .edit(key: note.key), text: note.text, tags: tags, title: nil) { [weak self] _, result in + coordinatorDelegate?.showNote(library: library, kind: .edit(key: note.key), text: note.text, tags: tags, parentTitleData: nil, title: note.title) { [weak self] _, result in self?.viewModel.process(action: .processNoteSaveResult(result)) } } diff --git a/Zotero/Scenes/General/Models/NoteEditorState.swift b/Zotero/Scenes/General/Models/NoteEditorState.swift index c03d68f0d..65e6c859f 100644 --- a/Zotero/Scenes/General/Models/NoteEditorState.swift +++ b/Zotero/Scenes/General/Models/NoteEditorState.swift @@ -26,16 +26,6 @@ struct NoteEditorState: ViewModelState { return false } } - - var key: String? { - switch self { - case .itemCreation, .standaloneCreation: - return nil - - case .edit(let key), .readOnly(let key): - return key - } - } } struct Changes: OptionSet { @@ -46,7 +36,7 @@ struct NoteEditorState: ViewModelState { static let tags = Changes(rawValue: 1 << 0) static let save = Changes(rawValue: 1 << 1) static let openItems = Changes(rawValue: 1 << 2) - static let activityTitle = Changes(rawValue: 1 << 3) + static let title = Changes(rawValue: 1 << 3) } struct TitleData { @@ -59,24 +49,24 @@ struct NoteEditorState: ViewModelState { } let library: Library - let title: TitleData? + let parentTitleData: TitleData? var kind: Kind var text: String var tags: [Tag] var changes: Changes var openItemsCount: Int - var activityTitle: String? + var title: String? - init(kind: Kind, library: Library, title: TitleData?, text: String, tags: [Tag], openItemsCount: Int, activityTitle: String?) { + init(kind: Kind, library: Library, parentTitleData: TitleData?, text: String, tags: [Tag], openItemsCount: Int, title: String?) { self.kind = kind self.text = text self.tags = tags self.library = library - self.title = title + self.parentTitleData = parentTitleData changes = [] self.openItemsCount = openItemsCount - self.activityTitle = activityTitle + self.title = title } mutating func cleanup() { diff --git a/Zotero/Scenes/General/NoteEditorCoordinator.swift b/Zotero/Scenes/General/NoteEditorCoordinator.swift index bf4c68af7..38f5136cf 100644 --- a/Zotero/Scenes/General/NoteEditorCoordinator.swift +++ b/Zotero/Scenes/General/NoteEditorCoordinator.swift @@ -31,7 +31,8 @@ final class NoteEditorCoordinator: NSObject, Coordinator { private let kind: NoteEditorKind private let initialText: String private let initialTags: [Tag] - private let title: NoteEditorState.TitleData? + private let parentTitleData: NoteEditorState.TitleData? + private let title: String? private let library: Library private let saveCallback: NoteEditorSaveCallback private let sessionIdentifier: String @@ -42,7 +43,8 @@ final class NoteEditorCoordinator: NSObject, Coordinator { kind: NoteEditorKind, text: String, tags: [Tag], - title: NoteEditorState.TitleData?, + parentTitleData: NoteEditorState.TitleData?, + title: String?, saveCallback: @escaping NoteEditorSaveCallback, navigationController: NavigationViewController, sessionIdentifier: String, @@ -51,6 +53,7 @@ final class NoteEditorCoordinator: NSObject, Coordinator { self.kind = kind initialText = text initialTags = tags + self.parentTitleData = parentTitleData self.title = title self.library = library self.saveCallback = saveCallback @@ -77,11 +80,11 @@ final class NoteEditorCoordinator: NSObject, Coordinator { let state = NoteEditorState( kind: kind, library: library, - title: title, + parentTitleData: parentTitleData, text: initialText, tags: initialTags, openItemsCount: openItemsController.getItems(for: sessionIdentifier).count, - activityTitle: kind.key.flatMap { (try? dbStorage.perform(request: ReadItemDbRequest(libraryId: library.identifier, key: $0), on: .main))?.displayTitle } + title: title ) let handler = NoteEditorActionHandler(dbStorage: dbStorage, schemaController: controllers.schemaController, saveCallback: saveCallback) let viewModel = ViewModel(initialState: state, handler: handler) diff --git a/Zotero/Scenes/General/ViewModels/NoteEditorActionHandler.swift b/Zotero/Scenes/General/ViewModels/NoteEditorActionHandler.swift index b117ecffd..0d7320245 100644 --- a/Zotero/Scenes/General/ViewModels/NoteEditorActionHandler.swift +++ b/Zotero/Scenes/General/ViewModels/NoteEditorActionHandler.swift @@ -102,7 +102,7 @@ struct NoteEditorActionHandler: ViewModelActionHandler, BackgroundDbProcessingAc state.kind = .edit(key: note.key) } saveCallback(note.key, .success((note: note, isCreated: true))) - updateActivityTitleIfNeeded(title: note.title) + updateTitleIfNeeded(title: note.title) case .failure(let error): DDLogError("NoteEditorActionHandler: can't create item note: \(error)") @@ -120,16 +120,16 @@ struct NoteEditorActionHandler: ViewModelActionHandler, BackgroundDbProcessingAc saveCallback(key, .failure(error)) } else { saveCallback(key, .success((note: note, isCreated: false))) - updateActivityTitleIfNeeded(title: note.title) + updateTitleIfNeeded(title: note.title) } } } - func updateActivityTitleIfNeeded(title: String) { - guard title != viewModel.state.activityTitle else { return } + func updateTitleIfNeeded(title: String) { + guard title != viewModel.state.title else { return } update(viewModel: viewModel) { state in - state.activityTitle = title - state.changes = [.activityTitle] + state.title = title + state.changes = [.title] } } } diff --git a/Zotero/Scenes/General/Views/NoteEditorViewController.swift b/Zotero/Scenes/General/Views/NoteEditorViewController.swift index 859c18cda..24ffe7ef9 100644 --- a/Zotero/Scenes/General/Views/NoteEditorViewController.swift +++ b/Zotero/Scenes/General/Views/NoteEditorViewController.swift @@ -52,10 +52,10 @@ final class NoteEditorViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - openItemsController.setOpenItemsUserActivity(from: self, libraryId: viewModel.state.library.identifier, title: viewModel.state.activityTitle) + openItemsController.setOpenItemsUserActivity(from: self, libraryId: viewModel.state.library.identifier, title: viewModel.state.title) - if let data = viewModel.state.title { - navigationItem.titleView = NoteEditorTitleView(type: data.type, title: data.title) + if let parentTitleData = viewModel.state.parentTitleData { + navigationItem.titleView = NoteEditorTitleView(type: parentTitleData.type, title: parentTitleData.title) } view.backgroundColor = .systemBackground @@ -115,7 +115,7 @@ final class NoteEditorViewController: UIViewController { if changedCurrentItem { forceSaveIfNeeded() } else if openItemsChanged { - openItemsController.setOpenItemsUserActivity(from: self, libraryId: viewModel.state.library.identifier, title: viewModel.state.activityTitle) + openItemsController.setOpenItemsUserActivity(from: self, libraryId: viewModel.state.library.identifier, title: viewModel.state.title) } } ) @@ -164,8 +164,8 @@ final class NoteEditorViewController: UIViewController { if state.changes.contains(.openItems) { setupNavbarItems(for: state) } - if state.changes.contains(.activityTitle) { - openItemsController.setOpenItemsUserActivity(from: self, libraryId: state.library.identifier, title: state.activityTitle) + if state.changes.contains(.title) { + openItemsController.setOpenItemsUserActivity(from: self, libraryId: state.library.identifier, title: state.title) } func debounceSave() {