diff options
| author | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
| commit | 659c76df9ff3926cb68886c16167808c23bd8f75 (patch) | |
| tree | 572bef546fcca19ad37bc1aa7cfb153eb2bf8eb7 /Hutch/Views/Pastes/PasteListViewModel.swift | |
| parent | ed48e72520c51e4635cd3840dbc569bdd74c950f (diff) | |
| parent | 6ba4e967d5dfb5d3c7bb97a0f2662f3180595563 (diff) | |
| download | hutch-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.swift | 109 |
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 } + } +} |
