198 lines
6.4 KiB
Swift
198 lines
6.4 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 showEmptyAlert: Bool = false
|
||
@State private var showCopied: Bool = false
|
||
|
||
var body: some View {
|
||
NavigationStack {
|
||
VStack(spacing: 0) {
|
||
headerView
|
||
|
||
inputArea
|
||
.frame(maxHeight: .infinity)
|
||
|
||
actionArea
|
||
}
|
||
.background(Color(.systemGroupedBackground).ignoresSafeArea())
|
||
.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()
|
||
Menu {
|
||
Button(action: copyText) {
|
||
Label("复制", systemImage: "doc.on.doc")
|
||
}
|
||
.disabled(inputText.isEmpty)
|
||
Button(role: .destructive, action: clearText) {
|
||
Label("清除", systemImage: "xmark.circle")
|
||
}
|
||
.disabled(inputText.isEmpty)
|
||
} label: {
|
||
Image(systemName: "ellipsis")
|
||
.font(.system(size: 20, weight: .bold))
|
||
.foregroundStyle(.primary)
|
||
.frame(width: 44, height: 44)
|
||
.background(.ultraThinMaterial)
|
||
.clipShape(Circle())
|
||
}
|
||
}
|
||
.frame(maxWidth: .infinity, minHeight: 44)
|
||
.padding(.horizontal)
|
||
.padding(.top, 8)
|
||
.padding(.bottom, 8)
|
||
.background(Color(.systemGroupedBackground))
|
||
.contentShape(Rectangle())
|
||
.onTapGesture {
|
||
dismissKeyboard()
|
||
}
|
||
}
|
||
|
||
private var inputArea: some View {
|
||
VStack(alignment: .leading, spacing: 8) {
|
||
Text("输入")
|
||
.font(.subheadline)
|
||
.foregroundStyle(.secondary)
|
||
.padding(.horizontal)
|
||
|
||
TextEditor(text: $inputText)
|
||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||
.padding(12)
|
||
.background(Color(.systemBackground))
|
||
.cornerRadius(12)
|
||
.overlay(
|
||
RoundedRectangle(cornerRadius: 12)
|
||
.stroke(Color(.systemGray4), lineWidth: 1)
|
||
)
|
||
.padding(.horizontal)
|
||
.toolbar {
|
||
ToolbarItemGroup(placement: .keyboard) {
|
||
Spacer()
|
||
Button("完成") {
|
||
dismissKeyboard()
|
||
}
|
||
}
|
||
}
|
||
|
||
Text("粘贴需要格式化的文案")
|
||
.font(.subheadline)
|
||
.foregroundStyle(.secondary)
|
||
.padding(.horizontal)
|
||
}
|
||
.padding(.vertical, 8)
|
||
}
|
||
|
||
private var actionArea: some View {
|
||
Button(action: formatText) {
|
||
Label("格式化", systemImage: "wand.and.stars")
|
||
.font(.headline)
|
||
.frame(maxWidth: .infinity)
|
||
.padding()
|
||
.background(Color(.systemBackground))
|
||
.foregroundStyle(Color.accentColor)
|
||
.cornerRadius(12)
|
||
}
|
||
.padding()
|
||
.background(Color(.systemGroupedBackground))
|
||
}
|
||
|
||
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
|
||
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: "## 三、工作方面")
|
||
|
||
inputText = content
|
||
dismissKeyboard()
|
||
}
|
||
|
||
private func copyText() {
|
||
UIPasteboard.general.string = inputText
|
||
withAnimation {
|
||
showCopied = true
|
||
}
|
||
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
|
||
withAnimation {
|
||
showCopied = false
|
||
}
|
||
}
|
||
}
|
||
|
||
private func clearText() {
|
||
inputText = ""
|
||
}
|
||
}
|
||
|
||
#Preview {
|
||
FormatterView()
|
||
}
|