Skip to content

Commit

Permalink
Note editor improvements (#1007)
Browse files Browse the repository at this point in the history
  • Loading branch information
michalrentka committed Sep 9, 2024
1 parent eec7200 commit 4e4babd
Show file tree
Hide file tree
Showing 22 changed files with 386 additions and 195 deletions.
20 changes: 18 additions & 2 deletions Zotero.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
61ABA7512A6137D1002A4219 /* ShareableImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61ABA7502A6137D1002A4219 /* ShareableImage.swift */; };
61BD13952A5831EF008A0704 /* TextKit1TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61BD13942A5831EF008A0704 /* TextKit1TextView.swift */; };
61C817F22A49B5D30085B1E6 /* CollectionResponseSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B1EDEE250242E700D8BC1E /* CollectionResponseSpec.swift */; };
61E24DCC2ABB385E00D75F50 /* OpenItemsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E24DCB2ABB385E00D75F50 /* OpenItemsController.swift */; };
61DE64D52C5BD0250096776C /* FormattedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61DE64D42C5BD0250096776C /* FormattedTextView.swift */; };
61E24DCC2ABB385E00D75F50 /* OpenItemsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61E24DCB2ABB385E00D75F50 /* OpenItemsController.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 @@ -938,6 +938,11 @@
B3B41F1A2848E5A90017CA4B /* AnnotationsFilterAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B41F172848E5A80017CA4B /* AnnotationsFilterAction.swift */; };
B3B41F1B2848E5A90017CA4B /* AnnotationsFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B41F182848E5A80017CA4B /* AnnotationsFilter.swift */; };
B3B41F1D2848E6B80017CA4B /* AnnotationsFilterPopoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B41F1C2848E6B80017CA4B /* AnnotationsFilterPopoverCoordinator.swift */; };
B3B557132C884B8300BD6325 /* AnnotationPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B557122C884B7D00BD6325 /* AnnotationPreview.swift */; };
B3B557142C884B8300BD6325 /* AnnotationPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B557122C884B7D00BD6325 /* AnnotationPreview.swift */; };
B3B557162C884DD600BD6325 /* ZoteroURIConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B557152C884DD200BD6325 /* ZoteroURIConverter.swift */; };
B3B557182C8860E600BD6325 /* CitationMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B557172C8860E400BD6325 /* CitationMetadata.swift */; };
B3B557192C8860E600BD6325 /* CitationMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B557172C8860E400BD6325 /* CitationMetadata.swift */; };
B3B613F7260B844B00B92017 /* EmptyTrashDbRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B613F6260B844B00B92017 /* EmptyTrashDbRequest.swift */; };
B3B6759526205A3C003231A5 /* CollectionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B6759426205A3C003231A5 /* CollectionRowView.swift */; };
B3B6759B26205A48003231A5 /* CollectionRowView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B3B6759A26205A48003231A5 /* CollectionRowView.xib */; };
Expand Down Expand Up @@ -1283,8 +1288,8 @@
61A0C8462B8F669B0048FF92 /* PSPDFKitUI+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PSPDFKitUI+Extensions.swift"; sourceTree = "<group>"; };
61ABA7502A6137D1002A4219 /* ShareableImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareableImage.swift; sourceTree = "<group>"; };
61BD13942A5831EF008A0704 /* TextKit1TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextKit1TextView.swift; sourceTree = "<group>"; };
61E24DCB2ABB385E00D75F50 /* OpenItemsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenItemsController.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>"; };
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 @@ -1935,6 +1940,9 @@
B3B41F172848E5A80017CA4B /* AnnotationsFilterAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnnotationsFilterAction.swift; sourceTree = "<group>"; };
B3B41F182848E5A80017CA4B /* AnnotationsFilter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnnotationsFilter.swift; sourceTree = "<group>"; };
B3B41F1C2848E6B80017CA4B /* AnnotationsFilterPopoverCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnotationsFilterPopoverCoordinator.swift; sourceTree = "<group>"; };
B3B557122C884B7D00BD6325 /* AnnotationPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnotationPreview.swift; sourceTree = "<group>"; };
B3B557152C884DD200BD6325 /* ZoteroURIConverter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoteroURIConverter.swift; sourceTree = "<group>"; };
B3B557172C8860E400BD6325 /* CitationMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CitationMetadata.swift; sourceTree = "<group>"; };
B3B613F6260B844B00B92017 /* EmptyTrashDbRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTrashDbRequest.swift; sourceTree = "<group>"; };
B3B6759426205A3C003231A5 /* CollectionRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionRowView.swift; sourceTree = "<group>"; };
B3B6759A26205A48003231A5 /* CollectionRowView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CollectionRowView.xib; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2325,6 +2333,7 @@
B324276C25C81F2000567504 /* WebSocketController.swift */,
618404252A4456A9005AAF22 /* IdentifierLookupController.swift */,
B3F9A4CA2B04F28400684030 /* WebViewEncoder.swift */,
B3B557152C884DD200BD6325 /* ZoteroURIConverter.swift */,
);
path = Controllers;
sourceTree = "<group>";
Expand Down Expand Up @@ -2637,11 +2646,13 @@
B305655523FC051E003304F2 /* Sync */,
B324277025C82D6900567504 /* WebSocket */,
B3242CCC246ABBAF00D8748F /* AnnotationsConfig.swift */,
B3B557122C884B7D00BD6325 /* AnnotationPreview.swift */,
B3F6AA392AB30663005BC22E /* AnnotationTool.swift */,
B311737A2AFCF004007D9741 /* AnnotationType.swift */,
B305656123FC051E003304F2 /* AppGroup.swift */,
B305653A23FC051E003304F2 /* Attachment.swift */,
B339459026DE6C2900E59A02 /* AttachmentFileDeletedNotification.swift */,
B3B557172C8860E400BD6325 /* CitationMetadata.swift */,
B305653B23FC051E003304F2 /* Collection.swift */,
B343419D260A093400093E63 /* CollectionIdentifier.swift */,
B3325F6E27B41D69007C7137 /* CollectionTree.swift */,
Expand Down Expand Up @@ -5070,6 +5081,7 @@
B3F09AE629CAFF860084E4D8 /* TagFilterActionHandler.swift in Sources */,
B30566B523FC051F003304F2 /* LoginResponse.swift in Sources */,
B3B41F1B2848E5A90017CA4B /* AnnotationsFilter.swift in Sources */,
B3B557192C8860E600BD6325 /* CitationMetadata.swift in Sources */,
B30565CB23FC051E003304F2 /* ReadSearchDbRequest.swift in Sources */,
B31CC58128646D990055C114 /* ManualLookupState.swift in Sources */,
B3D06ADE29DD8C21009C0D98 /* DeleteAutomaticTagsDbRequest.swift in Sources */,
Expand Down Expand Up @@ -5209,6 +5221,7 @@
B30565D323FC051E003304F2 /* MoveItemsToParentDbRequest.swift in Sources */,
B305669723FC051F003304F2 /* RTag.swift in Sources */,
B3FBAC1924570BDE00AA00C0 /* AnnotationPreviewController.swift in Sources */,
B3B557162C884DD600BD6325 /* ZoteroURIConverter.swift in Sources */,
B305660323FC051E003304F2 /* ZoteroApiClient.swift in Sources */,
B3B78C42266FAED500E91D02 /* CitationController.swift in Sources */,
B3B41F1A2848E5A90017CA4B /* AnnotationsFilterAction.swift in Sources */,
Expand Down Expand Up @@ -5440,6 +5453,7 @@
B3593F4B241A61C700760E20 /* LibrariesError.swift in Sources */,
B3242CCD246ABBAF00D8748F /* AnnotationsConfig.swift in Sources */,
B305669923FC051F003304F2 /* RCreator.swift in Sources */,
B3B557132C884B8300BD6325 /* AnnotationPreview.swift in Sources */,
B355B12C2850B6C400BAE2C5 /* TableViewDiffableDataSource.swift in Sources */,
B310280B2B1E16EC00E41554 /* PDFThumbnailsState.swift in Sources */,
B3B953CC245981C100FC96DB /* PDFReaderActionHandler.swift in Sources */,
Expand Down Expand Up @@ -5641,6 +5655,7 @@
B3FC7436272195DE00F55531 /* WebDavDownloadRequest.swift in Sources */,
B3FC7437272195E100F55531 /* WebDavNonexistentPropRequest.swift in Sources */,
B30549002B3327CB00853966 /* ReadAllDownloadsDbRequest.swift in Sources */,
B3B557142C884B8300BD6325 /* AnnotationPreview.swift in Sources */,
B305676F23FC0A55003304F2 /* ArrayEncoding.swift in Sources */,
B305672523FC0909003304F2 /* DeleteGroupSyncAction.swift in Sources */,
B305670323FC08A4003304F2 /* PerformDeletionsDbRequest.swift in Sources */,
Expand Down Expand Up @@ -5753,6 +5768,7 @@
B36459E726441A1800A0C2C0 /* TagRow.swift in Sources */,
B3FC74322721857C00F55531 /* WebDavController.swift in Sources */,
B3B78C47266FB11D00E91D02 /* WKWebView+Extensions.swift in Sources */,
B3B557182C8860E600BD6325 /* CitationMetadata.swift in Sources */,
B305677023FC0A58003304F2 /* Alamofire+RxSwift.swift in Sources */,
B330261225DEAD9A00742025 /* RPageIndex.swift in Sources */,
B305670023FC086B003304F2 /* MarkObjectsAsDeletedDbRequest.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ final class AttachmentDownloader: NSObject {
case incompatibleAttachment
case zipDidntContainRequestedFile
case cantUnzipSnapshot
case cancelled
}

struct Update {
Expand Down Expand Up @@ -230,7 +231,7 @@ final class AttachmentDownloader: NSObject {

guard let attachmentItem = try? dbStorage.perform(request: ReadItemDbRequest(libraryId: libraryId, key: rDownload.key), on: dbQueue),
let attachment = AttachmentCreator.attachment(for: attachmentItem, fileStorage: fileStorage, urlDetector: nil),
case .file(let filename, let contentType, _, _, _) = attachment.type else {
let file = attachment.file else {
// Attachment item doesn't exist anymore, cancel download
toDelete.append(download)
if let taskId = rDownload.taskId {
Expand All @@ -239,8 +240,6 @@ final class AttachmentDownloader: NSObject {
continue
}

let file = Files.attachmentFile(in: attachment.libraryId, key: attachment.key, filename: filename, contentType: contentType)

if let taskId = rDownload.taskId, existingTaskIds.contains(taskId) {
// Download is ongoing, cache data
activeDownloads.append((taskId, EnqueuedDownload(download: download, file: file, progress: Progress(), extractAfterDownload: false)))
Expand Down Expand Up @@ -443,6 +442,30 @@ final class AttachmentDownloader: NSObject {
}
}

func downloadIfNeeded(attachment: Attachment, parentKey: String?, completion: @escaping (Result<(), Swift.Error>) -> Void) {
observable
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] update in
guard let self, update.libraryId == attachment.libraryId && update.key == attachment.key else { return }
switch update.kind {
case .ready:
completion(.success(()))

case .cancelled:
completion(.failure(Error.cancelled))

case .failed(let error):
completion(.failure(error))

case .progress:
break
}
})
.disposed(by: disposeBag)

downloadIfNeeded(attachment: attachment, parentKey: parentKey)
}

private func extract(zipFile: File, toFile file: File, download: Download) {
unzipQueue.async { [weak self] in
guard let self else { return }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ final class RemoteAttachmentDownloader {
func createDownload(url: URL, attachment: Attachment, parentKey: String) -> (Download, RemoteAttachmentDownloadOperation)? {
let download = Download(key: attachment.key, parentKey: parentKey, libraryId: attachment.libraryId)

guard operations[download] == nil, let file = file(for: attachment) else { return nil }
guard operations[download] == nil, let file = attachment.file else { return nil }

let progress = Progress(totalUnitCount: 100)
let operation = RemoteAttachmentDownloadOperation(url: url, file: file, progress: progress, apiClient: apiClient, fileStorage: fileStorage, queue: processingQueue)
Expand Down Expand Up @@ -146,16 +146,6 @@ final class RemoteAttachmentDownloader {

return (download, operation)

func file(for attachment: Attachment) -> File? {
switch attachment.type {
case .file(let filename, let contentType, _, _, _):
return Files.attachmentFile(in: attachment.libraryId, key: attachment.key, filename: filename, contentType: contentType)

case .url:
return nil
}
}

func finish(download: Download, file: File, attachment: Attachment, parentKey: String, result: Result<(), Swift.Error>) {
operations[download] = nil
progressObservers[download] = nil
Expand Down
2 changes: 2 additions & 0 deletions Zotero/Controllers/Controllers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ final class Controllers {
let idleTimerController: IdleTimerController
let backgroundTaskController: BackgroundTaskController
let lowPowerModeController: LowPowerModeController
let uriConverter: ZoteroURIConverter
let userInitialized: PassthroughSubject<Result<Bool, Error>, Never>
fileprivate let lastBuildNumber: Int?

Expand Down Expand Up @@ -102,6 +103,7 @@ final class Controllers {
self.idleTimerController = IdleTimerController()
self.backgroundTaskController = BackgroundTaskController()
self.lowPowerModeController = LowPowerModeController()
uriConverter = ZoteroURIConverter()
self.didInitialize = false

Defaults.shared.lastBuildNumber = DeviceInfoProvider.buildNumber
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,19 +102,15 @@ struct CreateAttachmentDbRequest: DbResponseRequest {
}

case FieldKeys.Item.Attachment.md5:
switch self.attachment.type {
case .file(let filename, let contentType, _, _, _):
let file = Files.attachmentFile(in: self.attachment.libraryId, key: self.attachment.key, filename: filename, contentType: contentType)
if let md5Value = md5(from: file.createUrl()) {
if md5Value == "<null>" {
DDLogError("CreateAttachmentDbRequest: incorrect md5 value for attachment \(self.attachment.key)")
throw Error.incorrectMd5Value
}
value = md5Value
} else {
throw Error.cantCreateMd5
guard let file = attachment.file else { continue }
if let md5Value = md5(from: file.createUrl()) {
if md5Value == "<null>" {
DDLogError("CreateAttachmentDbRequest: incorrect md5 value for attachment \(self.attachment.key)")
throw Error.incorrectMd5Value
}
case .url: continue
value = md5Value
} else {
throw Error.cantCreateMd5
}

case FieldKeys.Item.Attachment.mtime:
Expand All @@ -129,6 +125,7 @@ struct CreateAttachmentDbRequest: DbResponseRequest {
switch self.attachment.type {
case .file(let filename, _, _, _, _):
value = filename

case .url: continue
}

Expand All @@ -143,16 +140,13 @@ struct CreateAttachmentDbRequest: DbResponseRequest {
}

case FieldKeys.Item.Attachment.path:
switch self.attachment.type {
case .file(let filename, let contentType, _, let linkType, _) where linkType == .linkedFile:
let file = Files.attachmentFile(in: self.attachment.libraryId, key: self.attachment.key, filename: filename, contentType: contentType)
value = file.createUrl().path
default: continue
}
guard let file = attachment.file else { continue }
value = file.createUrl().path

case FieldKeys.Item.accessDate:
guard self.includeAccessDate else { continue }
value = Formatter.iso8601.string(from: self.attachment.dateAdded)

default: continue
}

Expand Down
3 changes: 1 addition & 2 deletions Zotero/Controllers/IdentifierLookupController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,7 @@ final class IdentifierLookupController {
DDLogError("IdentifierLookupController: can't store attachment after download - \(error)")

// Storing item failed, remove downloaded file
guard case .file(let filename, let contentType, _, _, _) = attachment.type else { return }
let file = Files.attachmentFile(in: attachment.libraryId, key: attachment.key, filename: filename, contentType: contentType)
guard let file = attachment.file else { return }
try? self.fileStorage.remove(file)
}
}
Expand Down
Loading

0 comments on commit 4e4babd

Please sign in to comment.