summaryrefslogtreecommitdiff
path: root/Hutch/Views/Pastes/PasteListViewModel.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/PasteListViewModel.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/PasteListViewModel.swift')
-rw-r--r--Hutch/Views/Pastes/PasteListViewModel.swift109
1 files changed, 109 insertions, 0 deletions
diff --git a/Hutch/Views/Pastes/PasteListViewModel.swift b/Hutch/Views/Pastes/PasteListViewModel.swift
new file mode 100644
index 0000000..ee7d47a
--- /dev/null
+++ b/Hutch/Views/Pastes/PasteListViewModel.swift
@@ -0,0 +1,109 @@
+import Foundation
+
+@Observable
+@MainActor
+final class PasteListViewModel {
+ private(set) var pastes: [Paste] = []
+ private(set) var isLoading = false
+ private(set) var isLoadingMore = false
+ private(set) var isRefreshing = false
+ private(set) var isCreatingPaste = false
+ var error: String?
+
+ private var cursor: String?
+ private var hasMore = true
+ private let service: PasteService
+
+ init(service: PasteService) {
+ self.service = service
+ }
+
+ func loadPastes() async {
+ if pastes.isEmpty, let cached = service.loadCachedPastes() {
+ pastes = cached.results
+ cursor = cached.cursor
+ hasMore = cached.cursor != nil
+ }
+
+ if pastes.isEmpty {
+ isLoading = true
+ } else {
+ isRefreshing = true
+ }
+ error = nil
+ cursor = nil
+ hasMore = true
+
+ do {
+ let page = try await service.listPastes(cursor: nil, useCache: true)
+ pastes = page.results
+ cursor = page.cursor
+ hasMore = page.cursor != nil
+ } catch {
+ if pastes.isEmpty {
+ self.error = error.localizedDescription
+ }
+ }
+
+ isLoading = false
+ isRefreshing = false
+ }
+
+ func loadMoreIfNeeded(currentItem: Paste) async {
+ guard let last = pastes.last,
+ last.id == currentItem.id,
+ hasMore,
+ !isLoadingMore else {
+ return
+ }
+
+ isLoadingMore = true
+ defer { isLoadingMore = false }
+
+ do {
+ let page = try await service.listPastes(cursor: cursor, useCache: false)
+ pastes.append(contentsOf: page.results)
+ cursor = page.cursor
+ hasMore = page.cursor != nil
+ } catch {
+ self.error = error.localizedDescription
+ }
+ }
+
+ func createPaste(files: [PasteUploadDraft], visibility: Visibility) async -> Paste? {
+ guard !isCreatingPaste else { return nil }
+
+ let normalizedFiles = files.filter {
+ !$0.contents.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
+ }
+ guard !normalizedFiles.isEmpty else {
+ error = "Add at least one file with text content."
+ return nil
+ }
+
+ isCreatingPaste = true
+ error = nil
+ defer { isCreatingPaste = false }
+
+ do {
+ let paste = try await service.createPaste(files: normalizedFiles, visibility: visibility)
+ upsertPaste(paste)
+ return paste
+ } catch {
+ self.error = error.localizedDescription
+ return nil
+ }
+ }
+
+ func upsertPaste(_ paste: Paste) {
+ if let index = pastes.firstIndex(where: { $0.id == paste.id }) {
+ pastes[index] = paste
+ } else {
+ pastes.insert(paste, at: 0)
+ }
+ }
+
+ func removePaste(id: String) {
+ pastes.removeAll { $0.id == id }
+ }
+}