Skip to content

Commit

Permalink
Merge pull request #1 from mvasilak/reader-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka authored and mvasilak committed Dec 24, 2024
1 parent bfbde87 commit 7537286
Show file tree
Hide file tree
Showing 26 changed files with 720 additions and 716 deletions.
12 changes: 12 additions & 0 deletions Zotero.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
614D65822A79C9AC007CF449 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 614D65802A79C9AC007CF449 /* Localizable.stringsdict */; };
614D65832A79C9B0007CF449 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 614D65802A79C9AC007CF449 /* Localizable.stringsdict */; };
614D65872A8030C9007CF449 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = 614D65862A8030C9007CF449 /* OrderedCollections */; };
615FD8772C8B475A00808C1D /* ReaderCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 615FD8762C8B475A00808C1D /* ReaderCoordinator.swift */; };
6162F2512D076A990096FEEE /* ReaderAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6162F2502D076A990096FEEE /* ReaderAnnotation.swift */; };
61639F852AE03B8500026003 /* InstantPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61639F842AE03B8500026003 /* InstantPresenter.swift */; };
618404262A4456A9005AAF22 /* IdentifierLookupController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 618404252A4456A9005AAF22 /* IdentifierLookupController.swift */; };
618D83E72BAAC88C00E7966B /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 618D83E62BAAC88C00E7966B /* PrivacyInfo.xcprivacy */; };
Expand All @@ -45,6 +47,7 @@
61C817F22A49B5D30085B1E6 /* CollectionResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B1EDEE250242E700D8BC1E /* CollectionResponseSpec.swift */; };
61DE64D52C5BD0250096776C /* FormattedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DE64D42C5BD0250096776C /* FormattedTextView.swift */; };
61E24DCC2ABB385E00D75F50 /* OpenItemsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E24DCB2ABB385E00D75F50 /* OpenItemsController.swift */; };
61EB05B42C9D8EA200152482 /* CreateReaderAnnotationsDbRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61EB05B22C9D8EA200152482 /* CreateReaderAnnotationsDbRequest.swift */; };
61FA14CE2B05081D00E7D423 /* TextConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FA14CD2B05081D00E7D423 /* TextConverter.swift */; };
61FA14D02B08E24A00E7D423 /* ColorPickerStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FA14CF2B08E24A00E7D423 /* ColorPickerStackView.swift */; };
B300B33324291C8D00C1FE1E /* RTranslatorMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = B300B33224291C8D00C1FE1E /* RTranslatorMetadata.swift */; };
Expand Down Expand Up @@ -1315,6 +1318,8 @@
613F32782C1086950088EF70 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
614D65812A79C9AC007CF449 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
614D65842A7BCC22007CF449 /* ci_post_clone.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = ci_post_clone.sh; sourceTree = "<group>"; };
615FD8762C8B475A00808C1D /* ReaderCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderCoordinator.swift; sourceTree = "<group>"; };
6162F2502D076A990096FEEE /* ReaderAnnotation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderAnnotation.swift; sourceTree = "<group>"; };
61639F842AE03B8500026003 /* InstantPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPresenter.swift; sourceTree = "<group>"; };
618404252A4456A9005AAF22 /* IdentifierLookupController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentifierLookupController.swift; sourceTree = "<group>"; };
618D83E62BAAC88C00E7966B /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
Expand All @@ -1323,6 +1328,7 @@
61BD13942A5831EF008A0704 /* TextKit1TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextKit1TextView.swift; sourceTree = "<group>"; };
61DE64D42C5BD0250096776C /* FormattedTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormattedTextView.swift; sourceTree = "<group>"; };
61E24DCB2ABB385E00D75F50 /* OpenItemsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenItemsController.swift; sourceTree = "<group>"; };
61EB05B22C9D8EA200152482 /* CreateReaderAnnotationsDbRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateReaderAnnotationsDbRequest.swift; sourceTree = "<group>"; };
61FA14CD2B05081D00E7D423 /* TextConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextConverter.swift; sourceTree = "<group>"; };
61FA14CF2B08E24A00E7D423 /* ColorPickerStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorPickerStackView.swift; sourceTree = "<group>"; };
B300B33224291C8D00C1FE1E /* RTranslatorMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RTranslatorMetadata.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2427,6 +2433,7 @@
B305644323FC051E003304F2 /* CreateItemFromDetailDbRequest.swift */,
B305645D23FC051E003304F2 /* CreateNoteDbRequest.swift */,
B32861E328BF89CE007B5A5C /* CreatePDFAnnotationsDbRequest.swift */,
61EB05B22C9D8EA200152482 /* CreateReaderAnnotationsDbRequest.swift */,
B30BDDE528366F1B007034E8 /* CreateTranslatedItemsDbRequest.swift */,
B3100919272C00BA003FC743 /* CreateWebDavDeletionsDbRequest.swift */,
B37ACB922730338A002EF4E1 /* DeleteAllWebDavDeletionsDbRequest.swift */,
Expand Down Expand Up @@ -3265,6 +3272,8 @@
B3C3EC282C492A570062705A /* Trash */,
B3593F61241A62DD00760E20 /* DetailCoordinator.swift */,
B391E4182C3FFA8A00F1BEFC /* ParentWithSidebarController.swift */,
6162F2502D076A990096FEEE /* ReaderAnnotation.swift */,
615FD8762C8B475A00808C1D /* ReaderCoordinator.swift */,
);
path = Detail;
sourceTree = "<group>";
Expand Down Expand Up @@ -4979,8 +4988,10 @@
B3593F28241A61C700760E20 /* ItemDetailFieldCell.swift in Sources */,
B361A3012511F98700271173 /* LinkMode.swift in Sources */,
B3429B8124BDE73A008359FC /* UIDevice+Extensions.swift in Sources */,
61EB05B42C9D8EA200152482 /* CreateReaderAnnotationsDbRequest.swift in Sources */,
B3229FD128C0A07500DAF3B7 /* EditAnnotationRectsDbRequest.swift in Sources */,
B3DF9AD22747AAD2007933CB /* ApiRequest.swift in Sources */,
615FD8772C8B475A00808C1D /* ReaderCoordinator.swift in Sources */,
B3DCDF0E240912500039ED0D /* SinglePickerActionHandler.swift in Sources */,
B3593F162668E29C00FA4BB2 /* Style.swift in Sources */,
B3593F37241A61C700760E20 /* ItemDetailViewController.swift in Sources */,
Expand Down Expand Up @@ -5250,6 +5261,7 @@
B39AF554290033CD001F400F /* TableOfContentsViewController.swift in Sources */,
B3593F78241A76E600760E20 /* CollectionEditError.swift in Sources */,
B36181EC24C96B0500B30D56 /* SearchableCollection.swift in Sources */,
6162F2512D076A990096FEEE /* ReaderAnnotation.swift in Sources */,
B3830CDB255451AB00910FE0 /* TagPickerAction.swift in Sources */,
B3593F40241A61C700760E20 /* ItemCell.swift in Sources */,
61E24DCC2ABB385E00D75F50 /* OpenItemsController.swift in Sources */,
Expand Down
5 changes: 4 additions & 1 deletion Zotero/Controllers/AnnotationConverter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ struct AnnotationConverter {
let comment = annotation.contents.flatMap({ $0.trimmingCharacters(in: .whitespacesAndNewlines) }) ?? ""
let sortIndex = self.sortIndex(from: annotation, boundingBoxConverter: boundingBoxConverter)
let date = Date()
let dateAdded = annotation.creationDate ?? date
let dateModified = annotation.lastModified ?? date

let author: String
if isAuthor {
Expand Down Expand Up @@ -137,7 +139,8 @@ struct AnnotationConverter {
fontSize: fontSize,
rotation: rotation,
sortIndex: sortIndex,
dateModified: date
dateAdded: dateAdded,
dateModified: dateModified
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,96 +10,26 @@ import Foundation

import RealmSwift

struct CreateHtmlEpubAnnotationsDbRequest: DbRequest {
let attachmentKey: String
let libraryId: LibraryIdentifier
let annotations: [HtmlEpubAnnotation]
let userId: Int
class CreateHtmlEpubAnnotationsDbRequest: CreateReaderAnnotationsDbRequest<HtmlEpubAnnotation> {
override func addFields(for annotation: HtmlEpubAnnotation, to item: RItem, database: Realm) {
super.addFields(for: annotation, to: item, database: database)

unowned let schemaController: SchemaController
for field in FieldKeys.Item.Annotation.extraHtmlEpubFields(for: annotation.type) {
let value: String

var needsWrite: Bool { return true }
switch field.key {
case FieldKeys.Item.Annotation.pageLabel:
value = annotation.pageLabel

func process(in database: Realm) throws {
guard let parent = database.objects(RItem.self).filter(.key(attachmentKey, in: libraryId)).first else { return }

for annotation in annotations {
create(annotation: annotation, parent: parent, in: database)
}
}

private func create(annotation: HtmlEpubAnnotation, parent: RItem, in database: Realm) {
let item: RItem

if let _item = database.objects(RItem.self).filter(.key(annotation.key, in: libraryId)).first {
if !_item.deleted {
// If item exists and is not deleted locally, we can ignore this request
return
default:
continue
}

// If item exists and was already deleted locally and not yet synced, we re-add the item
item = _item
item.deleted = false
} else {
// If item didn't exist, create it
item = RItem()
item.key = annotation.key
item.rawType = ItemTypes.annotation
item.localizedType = schemaController.localized(itemType: ItemTypes.annotation) ?? ""
item.libraryId = libraryId
item.dateAdded = annotation.dateCreated
database.add(item)
}

item.annotationType = annotation.type.rawValue
item.syncState = .synced
item.changeType = .user
item.htmlFreeContent = annotation.comment.isEmpty ? nil : annotation.comment.strippedRichTextTags
item.dateModified = annotation.dateModified
item.parent = parent

if annotation.isAuthor {
item.createdBy = database.object(ofType: RUser.self, forPrimaryKey: userId)
}

addFields(for: annotation, to: item, database: database)
addTags(for: annotation, to: item, database: database)
// We need to submit tags on creation even if they are empty, so we need to mark them as changed
let changes: RItemChanges = [.parent, .fields, .type, .tags]
item.changes.append(RObjectChange.create(changes: changes))
}

private func addFields(for annotation: HtmlEpubAnnotation, to item: RItem, database: Realm) {
// Create basic fields
for field in FieldKeys.Item.Annotation.allHtmlEpubFields(for: annotation.type) {
let rField = RItemField()
rField.key = field.key
rField.baseKey = field.baseKey
rField.changed = true

switch (field.key, field.baseKey) {
case (FieldKeys.Item.Annotation.type, nil):
rField.value = annotation.type.rawValue

case (FieldKeys.Item.Annotation.color, nil):
rField.value = annotation.color

case (FieldKeys.Item.Annotation.comment, nil):
rField.value = annotation.comment

case (FieldKeys.Item.Annotation.pageLabel, nil):
rField.value = annotation.pageLabel

case (FieldKeys.Item.Annotation.sortIndex, nil):
rField.value = annotation.sortIndex
item.annotationSortIndex = annotation.sortIndex

case (FieldKeys.Item.Annotation.text, nil):
rField.value = annotation.text ?? ""

default: break
}

rField.value = value
item.fields.append(rField)
}

Expand All @@ -124,7 +54,7 @@ struct CreateHtmlEpubAnnotationsDbRequest: DbRequest {
}
}

private func addTags(for annotation: HtmlEpubAnnotation, to item: RItem, database: Realm) {
override func addTags(for annotation: HtmlEpubAnnotation, to item: RItem, database: Realm) {
let allTags = database.objects(RTag.self)

for tag in annotation.tags {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,95 +6,35 @@
// Copyright © 2022 Corporation for Digital Scholarship. All rights reserved.
//

import UIKit
import Foundation

import CocoaLumberjackSwift
import RealmSwift

struct CreatePDFAnnotationsDbRequest: DbRequest {
let attachmentKey: String
let libraryId: LibraryIdentifier
let annotations: [PDFDocumentAnnotation]
let userId: Int

unowned let schemaController: SchemaController
class CreatePDFAnnotationsDbRequest: CreateReaderAnnotationsDbRequest<PDFDocumentAnnotation> {
unowned let boundingBoxConverter: AnnotationBoundingBoxConverter

var needsWrite: Bool { return true }

func process(in database: Realm) throws {
guard let parent = database.objects(RItem.self).uniqueObject(key: attachmentKey, libraryId: libraryId) else { return }

for annotation in annotations {
create(annotation: annotation, parent: parent, in: database)
}
init(
attachmentKey: String,
libraryId: LibraryIdentifier,
annotations: [PDFDocumentAnnotation],
userId: Int,
schemaController: SchemaController,
boundingBoxConverter: AnnotationBoundingBoxConverter
) {
self.boundingBoxConverter = boundingBoxConverter
super.init(attachmentKey: attachmentKey, libraryId: libraryId, annotations: annotations, userId: userId, schemaController: schemaController)
}

private func create(annotation: PDFDocumentAnnotation, parent: RItem, in database: Realm) {
var fromRestore = false
let item: RItem

if let _item = database.objects(RItem.self).uniqueObject(key: annotation.key, libraryId: libraryId) {
if !_item.deleted {
// If item exists and is not deleted locally, we can ignore this request
return
}

// If item exists and was already deleted locally and not yet synced, we re-add the item
item = _item
item.deleted = false
fromRestore = true
} else {
// If item didn't exist, create it
item = RItem()
item.key = annotation.key
item.rawType = ItemTypes.annotation
item.localizedType = schemaController.localized(itemType: ItemTypes.annotation) ?? ""
item.libraryId = libraryId
item.dateAdded = annotation.dateModified
database.add(item)
}

item.annotationType = annotation.type.rawValue
item.syncState = .synced
item.changeType = .user
item.htmlFreeContent = annotation.comment.isEmpty ? nil : annotation.comment.strippedRichTextTags
item.dateModified = annotation.dateModified
item.parent = parent

if annotation.isAuthor {
let user = database.object(ofType: RUser.self, forPrimaryKey: userId)
item.createdBy = user
if user == nil {
DDLogWarn("CreatePDFAnnotationsDbRequest: user not found for userId \(userId)")
}
}

// We need to submit tags on creation even if they are empty, so we need to mark them as changed
var changes: RItemChanges = [.parent, .fields, .type, .tags]
self.addFields(for: annotation, to: item, database: database)
self.add(rects: annotation.rects, fromRestore: fromRestore, to: item, changes: &changes, database: database)
self.add(paths: annotation.paths, fromRestore: fromRestore, to: item, changes: &changes, database: database)
item.changes.append(RObjectChange.create(changes: changes))
}
override func addFields(for annotation: PDFDocumentAnnotation, to item: RItem, database: Realm) {
super.addFields(for: annotation, to: item, database: database)

private func addFields(for annotation: PDFDocumentAnnotation, to item: RItem, database: Realm) {
for field in FieldKeys.Item.Annotation.allPDFFields(for: annotation.type) {
for field in FieldKeys.Item.Annotation.extraPDFFields(for: annotation.type) {
let rField = RItemField()
rField.key = field.key
rField.baseKey = field.baseKey
rField.changed = true

switch field.key {
case FieldKeys.Item.Annotation.type:
rField.value = annotation.type.rawValue

case FieldKeys.Item.Annotation.color:
rField.value = annotation.color

case FieldKeys.Item.Annotation.comment:
rField.value = annotation.comment

case FieldKeys.Item.Annotation.Position.pageIndex where field.baseKey == FieldKeys.Item.Annotation.position:
rField.value = "\(annotation.page)"

Expand All @@ -104,26 +44,25 @@ struct CreatePDFAnnotationsDbRequest: DbRequest {
case FieldKeys.Item.Annotation.pageLabel:
rField.value = annotation.pageLabel

case FieldKeys.Item.Annotation.sortIndex:
rField.value = annotation.sortIndex
item.annotationSortIndex = annotation.sortIndex

case FieldKeys.Item.Annotation.text:
rField.value = annotation.text ?? ""

case FieldKeys.Item.Annotation.Position.rotation where field.baseKey == FieldKeys.Item.Annotation.position:
rField.value = "\(annotation.rotation ?? 0)"

case FieldKeys.Item.Annotation.Position.fontSize where field.baseKey == FieldKeys.Item.Annotation.position:
rField.value = "\(annotation.fontSize ?? 0)"

default: break
default:
break
}

item.fields.append(rField)
}
}

override func addAdditionalProperties(for annotation: PDFDocumentAnnotation, fromRestore: Bool, to item: RItem, changes: inout RItemChanges, database: Realm) {
add(rects: annotation.rects, fromRestore: fromRestore, to: item, changes: &changes, database: database)
add(paths: annotation.paths, fromRestore: fromRestore, to: item, changes: &changes, database: database)
}

private func add(rects: [CGRect], fromRestore: Bool, to item: RItem, changes: inout RItemChanges, database: Realm) {
if fromRestore {
item.rects.removeAll()
Expand Down
Loading

0 comments on commit 7537286

Please sign in to comment.