136 lines
6.1 KiB
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)
|
|
}
|
|
}
|