summaryrefslogtreecommitdiff
path: root/Hutch/Views/Pastes/PasteDetailViewModel.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-03-19 15:18:38 -0500
committerChristian Cleberg <[email protected]>2026-03-19 15:18:38 -0500
commit659c76df9ff3926cb68886c16167808c23bd8f75 (patch)
tree572bef546fcca19ad37bc1aa7cfb153eb2bf8eb7 /Hutch/Views/Pastes/PasteDetailViewModel.swift
parented48e72520c51e4635cd3840dbc569bdd74c950f (diff)
parent6ba4e967d5dfb5d3c7bb97a0f2662f3180595563 (diff)
downloadhutch-2.tar.gz
hutch-2.tar.bz2
hutch-2.zip
v2.0: Merge branch 'dev'v2
Diffstat (limited to 'Hutch/Views/Pastes/PasteDetailViewModel.swift')
-rw-r--r--Hutch/Views/Pastes/PasteDetailViewModel.swift114
1 files changed, 114 insertions, 0 deletions
diff --git a/Hutch/Views/Pastes/PasteDetailViewModel.swift b/Hutch/Views/Pastes/PasteDetailViewModel.swift
new file mode 100644
index 0000000..8c60edd
--- /dev/null
+++ b/Hutch/Views/Pastes/PasteDetailViewModel.swift
@@ -0,0 +1,114 @@
+import Foundation
+
+@Observable
+@MainActor
+final class PasteDetailViewModel {
+ private(set) var paste: Paste?
+ private(set) var isLoading = false
+ private(set) var isUpdatingVisibility = false
+ private(set) var isDeleting = false
+ private(set) var loadingFileHashes: Set<String> = []
+ var error: String?
+
+ var selectedFileHash: String?
+ private(set) var fileContents: [String: String] = [:]
+
+ private let pasteID: String
+ private let service: PasteService
+
+ init(pasteID: String, initialPaste: Paste? = nil, service: PasteService) {
+ self.pasteID = pasteID
+ self.paste = initialPaste
+ self.service = service
+ self.selectedFileHash = initialPaste?.files.first?.hash
+ }
+
+ var selectedFile: PasteFile? {
+ let hash = selectedFileHash ?? paste?.files.first?.hash
+ return paste?.files.first(where: { $0.hash == hash })
+ }
+
+ var selectedFileContents: String? {
+ guard let selectedFile else { return nil }
+ return fileContents[selectedFile.hash]
+ }
+
+ func loadPaste() async {
+ guard !isLoading else { return }
+ isLoading = true
+ error = nil
+ defer { isLoading = false }
+
+ do {
+ let loaded = try await service.loadPaste(id: pasteID)
+ paste = loaded
+ if selectedFileHash == nil {
+ selectedFileHash = loaded?.files.first?.hash
+ }
+ await loadSelectedFileContentsIfNeeded()
+ } catch {
+ self.error = error.localizedDescription
+ }
+ }
+
+ func selectFile(hash: String) {
+ selectedFileHash = hash
+ Task {
+ await loadSelectedFileContentsIfNeeded()
+ }
+ }
+
+ func updateVisibility(_ visibility: Visibility) async -> Paste? {
+ guard !isUpdatingVisibility else { return nil }
+ guard let paste else { return nil }
+ guard paste.visibility != visibility else { return paste }
+
+ isUpdatingVisibility = true
+ error = nil
+ defer { isUpdatingVisibility = false }
+
+ do {
+ let updatedPaste = try await service.updateVisibility(id: paste.id, visibility: visibility)
+ if let updatedPaste {
+ self.paste = updatedPaste
+ if selectedFileHash == nil {
+ selectedFileHash = updatedPaste.files.first?.hash
+ }
+ }
+ return updatedPaste
+ } catch {
+ self.error = error.localizedDescription
+ return nil
+ }
+ }
+
+ func deletePaste() async -> Bool {
+ guard !isDeleting else { return false }
+ isDeleting = true
+ error = nil
+ defer { isDeleting = false }
+
+ do {
+ _ = try await service.deletePaste(id: pasteID)
+ return true
+ } catch {
+ self.error = error.localizedDescription
+ return false
+ }
+ }
+
+ func loadSelectedFileContentsIfNeeded() async {
+ guard let file = selectedFile, fileContents[file.hash] == nil else { return }
+ guard let url = file.contents else { return }
+ guard !loadingFileHashes.contains(file.hash) else { return }
+
+ loadingFileHashes.insert(file.hash)
+ defer { loadingFileHashes.remove(file.hash) }
+
+ do {
+ fileContents[file.hash] = try await service.loadContents(from: url)
+ } catch {
+ self.error = error.localizedDescription
+ }
+ }
+}