diff --git a/Zotero/Controllers/AnnotationConverter.swift b/Zotero/Controllers/AnnotationConverter.swift index ea7d698a3..f35ce2aa4 100644 --- a/Zotero/Controllers/AnnotationConverter.swift +++ b/Zotero/Controllers/AnnotationConverter.swift @@ -84,7 +84,7 @@ struct AnnotationConverter { var text: String? let paths: [[CGPoint]] var lineWidth: CGFloat? - var fontSize: UInt? + var fontSize: CGFloat? var rotation: UInt? if let annotation = annotation as? PSPDFKit.NoteAnnotation { @@ -112,7 +112,8 @@ struct AnnotationConverter { paths = [] } else if let annotation = annotation as? PSPDFKit.FreeTextAnnotation { type = .freeText - fontSize = UInt(annotation.fontSize) + let roundedFontSize = AnnotationsConfig.roundFreeTextAnnotationFontSize(annotation.fontSize) + fontSize = roundedFontSize rotation = annotation.rotation paths = [] rects = self.rects(fromTextAnnotation: annotation) diff --git a/Zotero/Controllers/Database/Requests/EditAnnotationFontSizeDbRequest.swift b/Zotero/Controllers/Database/Requests/EditAnnotationFontSizeDbRequest.swift index acbe95d93..a3b4333cf 100644 --- a/Zotero/Controllers/Database/Requests/EditAnnotationFontSizeDbRequest.swift +++ b/Zotero/Controllers/Database/Requests/EditAnnotationFontSizeDbRequest.swift @@ -13,7 +13,7 @@ import RealmSwift struct EditAnnotationFontSizeDbRequest: DbRequest { let key: String let libraryId: LibraryIdentifier - let size: UInt + let size: CGFloat var needsWrite: Bool { return true } diff --git a/Zotero/Models/AnnotationsConfig.swift b/Zotero/Models/AnnotationsConfig.swift index d9fdbd528..754f608f5 100644 --- a/Zotero/Models/AnnotationsConfig.swift +++ b/Zotero/Models/AnnotationsConfig.swift @@ -29,6 +29,13 @@ struct AnnotationsConfig { static let keyKey = "Zotero:Key" // Line width of image annotation in PDF document. static let imageAnnotationLineWidth: CGFloat = 2 + // Free text annotation font size minimum, maximum, increment and rounding + static let freeTextAnnotationFontSizeMinimum: CGFloat = 1 + static let freeTextAnnotationFontSizeMaximum: CGFloat = 200 + static let freeTextAnnotationFontSizeIncrement: CGFloat = 0.5 + static func roundFreeTextAnnotationFontSize(_ fontSize: CGFloat) -> CGFloat { + round(fontSize * 2) / 2 + } // Size of note annotation in PDF document. static let noteAnnotationSize: CGSize = CGSize(width: 22, height: 22) static let positionSizeLimit = 65000 diff --git a/Zotero/Scenes/Detail/Annotation Popover/AnnotationPopoverCoordinator.swift b/Zotero/Scenes/Detail/Annotation Popover/AnnotationPopoverCoordinator.swift index 28a499cdf..a78e762bd 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/AnnotationPopoverCoordinator.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/AnnotationPopoverCoordinator.swift @@ -16,13 +16,13 @@ protocol AnnotationPopoverAnnotationCoordinatorDelegate: AnyObject { func createShareAnnotationMenu(sender: UIButton) -> UIMenu? func showEdit(state: AnnotationPopoverState, saveAction: @escaping AnnotationEditSaveAction, deleteAction: @escaping AnnotationEditDeleteAction) func showTagPicker(libraryId: LibraryIdentifier, selected: Set, picked: @escaping ([Tag]) -> Void) - func showFontSizePicker(picked: @escaping (UInt) -> Void) + func showFontSizePicker(picked: @escaping (CGFloat) -> Void) func didFinish() } protocol AnnotationEditCoordinatorDelegate: AnyObject { func showPageLabelEditor(label: String, updateSubsequentPages: Bool, saveAction: @escaping AnnotationPageLabelSaveAction) - func showFontSizePicker(picked: @escaping (UInt) -> Void) + func showFontSizePicker(picked: @escaping (CGFloat) -> Void) } final class AnnotationPopoverCoordinator: NSObject, Coordinator { @@ -64,7 +64,7 @@ final class AnnotationPopoverCoordinator: NSObject, Coordinator { } extension AnnotationPopoverCoordinator: AnnotationPopoverAnnotationCoordinatorDelegate { - func showFontSizePicker(picked: @escaping (UInt) -> Void) { + func showFontSizePicker(picked: @escaping (CGFloat) -> Void) { let controller = FontSizePickerViewController(pickAction: picked) self.navigationController?.pushViewController(controller, animated: true) } diff --git a/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditAction.swift b/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditAction.swift index c9613364f..858ccf2e8 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditAction.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditAction.swift @@ -13,5 +13,5 @@ enum AnnotationEditAction { case setLineWidth(CGFloat) case setPageLabel(String, Bool) case setHighlight(NSAttributedString) - case setFontSize(UInt) + case setFontSize(CGFloat) } diff --git a/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditState.swift b/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditState.swift index 2e9134651..1ed865d36 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditState.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/Models/AnnotationEditState.swift @@ -17,7 +17,7 @@ struct AnnotationEditState: ViewModelState { let pageLabel: String let highlightText: NSAttributedString let highlightFont: UIFont - let fontSize: UInt? + let fontSize: CGFloat? } struct Changes: OptionSet { @@ -35,7 +35,7 @@ struct AnnotationEditState: ViewModelState { var color: String var lineWidth: CGFloat var pageLabel: String - var fontSize: UInt + var fontSize: CGFloat var highlightText: NSAttributedString var highlightFont: UIFont var updateSubsequentLabels: Bool diff --git a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeCell.swift b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeCell.swift index d1938b7f5..4de611a29 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeCell.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeCell.swift @@ -12,21 +12,21 @@ import RxSwift class FontSizeCell: RxTableViewCell { private weak var fontSizeView: FontSizeView! - var tapObservable: PublishSubject<()> { return self.fontSizeView.tapObservable } - var valueObservable: PublishSubject { return self.fontSizeView.valueObservable } + var tapObservable: PublishSubject<()> { return fontSizeView.tapObservable } + var valueObservable: PublishSubject { return fontSizeView.valueObservable } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - self.setup() + setup() } required init?(coder: NSCoder) { super.init(coder: coder) - self.setup() + setup() } - func set(value: UInt) { - self.fontSizeView.value = value + func set(value: CGFloat) { + fontSizeView.value = value } private func setup() { @@ -34,13 +34,13 @@ class FontSizeCell: RxTableViewCell { fontSizeView.translatesAutoresizingMaskIntoConstraints = false fontSizeView.button.isUserInteractionEnabled = false self.fontSizeView = fontSizeView - self.contentView.addSubview(fontSizeView) + contentView.addSubview(fontSizeView) NSLayoutConstraint.activate([ - self.contentView.topAnchor.constraint(equalTo: fontSizeView.topAnchor), - self.contentView.bottomAnchor.constraint(equalTo: fontSizeView.bottomAnchor), - self.contentView.leadingAnchor.constraint(equalTo: fontSizeView.leadingAnchor), - self.contentView.trailingAnchor.constraint(equalTo: fontSizeView.trailingAnchor) + contentView.topAnchor.constraint(equalTo: fontSizeView.topAnchor), + contentView.bottomAnchor.constraint(equalTo: fontSizeView.bottomAnchor), + contentView.leadingAnchor.constraint(equalTo: fontSizeView.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: fontSizeView.trailingAnchor) ]) } } diff --git a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizePickerViewController.swift b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizePickerViewController.swift index 9b129b9ff..f17a11f4f 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizePickerViewController.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizePickerViewController.swift @@ -11,7 +11,7 @@ import UIKit import RxSwift class FontSizePickerViewController: UIViewController { - private static let sizes: [UInt] = [ + private static let sizes: [CGFloat] = [ 10, 12, 14, @@ -26,15 +26,15 @@ class FontSizePickerViewController: UIViewController { 192 ] - private let pickAction: (UInt) -> Void + private let pickAction: (CGFloat) -> Void private let disposeBag: DisposeBag private weak var tableView: UITableView! - private var dataSource: UITableViewDiffableDataSource! + private var dataSource: UITableViewDiffableDataSource! - init(pickAction: @escaping (UInt) -> Void) { + init(pickAction: @escaping (CGFloat) -> Void) { self.pickAction = pickAction - self.disposeBag = DisposeBag() + disposeBag = DisposeBag() super.init(nibName: nil, bundle: nil) } @@ -50,7 +50,7 @@ class FontSizePickerViewController: UIViewController { setupSizes() func setupSizes() { - var snapshot = NSDiffableDataSourceSnapshot() + var snapshot = NSDiffableDataSourceSnapshot() snapshot.appendSections([0]) snapshot.appendItems(FontSizePickerViewController.sizes) dataSource.apply(snapshot, animatingDifferences: false) @@ -66,7 +66,7 @@ class FontSizePickerViewController: UIViewController { cell.contentConfiguration = configuration return cell }) - tableView.dataSource = self.dataSource + tableView.dataSource = dataSource tableView.delegate = self tableView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(tableView) @@ -87,16 +87,16 @@ class FontSizePickerViewController: UIViewController { cancel .rx .tap - .subscribe(with: self, onNext: { `self`, _ in - self.navigationController?.presentingViewController?.dismiss(animated: true) + .subscribe(onNext: { [weak self] _ in + self?.navigationController?.presentingViewController?.dismiss(animated: true) }) .disposed(by: disposeBag) - self.navigationItem.leftBarButtonItem = cancel + navigationItem.leftBarButtonItem = cancel } } override func loadView() { - self.view = UIView() + view = UIView() } } @@ -104,7 +104,7 @@ extension FontSizePickerViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) guard let size = dataSource.itemIdentifier(for: indexPath) else { return } - self.pickAction(size) + pickAction(size) if let controller = navigationController { if controller.viewControllers.count == 1 { controller.presentingViewController?.dismiss(animated: true) @@ -112,7 +112,7 @@ extension FontSizePickerViewController: UITableViewDelegate { controller.popViewController(animated: true) } } else { - self.presentingViewController?.dismiss(animated: true) + presentingViewController?.dismiss(animated: true) } } } diff --git a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeView.swift b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeView.swift index beae784aa..7d6c45025 100644 --- a/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeView.swift +++ b/Zotero/Scenes/Detail/Annotation Popover/Views/FontSizeView.swift @@ -15,84 +15,84 @@ final class FontSizeView: UIView { private let contentInsets: UIEdgeInsets private let disposeBag: DisposeBag let tapObservable: PublishSubject<()> - let valueObservable: PublishSubject + let valueObservable: PublishSubject var stepperEnabled: Bool { didSet { - self.stepper.isHidden = !self.stepperEnabled + stepper.isHidden = !stepperEnabled } } private(set) weak var button: UIButton! private weak var stepper: UIStepper! - var value: UInt { + var value: CGFloat { get { - return UInt(self.stepper.value) + return CGFloat(stepper.value) } set { - self.stepper.value = Double(newValue) - self.updateLabel(with: newValue) + stepper.value = Double(newValue) + updateLabel(with: newValue) } } init(contentInsets: UIEdgeInsets, stepperEnabled: Bool) { self.contentInsets = contentInsets self.stepperEnabled = stepperEnabled - self.disposeBag = DisposeBag() - self.tapObservable = PublishSubject() - self.valueObservable = PublishSubject() + disposeBag = DisposeBag() + tapObservable = PublishSubject() + valueObservable = PublishSubject() super.init(frame: CGRect()) - self.setup() + setup() } required init?(coder: NSCoder) { - self.contentInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) - self.stepperEnabled = true - self.disposeBag = DisposeBag() - self.tapObservable = PublishSubject() - self.valueObservable = PublishSubject() + contentInsets = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) + stepperEnabled = true + disposeBag = DisposeBag() + tapObservable = PublishSubject() + valueObservable = PublishSubject() super.init(coder: coder) - self.setup() + setup() } // MARK: - Actions private func stepChanged() { - let value = UInt(self.stepper.value) - self.updateLabel(with: value) - self.valueObservable.on(.next(value)) + let value = CGFloat(stepper.value) + updateLabel(with: value) + valueObservable.on(.next(value)) } - private func updateLabel(with value: UInt) { + private func updateLabel(with value: CGFloat) { let valueString = "\(value)" let ptString = "pt" let attributedString = NSMutableAttributedString(string: valueString + ptString) attributedString.addAttributes([.font: UIFont.preferredFont(forTextStyle: .body), .foregroundColor: UIColor.label], range: NSRange(location: 0, length: valueString.count)) attributedString.addAttributes([.font: UIFont.preferredFont(forTextStyle: .callout), .foregroundColor: UIColor.darkGray], range: NSRange(location: valueString.count, length: ptString.count)) - self.button.setAttributedTitle(attributedString, for: .normal) + button.setAttributedTitle(attributedString, for: .normal) } // MARK: - Setups private func setup() { let stepper = UIStepper() - stepper.isHidden = !self.stepperEnabled - stepper.stepValue = 1 - stepper.minimumValue = 1 - stepper.maximumValue = 200 + stepper.isHidden = !stepperEnabled + stepper.stepValue = AnnotationsConfig.freeTextAnnotationFontSizeIncrement + stepper.minimumValue = AnnotationsConfig.freeTextAnnotationFontSizeMinimum + stepper.maximumValue = AnnotationsConfig.freeTextAnnotationFontSizeMaximum stepper.rx.controlEvent(.valueChanged) .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { `self`, _ in - self.stepChanged() + .subscribe(onNext: { [weak self] _ in + self?.stepChanged() }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) self.stepper = stepper let button = UIButton() button.contentHorizontalAlignment = .leading button.titleLabel?.adjustsFontForContentSizeCategory = true - button.rx.tap.bind(to: self.tapObservable).disposed(by: self.disposeBag) + button.rx.tap.bind(to: tapObservable).disposed(by: disposeBag) self.button = button let container = UIStackView(arrangedSubviews: [button, stepper]) @@ -101,13 +101,13 @@ final class FontSizeView: UIView { container.spacing = 12 container.translatesAutoresizingMaskIntoConstraints = false - self.addSubview(container) + addSubview(container) NSLayoutConstraint.activate([ - container.topAnchor.constraint(equalTo: self.topAnchor, constant: self.contentInsets.top), - self.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: self.contentInsets.bottom), - container.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: self.contentInsets.left), - self.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: self.contentInsets.right) + container.topAnchor.constraint(equalTo: topAnchor, constant: contentInsets.top), + bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: contentInsets.bottom), + container.leadingAnchor.constraint(equalTo: leadingAnchor, constant: contentInsets.left), + trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: contentInsets.right) ]) } } diff --git a/Zotero/Scenes/Detail/PDF/AnnotationEditCoordinator.swift b/Zotero/Scenes/Detail/PDF/AnnotationEditCoordinator.swift index 200ef56a9..2bb59938e 100644 --- a/Zotero/Scenes/Detail/PDF/AnnotationEditCoordinator.swift +++ b/Zotero/Scenes/Detail/PDF/AnnotationEditCoordinator.swift @@ -63,7 +63,7 @@ final class AnnotationEditCoordinator: Coordinator { } extension AnnotationEditCoordinator: AnnotationEditCoordinatorDelegate { - func showFontSizePicker(picked: @escaping (UInt) -> Void) { + func showFontSizePicker(picked: @escaping (CGFloat) -> Void) { let controller = FontSizePickerViewController(pickAction: picked) self.navigationController?.pushViewController(controller, animated: true) } diff --git a/Zotero/Scenes/Detail/PDF/Models/PDFAnnotation.swift b/Zotero/Scenes/Detail/PDF/Models/PDFAnnotation.swift index b0dcbff47..5cd279ce6 100644 --- a/Zotero/Scenes/Detail/PDF/Models/PDFAnnotation.swift +++ b/Zotero/Scenes/Detail/PDF/Models/PDFAnnotation.swift @@ -18,7 +18,7 @@ protocol PDFAnnotation { var color: String { get } var comment: String { get } var text: String? { get } - var fontSize: UInt? { get } + var fontSize: CGFloat? { get } var rotation: UInt? { get } var sortIndex: String { get } var dateModified: Date { get } diff --git a/Zotero/Scenes/Detail/PDF/Models/PDFDatabaseAnnotation.swift b/Zotero/Scenes/Detail/PDF/Models/PDFDatabaseAnnotation.swift index 8c76b5cd1..cab46e0db 100644 --- a/Zotero/Scenes/Detail/PDF/Models/PDFDatabaseAnnotation.swift +++ b/Zotero/Scenes/Detail/PDF/Models/PDFDatabaseAnnotation.swift @@ -104,8 +104,8 @@ struct PDFDatabaseAnnotation { return item.fields.filter(.key(FieldKeys.Item.Annotation.text)).first?.value } - var fontSize: UInt? { - return (item.fields.filter(.key(FieldKeys.Item.Annotation.Position.fontSize)).first?.value).flatMap(UInt.init) + var fontSize: CGFloat? { + return (item.fields.filter(.key(FieldKeys.Item.Annotation.Position.fontSize)).first?.value).flatMap(Double.init).flatMap(CGFloat.init) } var rotation: UInt? { diff --git a/Zotero/Scenes/Detail/PDF/Models/PDFDocumentAnnotation.swift b/Zotero/Scenes/Detail/PDF/Models/PDFDocumentAnnotation.swift index bed416e9b..671034f6f 100644 --- a/Zotero/Scenes/Detail/PDF/Models/PDFDocumentAnnotation.swift +++ b/Zotero/Scenes/Detail/PDF/Models/PDFDocumentAnnotation.swift @@ -21,7 +21,7 @@ struct PDFDocumentAnnotation { let color: String let comment: String let text: String? - var fontSize: UInt? + var fontSize: CGFloat? var rotation: UInt? let sortIndex: String let dateModified: Date diff --git a/Zotero/Scenes/Detail/PDF/Models/PDFReaderAction.swift b/Zotero/Scenes/Detail/PDF/Models/PDFReaderAction.swift index e3f16626f..d1ce1b3df 100644 --- a/Zotero/Scenes/Detail/PDF/Models/PDFReaderAction.swift +++ b/Zotero/Scenes/Detail/PDF/Models/PDFReaderAction.swift @@ -32,7 +32,7 @@ enum PDFReaderAction { key: String, color: String, lineWidth: CGFloat, - fontSize: UInt, + fontSize: CGFloat, pageLabel: String, updateSubsequentLabels: Bool, highlightText: NSAttributedString, @@ -49,7 +49,7 @@ enum PDFReaderAction { case setComment(key: String, comment: NSAttributedString) case setCommentActive(Bool) case setVisiblePage(page: Int, userActionFromDocument: Bool, fromThumbnailList: Bool) - case setFontSize(key: String, size: UInt) + case setFontSize(key: String, size: CGFloat) case export(includeAnnotations: Bool) case clearTmpData case setSidebarEditingEnabled(Bool) diff --git a/Zotero/Scenes/Detail/PDF/PDFCoordinator.swift b/Zotero/Scenes/Detail/PDF/PDFCoordinator.swift index 61d7594db..8895da2aa 100644 --- a/Zotero/Scenes/Detail/PDF/PDFCoordinator.swift +++ b/Zotero/Scenes/Detail/PDF/PDFCoordinator.swift @@ -33,7 +33,7 @@ protocol PdfReaderCoordinatorDelegate: AnyObject { func showReader(document: Document, userInterfaceStyle: UIUserInterfaceStyle) func showCitation(for itemId: String, libraryId: LibraryIdentifier) func copyBibliography(using presenter: UIViewController, for itemId: String, libraryId: LibraryIdentifier) - func showFontSizePicker(sender: UIView, picked: @escaping (UInt) -> Void) + func showFontSizePicker(sender: UIView, picked: @escaping (CGFloat) -> Void) func showDeleteAlertForAnnotation(sender: UIView, delete: @escaping () -> Void) func showTagPicker(libraryId: LibraryIdentifier, selected: Set, userInterfaceStyle: UIUserInterfaceStyle?, picked: @escaping ([Tag]) -> Void) func showDocumentChangedAlert(completed: @escaping () -> Void) @@ -423,7 +423,7 @@ extension PDFCoordinator: PdfReaderCoordinatorDelegate { (parentCoordinator as? DetailCoordinator)?.copyBibliography(using: presenter, for: Set([itemId]), libraryId: libraryId, delegate: self) } - func showFontSizePicker(sender: UIView, picked: @escaping (UInt) -> Void) { + func showFontSizePicker(sender: UIView, picked: @escaping (CGFloat) -> Void) { let controller = FontSizePickerViewController(pickAction: picked) let presentedController: UIViewController switch UIDevice.current.userInterfaceIdiom { diff --git a/Zotero/Scenes/Detail/PDF/ViewModels/PDFReaderActionHandler.swift b/Zotero/Scenes/Detail/PDF/ViewModels/PDFReaderActionHandler.swift index a033c6bcc..0463b8de8 100644 --- a/Zotero/Scenes/Detail/PDF/ViewModels/PDFReaderActionHandler.swift +++ b/Zotero/Scenes/Detail/PDF/ViewModels/PDFReaderActionHandler.swift @@ -1246,7 +1246,7 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi update(annotation: annotation, lineWidth: lineWidth, in: viewModel.state.document) } - private func set(fontSize: UInt, key: String, viewModel: ViewModel) { + private func set(fontSize: CGFloat, key: String, viewModel: ViewModel) { guard let annotation = viewModel.state.annotation(for: PDFReaderState.AnnotationKey(key: key, type: .database)) else { return } update(annotation: annotation, fontSize: fontSize, in: viewModel.state.document) } @@ -1284,7 +1284,7 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi private func set( color: String, lineWidth: CGFloat, - fontSize: UInt, + fontSize: CGFloat, pageLabel: String, updateSubsequentLabels: Bool, highlightText: NSAttributedString, @@ -1318,7 +1318,7 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi annotation: PDFAnnotation, color: (String, UIUserInterfaceStyle)? = nil, lineWidth: CGFloat? = nil, - fontSize: UInt? = nil, + fontSize: CGFloat? = nil, contents: String? = nil, in document: PSPDFKit.Document ) { @@ -1675,7 +1675,8 @@ final class PDFReaderActionHandler: ViewModelActionHandler, BackgroundDbProcessi } if editFontSize { - requests.append(EditAnnotationFontSizeDbRequest(key: key, libraryId: viewModel.state.library.identifier, size: UInt(textAnnotation.fontSize))) + let roundedFontSize = AnnotationsConfig.roundFreeTextAnnotationFontSize(textAnnotation.fontSize) + requests.append(EditAnnotationFontSizeDbRequest(key: key, libraryId: viewModel.state.library.identifier, size: roundedFontSize)) } } else if hasChanges([.boundingBox, .rects]), let rects = AnnotationConverter.rects(from: annotation) { requests.append(EditAnnotationRectsDbRequest(key: key, libraryId: viewModel.state.library.identifier, rects: rects, boundingBoxConverter: boundingBoxConverter)) diff --git a/Zotero/Scenes/Detail/PDF/Views/CustomFreeTextAnnotationView.swift b/Zotero/Scenes/Detail/PDF/Views/CustomFreeTextAnnotationView.swift index 50f63a619..9ae4d4f7a 100644 --- a/Zotero/Scenes/Detail/PDF/Views/CustomFreeTextAnnotationView.swift +++ b/Zotero/Scenes/Detail/PDF/Views/CustomFreeTextAnnotationView.swift @@ -14,12 +14,12 @@ import RxSwift protocol FreeTextInputDelegate: AnyObject { func showColorPicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping (String) -> Void) - func showFontSizePicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping (UInt) -> Void) + func showFontSizePicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping (CGFloat) -> Void) func showTagPicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping ([Tag]) -> Void) func deleteAnnotation(sender: UIView, key: PDFReaderState.AnnotationKey) - func change(fontSize: UInt, for key: PDFReaderState.AnnotationKey) + func change(fontSize: CGFloat, for key: PDFReaderState.AnnotationKey) func getColor(for key: PDFReaderState.AnnotationKey) -> UIColor? - func getFontSize(for key: PDFReaderState.AnnotationKey) -> UInt? + func getFontSize(for key: PDFReaderState.AnnotationKey) -> CGFloat? func getTags(for key: PDFReaderState.AnnotationKey) -> [Tag]? } @@ -44,10 +44,10 @@ final class FreeTextInputAccessory: UIView { init(key: PDFReaderState.AnnotationKey, delegate: FreeTextInputDelegate) { self.delegate = delegate - self.disposeBag = DisposeBag() + disposeBag = DisposeBag() super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 44)) - self.autoresizingMask = .flexibleWidth - self.backgroundColor = .systemBackground + autoresizingMask = .flexibleWidth + backgroundColor = .systemBackground let separator = UIView() separator.backgroundColor = .opaqueSeparator @@ -56,25 +56,24 @@ final class FreeTextInputAccessory: UIView { let separator3 = UIView() separator3.backgroundColor = .opaqueSeparator - let sizePicker = FontSizeView(contentInsets: UIEdgeInsets.zero, stepperEnabled: self.traitCollection.horizontalSizeClass != .compact) + let sizePicker = FontSizeView(contentInsets: UIEdgeInsets.zero, stepperEnabled: traitCollection.horizontalSizeClass != .compact) sizePicker.value = delegate.getFontSize(for: key) ?? 0 self.sizePicker = sizePicker sizePicker.valueObservable .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { `self`, value in - self.delegate?.change(fontSize: value, for: key) + .subscribe(onNext: { [weak delegate] value in + delegate?.change(fontSize: value, for: key) }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) sizePicker.tapObservable .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { [weak sizePicker] `self`, _ in - guard let sizePicker else { return } - self.delegate?.showFontSizePicker(sender: sizePicker, key: key, updated: { [weak sizePicker] size in - guard let sizePicker else { return } - sizePicker.value = size + .subscribe(onNext: { [weak delegate, weak sizePicker] _ in + guard let delegate, let sizePicker else { return } + delegate.showFontSizePicker(sender: sizePicker, key: key, updated: { [weak sizePicker] size in + sizePicker?.value = size }) }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) let colorButton = UIButton() var colorConfiguration = UIButton.Configuration.plain() @@ -88,21 +87,20 @@ final class FreeTextInputAccessory: UIView { deleteConfiguration.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20) deleteButton.configuration = deleteConfiguration - colorButton.tintColor = self.delegate?.getColor(for: key) ?? Asset.Colors.zoteroBlueWithDarkMode.color + colorButton.tintColor = delegate.getColor(for: key) ?? Asset.Colors.zoteroBlueWithDarkMode.color colorButton.rx.tap .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { [weak colorButton] `self`, _ in - guard let colorButton else { return } - self.delegate?.showColorPicker(sender: colorButton, key: key, updated: { [weak colorButton] color in - guard let colorButton else { return } - colorButton.tintColor = UIColor(hex: color) + .subscribe(onNext: { [weak delegate, weak colorButton] _ in + guard let delegate, let colorButton else { return } + delegate.showColorPicker(sender: colorButton, key: key, updated: { [weak colorButton] color in + colorButton?.tintColor = UIColor(hex: color) }) }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) // Can't use the Configuration API for tagButton because it ignores number of lines and just always adds multiple lines let tagButton = UIButton() - tagButton.setAttributedTitle(self.attributedString(from: self.delegate?.getTags(for: key) ?? []), for: .normal) + tagButton.setAttributedTitle(attributedString(from: delegate.getTags(for: key) ?? []), for: .normal) tagButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20) tagButton.titleLabel?.numberOfLines = 1 tagButton.titleLabel?.lineBreakMode = .byTruncatingTail @@ -111,23 +109,23 @@ final class FreeTextInputAccessory: UIView { tagButton.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) tagButton.rx.tap .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { [weak tagButton] `self`, _ in - guard let tagButton else { return } - self.delegate?.showTagPicker(sender: tagButton, key: key, updated: { [weak tagButton] tags in - guard let tagButton else { return } - tagButton.setAttributedTitle(self.attributedString(from: tags), for: .normal) + .subscribe(onNext: { [weak self, weak tagButton] _ in + guard let self, let tagButton else { return } + self.delegate?.showTagPicker(sender: tagButton, key: key, updated: { [weak self, weak tagButton] tags in + guard let self, let tagButton else { return } + tagButton.setAttributedTitle(attributedString(from: tags), for: .normal) }) }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) deleteButton.tintColor = .red deleteButton.rx.tap .observe(on: MainScheduler.instance) - .subscribe(with: self, onNext: { [weak deleteButton] `self`, _ in - guard let deleteButton else { return } - self.delegate?.deleteAnnotation(sender: deleteButton, key: key) + .subscribe(onNext: { [weak delegate, weak deleteButton] _ in + guard let delegate, let deleteButton else { return } + delegate.deleteAnnotation(sender: deleteButton, key: key) }) - .disposed(by: self.disposeBag) + .disposed(by: disposeBag) let spacer = UIView() @@ -135,14 +133,14 @@ final class FreeTextInputAccessory: UIView { container.translatesAutoresizingMaskIntoConstraints = false container.spacing = 0 container.alignment = .center - self.addSubview(container) + addSubview(container) NSLayoutConstraint.activate([ - container.leadingAnchor.constraint(greaterThanOrEqualTo: self.leadingAnchor, constant: 20), - self.trailingAnchor.constraint(greaterThanOrEqualTo: container.trailingAnchor, constant: 20), - container.centerXAnchor.constraint(equalTo: self.centerXAnchor), - self.topAnchor.constraint(equalTo: container.topAnchor), - self.bottomAnchor.constraint(equalTo: container.bottomAnchor), + container.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor, constant: 20), + trailingAnchor.constraint(greaterThanOrEqualTo: container.trailingAnchor, constant: 20), + container.centerXAnchor.constraint(equalTo: centerXAnchor), + topAnchor.constraint(equalTo: container.topAnchor), + bottomAnchor.constraint(equalTo: container.bottomAnchor), separator.widthAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale), separator.heightAnchor.constraint(equalToConstant: 30), separator2.widthAnchor.constraint(equalToConstant: 1 / UIScreen.main.scale), @@ -167,6 +165,6 @@ final class FreeTextInputAccessory: UIView { override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) - self.sizePicker?.stepperEnabled = self.traitCollection.horizontalSizeClass != .compact + sizePicker?.stepperEnabled = traitCollection.horizontalSizeClass != .compact } } diff --git a/Zotero/Scenes/Detail/PDF/Views/PDFDocumentViewController.swift b/Zotero/Scenes/Detail/PDF/Views/PDFDocumentViewController.swift index dd433c269..c9070e64f 100644 --- a/Zotero/Scenes/Detail/PDF/Views/PDFDocumentViewController.swift +++ b/Zotero/Scenes/Detail/PDF/Views/PDFDocumentViewController.swift @@ -959,7 +959,7 @@ extension PDFDocumentViewController: FreeTextInputDelegate { ) } - func showFontSizePicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping (UInt) -> Void) { + func showFontSizePicker(sender: UIView, key: PDFReaderState.AnnotationKey, updated: @escaping (CGFloat) -> Void) { self.coordinatorDelegate?.showFontSizePicker(sender: sender, picked: { [weak self] size in self?.viewModel.process(action: .setFontSize(key: key.key, size: size)) updated(size) @@ -980,11 +980,11 @@ extension PDFDocumentViewController: FreeTextInputDelegate { }) } - func change(fontSize: UInt, for key: PDFReaderState.AnnotationKey) { + func change(fontSize: CGFloat, for key: PDFReaderState.AnnotationKey) { self.viewModel.process(action: .setFontSize(key: key.key, size: fontSize)) } - func getFontSize(for key: PDFReaderState.AnnotationKey) -> UInt? { + func getFontSize(for key: PDFReaderState.AnnotationKey) -> CGFloat? { return self.viewModel.state.annotation(for: key)?.fontSize }