IceCubesApp/Packages/Status/Sources/Status/Editor/StatusEditorViewModel.swift

112 lines
3.5 KiB
Swift
Raw Normal View History

2022-12-25 05:55:33 +00:00
import SwiftUI
import DesignSystem
2022-12-25 07:17:16 +00:00
import Models
import Network
2022-12-25 18:15:35 +00:00
import PhotosUI
2022-12-25 05:55:33 +00:00
@MainActor
class StatusEditorViewModel: ObservableObject {
@Published var statusText = NSAttributedString(string: "") {
didSet {
guard !internalUpdate else { return }
highlightMeta()
}
}
2022-12-25 16:46:51 +00:00
@Published var isPosting: Bool = false
2022-12-25 18:15:35 +00:00
@Published var selectedMedias: [PhotosPickerItem] = [] {
didSet {
inflateSelectedMedias()
}
}
@Published var mediasImages: [ImageContainer] = []
struct ImageContainer: Identifiable {
let id = UUID().uuidString
let image: UIImage
}
2022-12-25 16:46:51 +00:00
2022-12-25 07:17:16 +00:00
var client: Client?
2022-12-25 05:55:33 +00:00
private var internalUpdate: Bool = false
2022-12-25 07:17:16 +00:00
private var inReplyTo: Status?
2022-12-25 16:46:51 +00:00
let generator = UINotificationFeedbackGenerator()
2022-12-25 07:17:16 +00:00
init(inReplyTo: Status?) {
self.inReplyTo = inReplyTo
}
func postStatus() async -> Status? {
guard let client else { return nil }
do {
2022-12-25 16:46:51 +00:00
isPosting = true
2022-12-25 07:17:16 +00:00
let status: Status = try await client.post(endpoint: Statuses.postStatus(status: statusText.string,
inReplyTo: inReplyTo?.id,
mediaIds: nil,
spoilerText: nil))
2022-12-25 16:46:51 +00:00
generator.notificationOccurred(.success)
isPosting = false
2022-12-25 07:17:16 +00:00
return status
} catch {
2022-12-25 16:46:51 +00:00
isPosting = false
generator.notificationOccurred(.error)
2022-12-25 07:17:16 +00:00
return nil
}
}
func insertReplyTo() {
if let inReplyTo {
statusText = .init(string: "@\(inReplyTo.account.acct) ")
}
}
2022-12-25 05:55:33 +00:00
func highlightMeta() {
2022-12-25 16:46:51 +00:00
let mutableString = NSMutableAttributedString(string: statusText.string)
mutableString.addAttributes([.foregroundColor: UIColor(Color.label)],
range: NSMakeRange(0, mutableString.string.utf16.count))
2022-12-25 05:55:33 +00:00
let hashtagPattern = "(#+[a-zA-Z0-9(_)]{1,})"
2022-12-25 07:17:16 +00:00
let mentionPattern = "(@+[a-zA-Z0-9(_).]{1,})"
2022-12-25 05:55:33 +00:00
var ranges: [NSRange] = [NSRange]()
do {
let hashtagRegex = try NSRegularExpression(pattern: hashtagPattern, options: [])
let mentionRegex = try NSRegularExpression(pattern: mentionPattern, options: [])
ranges = hashtagRegex.matches(in: mutableString.string,
options: [],
range: NSMakeRange(0, mutableString.string.utf16.count)).map { $0.range }
ranges.append(contentsOf: mentionRegex.matches(in: mutableString.string,
options: [],
range: NSMakeRange(0, mutableString.string.utf16.count)).map {$0.range})
2022-12-25 05:55:33 +00:00
for range in ranges {
mutableString.addAttributes([.foregroundColor: UIColor(Color.brand)],
range: NSRange(location: range.location, length: range.length))
}
internalUpdate = true
statusText = mutableString
internalUpdate = false
} catch {
2022-12-25 05:55:33 +00:00
}
}
2022-12-25 18:15:35 +00:00
func inflateSelectedMedias() {
for media in selectedMedias {
media.loadTransferable(type: Data.self) { [weak self] result in
switch result {
case .success(let data?):
if let image = UIImage(data: data) {
DispatchQueue.main.async {
self?.mediasImages.append(.init(image: image))
}
}
default:
break
}
}
}
}
2022-12-25 05:55:33 +00:00
}