188 lines
6.8 KiB
Swift
188 lines
6.8 KiB
Swift
//
|
||
// FormatterView.swift
|
||
// Note
|
||
//
|
||
// Created by fish on 2026/7/12.
|
||
//
|
||
|
||
import SwiftUI
|
||
|
||
struct FormatterView: View {
|
||
@State private var inputText: String = ""
|
||
@State private var outputText: String = ""
|
||
@State private var showEmptyAlert: Bool = false
|
||
@State private var showCopied: Bool = false
|
||
|
||
var body: some View {
|
||
NavigationStack {
|
||
VStack(spacing: 0) {
|
||
headerView
|
||
.background(Color(hex: "f2f2f7"))
|
||
|
||
ScrollView {
|
||
VStack(spacing: 16) {
|
||
TextEditor(text: $inputText)
|
||
.frame(minHeight: 160)
|
||
.padding(8)
|
||
.background(Color(.systemBackground))
|
||
.cornerRadius(8)
|
||
.overlay(
|
||
RoundedRectangle(cornerRadius: 8)
|
||
.stroke(Color(.systemGray4), lineWidth: 1)
|
||
)
|
||
.toolbar {
|
||
ToolbarItemGroup(placement: .keyboard) {
|
||
Spacer()
|
||
Button("完成") {
|
||
dismissKeyboard()
|
||
}
|
||
}
|
||
}
|
||
|
||
Button(action: formatText) {
|
||
Label("格式化", systemImage: "wand.and.stars")
|
||
.font(.headline)
|
||
.frame(maxWidth: .infinity)
|
||
.padding()
|
||
.background(Color.accentColor)
|
||
.foregroundStyle(.white)
|
||
.cornerRadius(10)
|
||
}
|
||
|
||
if !outputText.isEmpty {
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
HStack {
|
||
Text("格式化结果")
|
||
.font(.subheadline)
|
||
.foregroundStyle(.secondary)
|
||
Spacer()
|
||
Button(action: copyOutput) {
|
||
Image(systemName: "doc.on.doc")
|
||
}
|
||
}
|
||
|
||
TextEditor(text: .constant(outputText))
|
||
.frame(minHeight: 160)
|
||
.padding(8)
|
||
.background(Color(.systemBackground))
|
||
.cornerRadius(8)
|
||
.overlay(
|
||
RoundedRectangle(cornerRadius: 8)
|
||
.stroke(Color(.systemGray4), lineWidth: 1)
|
||
)
|
||
}
|
||
}
|
||
|
||
Spacer(minLength: 16)
|
||
}
|
||
.padding()
|
||
}
|
||
.background(Color(hex: "f2f2f7"))
|
||
}
|
||
.background(Color(hex: "f2f2f7").ignoresSafeArea())
|
||
.onTapGesture {
|
||
dismissKeyboard()
|
||
}
|
||
.alert("提示", isPresented: $showEmptyAlert) {
|
||
Button("确定", role: .cancel) {}
|
||
} message: {
|
||
Text("请输入需要格式化的文案")
|
||
}
|
||
.overlay {
|
||
if showCopied {
|
||
VStack {
|
||
Spacer()
|
||
Text("已复制")
|
||
.font(.subheadline)
|
||
.padding(.horizontal, 16)
|
||
.padding(.vertical, 8)
|
||
.background(Color.black.opacity(0.75))
|
||
.foregroundStyle(.white)
|
||
.cornerRadius(20)
|
||
.padding(.bottom, 32)
|
||
}
|
||
.transition(.opacity)
|
||
}
|
||
}
|
||
.navigationBarHidden(true)
|
||
}
|
||
}
|
||
|
||
private var headerView: some View {
|
||
HStack {
|
||
Text("文案格式化")
|
||
.font(.largeTitle.bold())
|
||
.foregroundStyle(.primary)
|
||
Spacer()
|
||
}
|
||
.frame(maxWidth: .infinity, minHeight: 44)
|
||
.padding(.horizontal)
|
||
.padding(.top, 8)
|
||
.padding(.bottom, 8)
|
||
.contentShape(Rectangle())
|
||
.onTapGesture {
|
||
dismissKeyboard()
|
||
}
|
||
}
|
||
|
||
private func dismissKeyboard() {
|
||
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
|
||
}
|
||
|
||
private func formatText() {
|
||
if inputText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||
showEmptyAlert = true
|
||
outputText = ""
|
||
return
|
||
}
|
||
|
||
var content = inputText
|
||
|
||
// 去 #
|
||
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
|
||
// 标题设置
|
||
content = content.replacingOccurrences(of: "一、生活方面", with: "## 一、生活方面")
|
||
content = content.replacingOccurrences(of: "二、交易方面", with: "## 二、交易方面")
|
||
content = content.replacingOccurrences(of: "三、工作方面", with: "## 三、工作方面")
|
||
|
||
outputText = content
|
||
}
|
||
|
||
private func copyOutput() {
|
||
UIPasteboard.general.string = outputText
|
||
withAnimation {
|
||
showCopied = true
|
||
}
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
|
||
withAnimation {
|
||
showCopied = false
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#Preview {
|
||
FormatterView()
|
||
}
|