ReadViewSDK/Sources/RDEpubReaderView/EPUBUI/RDEPUBAnnotationEditorViewController.swift

136 lines
6.1 KiB
Swift

import UIKit
final class RDEPUBAnnotationEditorViewController: UIViewController, UITextViewDelegate {
private let quote: String
private let initialNote: String?
private let onSave: (String?) -> Void
private let textView = UITextView()
private let countLabel = UILabel()
init(quote: String, initialNote: String?, onSave: @escaping (String?) -> Void) {
self.quote = quote
self.initialNote = initialNote
self.onSave = onSave
super.init(nibName: nil, bundle: nil)
title = "写注释"
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 0.975, green: 0.965, blue: 0.935, alpha: 1)
configureNavigation()
configureContent()
updateCount()
DispatchQueue.main.async { [weak self] in self?.textView.becomeFirstResponder() }
}
private func configureNavigation() {
navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "取消", style: .plain, target: self, action: #selector(cancelAction)
)
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "保存", style: .done, target: self, action: #selector(saveAction)
)
navigationController?.navigationBar.tintColor = UIColor(red: 0.10, green: 0.34, blue: 0.78, alpha: 1)
navigationController?.navigationBar.titleTextAttributes = [
.foregroundColor: UIColor(red: 0.08, green: 0.10, blue: 0.14, alpha: 1),
.font: UIFont.systemFont(ofSize: 17, weight: .semibold)
]
}
private func configureContent() {
let quoteCard = UIView()
let rail = UIView()
let quoteLabel = UILabel()
let inputCard = UIView()
[quoteCard, rail, quoteLabel, inputCard, textView, countLabel].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
view.addSubview(quoteCard)
quoteCard.addSubview(rail)
quoteCard.addSubview(quoteLabel)
view.addSubview(inputCard)
inputCard.addSubview(textView)
inputCard.addSubview(countLabel)
quoteCard.backgroundColor = UIColor.white.withAlphaComponent(0.78)
quoteCard.layer.cornerRadius = 16
rail.backgroundColor = UIColor(red: 0.94, green: 0.63, blue: 0.18, alpha: 1)
rail.layer.cornerRadius = 2
quoteLabel.text = quote
quoteLabel.numberOfLines = 5
quoteLabel.font = UIFont.systemFont(ofSize: 16)
quoteLabel.textColor = UIColor(red: 0.19, green: 0.20, blue: 0.23, alpha: 1)
inputCard.backgroundColor = .white
inputCard.layer.cornerRadius = 18
inputCard.layer.shadowColor = UIColor.black.cgColor
inputCard.layer.shadowOpacity = 0.06
inputCard.layer.shadowRadius = 18
inputCard.layer.shadowOffset = CGSize(width: 0, height: 6)
textView.text = initialNote
textView.delegate = self
textView.font = UIFont.systemFont(ofSize: 17)
textView.textColor = UIColor(red: 0.08, green: 0.10, blue: 0.14, alpha: 1)
textView.backgroundColor = .clear
textView.accessibilityIdentifier = "epub.reader.annotation.editor"
countLabel.font = UIFont.monospacedDigitSystemFont(ofSize: 12, weight: .regular)
countLabel.textColor = .secondaryLabel
countLabel.textAlignment = .right
NSLayoutConstraint.activate([
quoteCard.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
quoteCard.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
quoteCard.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
rail.leadingAnchor.constraint(equalTo: quoteCard.leadingAnchor, constant: 16),
rail.topAnchor.constraint(equalTo: quoteCard.topAnchor, constant: 16),
rail.bottomAnchor.constraint(equalTo: quoteCard.bottomAnchor, constant: -16),
rail.widthAnchor.constraint(equalToConstant: 4),
quoteLabel.leadingAnchor.constraint(equalTo: rail.trailingAnchor, constant: 14),
quoteLabel.trailingAnchor.constraint(equalTo: quoteCard.trailingAnchor, constant: -18),
quoteLabel.topAnchor.constraint(equalTo: quoteCard.topAnchor, constant: 16),
quoteLabel.bottomAnchor.constraint(equalTo: quoteCard.bottomAnchor, constant: -16),
inputCard.topAnchor.constraint(equalTo: quoteCard.bottomAnchor, constant: 18),
inputCard.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
inputCard.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
inputCard.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor, constant: -16),
inputCard.heightAnchor.constraint(greaterThanOrEqualToConstant: 210),
textView.topAnchor.constraint(equalTo: inputCard.topAnchor, constant: 14),
textView.leadingAnchor.constraint(equalTo: inputCard.leadingAnchor, constant: 14),
textView.trailingAnchor.constraint(equalTo: inputCard.trailingAnchor, constant: -14),
textView.bottomAnchor.constraint(equalTo: countLabel.topAnchor, constant: -8),
countLabel.leadingAnchor.constraint(equalTo: inputCard.leadingAnchor, constant: 16),
countLabel.trailingAnchor.constraint(equalTo: inputCard.trailingAnchor, constant: -16),
countLabel.bottomAnchor.constraint(equalTo: inputCard.bottomAnchor, constant: -12)
])
}
func textViewDidChange(_ textView: UITextView) {
if textView.text.count > 1000 {
textView.text = String(textView.text.prefix(1000))
}
updateCount()
}
private func updateCount() {
countLabel.text = "\(textView.text.count)/1000"
}
@objc private func cancelAction() {
dismiss(animated: true)
}
@objc private func saveAction() {
let note = textView.text.trimmingCharacters(in: .whitespacesAndNewlines)
onSave(note.isEmpty ? nil : note)
dismiss(animated: true)
}
}