blob: 8c60edddd70e0a7543d3c67d2fe5f98c57e2a239 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
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
}
}
}
|