| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- import AppKit
- import Combine
- import Foundation
- @MainActor
- final class WordsCountViewModel: ObservableObject {
- static let maxWords = 1_000
- @Published var text: String = ""
- @Published private(set) var errorMessage: String?
- private let textExtractionService: any TextExtracting
- init(textExtractionService: any TextExtracting = TextExtractionService()) {
- self.textExtractionService = textExtractionService
- }
- var characterCount: Int { text.count }
- var wordCountLimitLabel: String {
- "\(wordCount)/\(Self.maxWords)"
- }
- var wordCount: Int {
- text.wordCount
- }
- var wordCountLabel: String {
- "\(wordCount) Words Count"
- }
- var sentenceCount: Int {
- let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
- guard !trimmed.isEmpty else { return 0 }
- let sentences = trimmed.components(separatedBy: CharacterSet(charactersIn: ".!?"))
- .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
- .filter { !$0.isEmpty }
- return max(sentences.count, 1)
- }
- var paragraphCount: Int {
- let paragraphs = text
- .components(separatedBy: .newlines)
- .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
- .filter { !$0.isEmpty }
- return paragraphs.count
- }
- func pasteText() {
- guard let clipboard = NSPasteboard.general.string(forType: .string) else { return }
- text = WordLimit.applyImported(clipboard, maxWords: Self.maxWords, setError: { errorMessage = $0 })
- }
- func uploadFile() {
- Task {
- do {
- guard let extracted = try await textExtractionService.pickAndExtractText() else { return }
- text = WordLimit.applyImported(extracted, maxWords: Self.maxWords, setError: { errorMessage = $0 })
- } catch {
- errorMessage = UserFacingError.message(for: error)
- }
- }
- }
- 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
- }
- }
- func clearText() {
- text = ""
- errorMessage = nil
- }
- }
|