Skip to content

Commit

Permalink
Bug fixes, only show annotations which are listed as supported
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka committed Mar 8, 2024
1 parent 5bfa585 commit 68b9b5e
Show file tree
Hide file tree
Showing 19 changed files with 255 additions and 166 deletions.
8 changes: 5 additions & 3 deletions Zotero.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,8 @@
B33E8A4C27B6A7BE00CBC7DE /* SearchableCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B36181EB24C96B0500B30D56 /* SearchableCollection.swift */; };
B33E8A4D27B6AAE600CBC7DE /* CollectionCellContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B34673CE27B14F0D00444C96 /* CollectionCellContentView.swift */; };
B33E8A4E27B6AAF000CBC7DE /* CollectionCellContentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B37D8E6324DC21D300F526C5 /* CollectionCellContentView.xib */; };
B3401D572567D8F700BB8D6E /* AnnotationPopoverViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3401D552567D8F700BB8D6E /* AnnotationPopoverViewController.swift */; };
B33EB2BA2B076657003255DA /* Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B37080512AA72135006F56B9 /* Localizable.swift */; };
B3401D572567D8F700BB8D6E /* AnnotationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3401D552567D8F700BB8D6E /* AnnotationViewController.swift */; };
B3401D572567D8F700BB8D6E /* AnnotationPopoverViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3401D552567D8F700BB8D6E /* AnnotationPopoverViewController.swift */; };
B3401D5B2567DAAE00BB8D6E /* AnnotationPopoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3401D5A2567DAAE00BB8D6E /* AnnotationPopoverCoordinator.swift */; };
B3401D612568047D00BB8D6E /* AnnotationViewTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3401D602568047D00BB8D6E /* AnnotationViewTextView.swift */; };
B340692224A60D6A009ECE48 /* Rounding+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B340692124A60D6A009ECE48 /* Rounding+Extensions.swift */; };
Expand Down Expand Up @@ -909,6 +908,7 @@
B3ADAE4D2833BED300D46271 /* LookupActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3ADAE4C2833BED300D46271 /* LookupActionHandler.swift */; };
B3ADAE4F2833BEDC00D46271 /* LookupState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3ADAE4E2833BEDC00D46271 /* LookupState.swift */; };
B3ADAE512833BEE300D46271 /* LookupAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3ADAE502833BEE300D46271 /* LookupAction.swift */; };
B3AED7212B98828F000FCD18 /* PSPDFKItAnnotation+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3AED7202B98828F000FCD18 /* PSPDFKItAnnotation+Extensions.swift */; };
B3AFB83C2A0CE82C008C2374 /* EmptyDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3AFB83B2A0CE82C008C2374 /* EmptyDecodable.swift */; };
B3AFB83D2A0CF1EE008C2374 /* EmptyDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3AFB83B2A0CE82C008C2374 /* EmptyDecodable.swift */; };
B3B1C5842664E23A00883597 /* ReadItemsForUploadDbRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B1C5832664E23A00883597 /* ReadItemsForUploadDbRequest.swift */; };
Expand Down Expand Up @@ -1030,7 +1030,6 @@
B3DCDF1F240945B40039ED0D /* CollectionsPickerActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DCDF1E240945B30039ED0D /* CollectionsPickerActionHandler.swift */; };
B3DCDF21240945D80039ED0D /* CollectionsPickerState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DCDF20240945D80039ED0D /* CollectionsPickerState.swift */; };
B3DCDF23240945FA0039ED0D /* CollectionsPickerAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DCDF22240945FA0039ED0D /* CollectionsPickerAction.swift */; };
B3DD197B2B0CA7840042C46D /* Localizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B37080512AA72135006F56B9 /* Localizable.swift */; };
B3DDACE928E6F52E0063407E /* CustomURLController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DDACE828E6F52E0063407E /* CustomURLController.swift */; };
B3DDC0CB2667824D00B2DFD1 /* RegularExpression+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DDC0CA2667824D00B2DFD1 /* RegularExpression+Extensions.swift */; };
B3DDC0CC2667825E00B2DFD1 /* RegularExpression+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3DDC0CA2667824D00B2DFD1 /* RegularExpression+Extensions.swift */; };
Expand Down Expand Up @@ -1884,6 +1883,7 @@
B3ADAE4C2833BED300D46271 /* LookupActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LookupActionHandler.swift; sourceTree = "<group>"; };
B3ADAE4E2833BEDC00D46271 /* LookupState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LookupState.swift; sourceTree = "<group>"; };
B3ADAE502833BEE300D46271 /* LookupAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LookupAction.swift; sourceTree = "<group>"; };
B3AED7202B98828F000FCD18 /* PSPDFKItAnnotation+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PSPDFKItAnnotation+Extensions.swift"; sourceTree = "<group>"; };
B3AFB83B2A0CE82C008C2374 /* EmptyDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyDecodable.swift; sourceTree = "<group>"; };
B3B1C5832664E23A00883597 /* ReadItemsForUploadDbRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadItemsForUploadDbRequest.swift; sourceTree = "<group>"; };
B3B1C58526651E2A00883597 /* StorageSettingsActionHandlerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageSettingsActionHandlerSpec.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3693,6 +3693,7 @@
B310280C2B1E16F300E41554 /* PDFThumbnailsAction.swift */,
B373C98E2B1F5431007FD56C /* PDFThumbnailsLayout.swift */,
B310280A2B1E16EC00E41554 /* PDFThumbnailsState.swift */,
B3AED7202B98828F000FCD18 /* PSPDFKItAnnotation+Extensions.swift */,
B37BF0AA25A5E2AD00AE0268 /* SquareAnnotation.swift */,
B3A47C3729015FDD00E7D90D /* TableOfContentsAction.swift */,
B3A47C3929015FE800E7D90D /* TableOfContentsState.swift */,
Expand Down Expand Up @@ -5249,6 +5250,7 @@
B30BDDE42836642D007034E8 /* FilenameFormatter.swift in Sources */,
B3E381D325F2D78A00F046CE /* ApiLogger.swift in Sources */,
B3E8FE192714297200F51458 /* CiteAction.swift in Sources */,
B3AED7212B98828F000FCD18 /* PSPDFKItAnnotation+Extensions.swift in Sources */,
B3A2AEDC2656511D004BF3A4 /* StylesRequest.swift in Sources */,
B3F3D62C255EBE3500F310C2 /* AnnotationViewHeader.swift in Sources */,
B3E8FE34271429C300F51458 /* ExportLocalePickerView.swift in Sources */,
Expand Down
5 changes: 3 additions & 2 deletions Zotero/Controllers/AnnotationConverter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ struct AnnotationConverter {
username: String,
boundingBoxConverter: AnnotationBoundingBoxConverter
) -> [PSPDFKit.Annotation] {
return items.map({ item in
return items.compactMap({ item in
guard let annotation = PDFDatabaseAnnotation(item: item) else { return nil }
return self.annotation(
from: PDFDatabaseAnnotation(item: item),
from: annotation,
type: type,
interfaceStyle: interfaceStyle,
currentUserId: currentUserId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ struct CreatePDFAnnotationsDbRequest: DbRequest {
var needsWrite: Bool { return true }

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

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

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

if let _item = database.objects(RItem.self).filter(.key(annotation.key, in: self.libraryId)).first {
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
Expand All @@ -46,12 +46,13 @@ struct CreatePDFAnnotationsDbRequest: DbRequest {
item = RItem()
item.key = annotation.key
item.rawType = ItemTypes.annotation
item.localizedType = self.schemaController.localized(itemType: ItemTypes.annotation) ?? ""
item.libraryId = self.libraryId
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
Expand Down Expand Up @@ -117,12 +118,12 @@ struct CreatePDFAnnotationsDbRequest: DbRequest {
}

private func add(rects: [CGRect], to item: RItem, changes: inout RItemChanges, database: Realm) {
guard !rects.isEmpty else { return }
guard !rects.isEmpty, let annotation = PDFDatabaseAnnotation(item: item) else { return }

let page = UInt(PDFDatabaseAnnotation(item: item).page)
let page = UInt(annotation.page)

for rect in rects {
let dbRect = self.boundingBoxConverter.convertToDb(rect: rect, page: page) ?? rect
let dbRect = boundingBoxConverter.convertToDb(rect: rect, page: page) ?? rect

let rRect = RRect()
rRect.minX = Double(dbRect.minX)
Expand All @@ -135,16 +136,16 @@ struct CreatePDFAnnotationsDbRequest: DbRequest {
}

private func add(paths: [[CGPoint]], to item: RItem, changes: inout RItemChanges, database: Realm) {
guard !paths.isEmpty else { return }
guard !paths.isEmpty, let annotation = PDFDatabaseAnnotation(item: item) else { return }

let page = UInt(PDFDatabaseAnnotation(item: item).page)
let page = UInt(annotation.page)

for (idx, path) in paths.enumerated() {
let rPath = RPath()
rPath.sortIndex = idx

for (idy, point) in path.enumerated() {
let dbPoint = self.boundingBoxConverter.convertToDb(point: point, page: page) ?? point
let dbPoint = boundingBoxConverter.convertToDb(point: point, page: page) ?? point

let rXCoordinate = RPathCoordinate()
rXCoordinate.value = Double(dbPoint.x)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ struct EditAnnotationPathsDbRequest: DbRequest {
var needsWrite: Bool { return true }

func process(in database: Realm) throws {
guard let item = database.objects(RItem.self).filter(.key(self.key, in: self.libraryId)).first else { return }
let page = UInt(PDFDatabaseAnnotation(item: item).page)
let dbPaths = self.paths.map { path in
return path.map({ self.boundingBoxConverter.convertToDb(point: $0, page: page) ?? $0 })
guard let item = database.objects(RItem.self).filter(.key(key, in: libraryId)).first, let annotation = PDFDatabaseAnnotation(item: item) else { return }
let page = UInt(annotation.page)
let dbPaths = paths.map { path in
return path.map({ boundingBoxConverter.convertToDb(point: $0, page: page) ?? $0 })
}
guard self.paths(dbPaths, differFrom: item.paths) else { return }
self.sync(paths: dbPaths, in: item, database: database)
guard paths(dbPaths, differFrom: item.paths) else { return }
sync(paths: dbPaths, in: item, database: database)
}

private func sync(paths: [[CGPoint]], in item: RItem, database: Realm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ struct EditAnnotationRectsDbRequest: DbRequest {
var needsWrite: Bool { return true }

func process(in database: Realm) throws {
guard let item = database.objects(RItem.self).filter(.key(self.key, in: self.libraryId)).first else { return }
let page = UInt(PDFDatabaseAnnotation(item: item).page)
let dbRects = self.rects.map({ self.boundingBoxConverter.convertToDb(rect: $0, page: page) ?? $0 })
guard self.rects(dbRects, differFrom: item.rects) else { return }
self.sync(rects: dbRects, in: item, database: database)
guard let item = database.objects(RItem.self).filter(.key(key, in: libraryId)).first, let annotation = PDFDatabaseAnnotation(item: item) else { return }
let page = UInt(annotation.page)
let dbRects = rects.map({ boundingBoxConverter.convertToDb(rect: $0, page: page) ?? $0 })
guard rects(dbRects, differFrom: item.rects) else { return }
sync(rects: dbRects, in: item, database: database)
}

private func sync(rects: [CGRect], in item: RItem, database: Realm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ struct ReadAnnotationsDbRequest: DbResponseRequest {
var needsWrite: Bool { return false }

func process(in database: Realm) throws -> Results<RItem> {
let supportedTypes = AnnotationType.allCases.filter({ AnnotationsConfig.supported.contains($0.kind) }).map({ $0.rawValue })
return database.objects(RItem.self).filter(.parent(self.attachmentKey, in: self.libraryId))
.filter(.items(type: ItemTypes.annotation, notSyncState: .dirty))
.filter(.deleted(false))
.filter("annotationType in %@", supportedTypes)
.sorted(byKeyPath: "annotationSortIndex", ascending: true)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct SplitAnnotationsDbRequest: DbRequest {
let new = RItem()
new.key = KeyGenerator.newKey
new.rawType = item.rawType
new.annotationType = item.annotationType
new.localizedType = item.localizedType
new.dateAdded = item.dateAdded
new.dateModified = item.dateModified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ struct StoreItemDbRequest: DbResponseRequest {
case (FieldKeys.Item.Annotation.comment, _) where item.rawType == ItemTypes.annotation:
item.htmlFreeContent = value.isEmpty ? nil : value.strippedRichTextTags

case (FieldKeys.Item.Annotation.type, _) where item.rawType == ItemTypes.annotation:
item.annotationType = value

case (FieldKeys.Item.date, _):
date = value

Expand Down
22 changes: 5 additions & 17 deletions Zotero/Models/API/ItemResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -373,28 +373,16 @@ struct ItemResponse {

for object in json {
switch object.key {
case FieldKeys.Item.Annotation.Position.pageIndex:
if (object.value as? Int) == nil {
throw SchemaError.invalidValue(value: "\(object.value)", field: FieldKeys.Item.Annotation.Position.pageIndex, key: key)
}

case FieldKeys.Item.Annotation.Position.lineWidth:
if (object.value as? Double) == nil {
throw SchemaError.invalidValue(value: "\(object.value)", field: FieldKeys.Item.Annotation.Position.lineWidth, key: key)
}

case FieldKeys.Item.Annotation.Position.paths:
guard let parsedPaths = object.value as? [[Double]], !parsedPaths.isEmpty && !parsedPaths.contains(where: { $0.count % 2 != 0 }) else {
throw SchemaError.invalidValue(value: "\(object.value)", field: FieldKeys.Item.Annotation.Position.paths, key: key)
if let parsedPaths = object.value as? [[Double]], !parsedPaths.isEmpty && !parsedPaths.contains(where: { $0.count % 2 != 0 }) {
paths = parsedPaths
}
paths = parsedPaths
continue

case FieldKeys.Item.Annotation.Position.rects:
guard let parsedRects = object.value as? [[Double]], !parsedRects.isEmpty && !parsedRects.contains(where: { $0.count != 4 }) else {
throw SchemaError.invalidValue(value: "\(object.value)", field: FieldKeys.Item.Annotation.Position.rects, key: key)
if let parsedRects = object.value as? [[Double]], !parsedRects.isEmpty && !parsedRects.contains(where: { $0.count != 4 }) {
rects = parsedRects
}
rects = parsedRects
continue

default: break
Expand Down Expand Up @@ -424,7 +412,7 @@ struct ItemResponse {
private static func validate(fields: [KeyBaseKeyPair: String], itemType: String, key: String, hasPaths: Bool, hasRects: Bool) throws {
switch itemType {
case ItemTypes.annotation:
// `position` values are validated in `parsePositionFields(from:key:fields:)` where we have access to their original value, instead of just `String`.
// `position` values are not validated at this point. They depend on content type of parent (attachment) item, which is unknown here, so they are validated when this item is being opened.
guard let rawType = fields[KeyBaseKeyPair(key: FieldKeys.Item.Annotation.type, baseKey: nil)] else {
throw SchemaError.missingField(key: key, field: FieldKeys.Item.Annotation.type, itemType: itemType)
}
Expand Down
2 changes: 1 addition & 1 deletion Zotero/Models/AnnotationType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation

enum AnnotationType: String {
enum AnnotationType: String, CaseIterable {
case note
case highlight
case image
Expand Down
15 changes: 13 additions & 2 deletions Zotero/Models/AnnotationsConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ import PSPDFKit
struct AnnotationsConfig {
static let defaultActiveColor = "#ffd400"
static let allColors: [String] = ["#ffd400", "#ff6666", "#5fb236", "#2ea8e5", "#a28ae5", "#e56eee", "#f19837", "#aaaaaa", "#000000"]
static let colorNames: [String: String] = ["#ffd400": "Yellow", "#ff6666": "Red", "#5fb236": "Green", "#2ea8e5": "Blue", "#a28ae5": "Purple", "#e56eee": "Magenta", "#f19837": "Orange", "#aaaaaa": "Gray", "#000000": "Black"]
static let colorNames: [String: String] = [
"#ffd400": "Yellow",
"#ff6666": "Red",
"#5fb236": "Green",
"#2ea8e5": "Blue",
"#a28ae5": "Purple",
"#e56eee": "Magenta",
"#f19837": "Orange",
"#aaaaaa": "Gray",
"#000000": "Black"
]
// Maps different variations colors to their base color
static let colorVariationMap: [String: String] = createColorVariationMap()
static let keyKey = "Zotero:Key"
Expand All @@ -22,7 +32,8 @@ struct AnnotationsConfig {
// Size of note annotation in PDF document.
static let noteAnnotationSize: CGSize = CGSize(width: 22, height: 22)
static let positionSizeLimit = 65000
static let supported: PSPDFKit.Annotation.Kind = [.note, .highlight, .square, .ink, .underline, .freeText]
// TODO: Enable when text/underline annotations are fully available
static let supported: PSPDFKit.Annotation.Kind = [.note, .highlight, .square, .ink]//, .underline, .freeText]

static func colors(for type: AnnotationType) -> [String] {
switch type {
Expand Down
Loading

0 comments on commit 68b9b5e

Please sign in to comment.