| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- import AppKit
- import Combine
- import Foundation
- @MainActor
- final class PunctuationCheckerViewModel: ObservableObject {
- static let maxWords = 1_000
- @Published var text: String = ""
- @Published private(set) var correctedText: String = ""
- @Published private(set) var issues: [GrammarIssue] = []
- @Published private(set) var hasResults = false
- @Published private(set) var isChecking = false
- @Published private(set) var errorMessage: String?
- private let punctuationCheckService: any PunctuationCheckServicing
- private let textExtractionService: any TextExtracting
- init(
- punctuationCheckService: any PunctuationCheckServicing = PunctuationCheckService(),
- textExtractionService: any TextExtracting = TextExtractionService()
- ) {
- self.punctuationCheckService = punctuationCheckService
- self.textExtractionService = textExtractionService
- }
- var wordCountLimitLabel: String {
- "\(text.wordCount)/\(Self.maxWords)"
- }
- var canCheck: Bool {
- !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && !isChecking
- }
- func pasteText() {
- guard let clipboard = NSPasteboard.general.string(forType: .string) else { return }
- text = WordLimit.applyImported(clipboard, maxWords: Self.maxWords, setError: { errorMessage = $0 })
- resetResults()
- }
- func uploadFile() {
- Task {
- do {
- guard let extracted = try await textExtractionService.pickAndExtractText() else { return }
- text = WordLimit.applyImported(extracted, maxWords: Self.maxWords, setError: { errorMessage = $0 })
- resetResults()
- } catch {
- errorMessage = error.localizedDescription
- }
- }
- }
- func notifyWordLimitReached() {
- errorMessage = WordLimit.message(maxWords: Self.maxWords)
- }
- func handleTextChange() {
- let (limited, exceeded) = WordLimit.apply(text, maxWords: Self.maxWords)
- if exceeded {
- text = limited
- errorMessage = WordLimit.message(maxWords: Self.maxWords)
- } else if errorMessage == WordLimit.message(maxWords: Self.maxWords) {
- errorMessage = nil
- }
- if hasResults {
- resetResults()
- }
- }
- func clearText() {
- text = ""
- resetResults()
- }
- func resetResults() {
- correctedText = ""
- issues = []
- hasResults = false
- errorMessage = nil
- }
- func checkPunctuation() {
- let content = text.trimmingCharacters(in: .whitespacesAndNewlines)
- guard !content.isEmpty else {
- resetResults()
- return
- }
- isChecking = true
- errorMessage = nil
- Task {
- do {
- let result = try await punctuationCheckService.checkPunctuation(in: content)
- correctedText = result.correctedText
- issues = result.issues
- hasResults = true
- } catch {
- errorMessage = error.localizedDescription
- }
- isChecking = false
- }
- }
- func copyCorrectedText() {
- guard !correctedText.isEmpty else { return }
- NSPasteboard.general.clearContents()
- NSPasteboard.general.setString(correctedText, forType: .string)
- }
- }
|