Files
note/Note/FormatNoteViewController.swift
T

229 lines
10 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// FormatNoteViewController.swift
// Note
//
// Created by fish on 2026/7/12.
//
import UIKit
class FormatNoteViewController: UIViewController {
private var textView: UITextView!
private var iCloudButton: UIButton!
private var noteButton: UIButton!
private var doneButton: UIBarButtonItem!
private var pasteButton: UIBarButtonItem!
private var resetButton: UIBarButtonItem!
private var rightBarButtonMode: RightBarButtonMode = .paste
private enum RightBarButtonMode {
case paste
case reset
}
override func viewDidLoad() {
super.viewDidLoad()
title = "格式化笔记"
navigationItem.largeTitleDisplayMode = .never
view.backgroundColor = .systemGroupedBackground
setupUI()
}
private func setupUI() {
textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
textView.backgroundColor = .systemBackground
textView.layer.cornerRadius = 12
textView.layer.masksToBounds = true
textView.font = UIFont.preferredFont(forTextStyle: .body)
textView.textContainerInset = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
textView.isEditable = true
textView.delegate = self
view.addSubview(textView)
doneButton = UIBarButtonItem(title: "完成", style: .plain, target: self, action: #selector(didTapDoneButton))
pasteButton = UIBarButtonItem(title: "粘贴文案", style: .plain, target: self, action: #selector(didTapPasteButton))
resetButton = UIBarButtonItem(title: "重置", style: .plain, target: self, action: #selector(didTapResetButton))
updateRightBarButtonItem()
iCloudButton = createBottomButton(title: "iCloud 格式化", color: .systemBlue)
iCloudButton.addTarget(self, action: #selector(didTapiCloudButton), for: .touchUpInside)
view.addSubview(iCloudButton)
noteButton = createBottomButton(title: "Note 格式化", color: .systemGreen)
noteButton.addTarget(self, action: #selector(didTapNoteButton), for: .touchUpInside)
view.addSubview(noteButton)
let safeArea = view.safeAreaLayoutGuide
let buttonHeight: CGFloat = 52
let spacing: CGFloat = 16
NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: safeArea.topAnchor, constant: spacing),
textView.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: spacing),
textView.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor, constant: -spacing),
iCloudButton.topAnchor.constraint(equalTo: textView.bottomAnchor, constant: spacing),
iCloudButton.leadingAnchor.constraint(equalTo: safeArea.leadingAnchor, constant: spacing),
iCloudButton.trailingAnchor.constraint(equalTo: safeArea.centerXAnchor, constant: -spacing / 2),
iCloudButton.heightAnchor.constraint(equalToConstant: buttonHeight),
iCloudButton.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor, constant: -spacing),
noteButton.topAnchor.constraint(equalTo: textView.bottomAnchor, constant: spacing),
noteButton.leadingAnchor.constraint(equalTo: safeArea.centerXAnchor, constant: spacing / 2),
noteButton.trailingAnchor.constraint(equalTo: safeArea.trailingAnchor, constant: -spacing),
noteButton.heightAnchor.constraint(equalToConstant: buttonHeight),
noteButton.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor, constant: -spacing)
])
}
private func createBottomButton(title: String, color: UIColor) -> UIButton {
var config = UIButton.Configuration.filled()
config.title = title
config.baseBackgroundColor = color
config.baseForegroundColor = .white
config.cornerStyle = .medium
config.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
let button = UIButton(configuration: config)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}
@objc private func didTapDoneButton() {
textView.resignFirstResponder()
}
@objc private func didTapPasteButton() {
if let string = UIPasteboard.general.string {
textView.text = string
}
}
@objc private func didTapResetButton() {
textView.text = ""
rightBarButtonMode = .paste
updateRightBarButtonItem()
}
private func updateRightBarButtonItem() {
if textView.isFirstResponder {
navigationItem.rightBarButtonItem = doneButton
} else {
switch rightBarButtonMode {
case .paste:
navigationItem.rightBarButtonItem = pasteButton
case .reset:
navigationItem.rightBarButtonItem = resetButton
}
}
}
@objc private func didTapiCloudButton() {
textView.text = formatForCloud(textView.text)
rightBarButtonMode = .reset
updateRightBarButtonItem()
}
@objc private func didTapNoteButton() {
textView.text = formatForNote(textView.text)
rightBarButtonMode = .reset
updateRightBarButtonItem()
}
private func formatForCloud(_ text: String) -> String {
var content = text
content = content.replacingOccurrences(of: " ", with: "")
content = content.replacingOccurrences(of: " ", with: "")
content = content.replacingOccurrences(of: "\u{00A0}", with: "")
content = content.replacingOccurrences(of: "# ", with: "")
content = content.replacingOccurrences(of: "#", with: "")
content = content.replacingOccurrences(of: "", with: "。")
content = content.replacingOccurrences(of: "!", with: "。")
content = content.replacingOccurrences(of: ";", with: "。")
content = content.replacingOccurrences(of: "", with: "。")
content = content.replacingOccurrences(of: ".", with: "。")
content = content.replacingOccurrences(of: "", with: "(")
content = content.replacingOccurrences(of: "", with: ")")
content = content.replacingOccurrences(of: "?", with: "")
content = content.replacingOccurrences(of: ",", with: "")
content = content.replacingOccurrences(of: ":", with: "")
let numberReplacements: [(String, String)] = [
("20、", "二十、"), ("19、", "十九、"), ("18、", "十八、"), ("17、", "十七、"),
("16、", "十六、"), ("15、", "十五、"), ("14、", "十四、"), ("13、", "十三、"),
("12、", "十二、"), ("11、", "十一、"), ("10、", "十、"),
("9、", "九、"), ("8、", "八、"), ("7、", "七、"), ("6、", "六、"),
("5、", "五、"), ("4、", "四、"), ("3、", "三、"), ("2、", "二、"), ("1、", "一、")
]
for (old, new) in numberReplacements {
content = content.replacingOccurrences(of: old, with: new)
}
content = content.replacingOccurrences(of: "。", with: "。\n")
content = content.replacingOccurrences(of: "", with: "\n")
content = removeEmptyLines(content)
content = content.replacingOccurrences(of: "\\s*", with: "\n\n", options: .regularExpression)
content = content.replacingOccurrences(of: "。", with: "。\n")
content = content.replacingOccurrences(of: "", with: "\n")
content = content.replacingOccurrences(of: "\n\n", with: "")
content = content.replacingOccurrences(of: ":一、", with: "\n\n一、")
content = content.replacingOccurrences(of: " ", with: "")
content = content.replacingOccurrences(of: "---", with: "---\n")
content = content.replacingOccurrences(of: "日星期", with: "日 星期")
content = "# " + content
content = insertEmptyLineAfterFirstLine(content)
return content
}
private func formatForNote(_ text: String) -> String {
var content = text
content = content.replacingOccurrences(of: " ", with: "")
content = content.replacingOccurrences(of: "# ", with: "")
content = content.replacingOccurrences(of: "#", with: "")
content = content.replacingOccurrences(of: "", with: "。")
content = content.replacingOccurrences(of: "!", with: "。")
content = content.replacingOccurrences(of: ";", with: "。")
content = content.replacingOccurrences(of: "", with: "。")
content = content.replacingOccurrences(of: ".", with: "。")
content = content.replacingOccurrences(of: "", with: "(")
content = content.replacingOccurrences(of: "", with: ")")
content = content.replacingOccurrences(of: "?", with: "")
content = content.replacingOccurrences(of: ",", with: "")
content = content.replacingOccurrences(of: ":", with: "")
content = content.replacingOccurrences(of: "。", with: "。\n")
content = content.replacingOccurrences(of: "", with: "\n")
content = removeEmptyLines(content)
content = content.replacingOccurrences(of: "---", with: "")
content = content.replacingOccurrences(of: "日星期", with: "日 星期")
content = insertEmptyLineAfterFirstLine(content)
return content
}
private func removeEmptyLines(_ text: String) -> String {
let lines = text.components(separatedBy: .newlines)
let nonEmptyLines = lines.filter { !$0.trimmingCharacters(in: .whitespaces).isEmpty }
return nonEmptyLines.joined(separator: "\n")
}
private func insertEmptyLineAfterFirstLine(_ text: String) -> String {
var lines = text.components(separatedBy: .newlines)
if !lines.isEmpty {
lines.insert("", at: 1)
}
return lines.joined(separator: "\n")
}
}
extension FormatNoteViewController: UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
updateRightBarButtonItem()
}
func textViewDidEndEditing(_ textView: UITextView) {
updateRightBarButtonItem()
}
}