blob: fd8d3370df4d44bbfcf7277e2fc9d0fa680b6588 (
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 SwiftUI
@MainActor
class MoebooruManager: ObservableObject {
@Published var posts: [MoebooruPost] = []
@Published var allTags: [MoebooruTag] = []
@Published var isLoading: Bool = false
@Published var currentPage: Int = 1
@Published var searchText = ""
@Published var endOfData: Bool = false
#if os(macOS)
@Published var selectedPost: MoebooruPost?
#endif
private var currentTask: Task<Void, Never>?
var tags: [String] {
if searchText.isEmpty {
return []
}
return searchText
.split(separator: " ")
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
}
init() {
fetchAllTags()
}
func fetchPosts(page: Int = 1, limit: Int = 100, tags: [String] = [], replace: Bool = false) async {
guard !isLoading else { return }
currentTask?.cancel()
currentTask = Task {
isLoading = true
defer { isLoading = false }
if replace {
self.posts = []
self.currentPage = 1
}
guard let url = URL(string: "https://yande.re/post.xml?page=\(page)&limit=\(limit)&tags=\(tags.joined(separator: "+"))") else { return }
do {
let (data, _) = try await URLSession.shared.data(from: url)
if Task.isCancelled { return }
DispatchQueue.main.async {
let newPosts = Array(Set(MoebooruPostXMLParser().parse(data: data))).sorted { $0.id > $1.id }
if newPosts == [] {
self.endOfData = true
} else {
self.posts += newPosts
}
}
} catch {
if (error as? URLError)?.code != .cancelled {
#if DEBUG
print(error)
#endif
}
}
}
}
func performSearch() {
Task {
await fetchPosts(
page: 1,
tags: tags,
replace: true
)
}
}
func loadNextPage() {
guard !isLoading else { return }
Task {
await fetchPosts(page: currentPage + 1, tags: tags)
DispatchQueue.main.async {
self.currentPage += 1
}
}
}
func fetchAllTags(limit: Int = 100_000) {
Task {
guard let url = URL(string: "https://yande.re/tag.xml?limit=\(limit)") else { return }
do {
let (data, _) = try await URLSession.shared.data(from: url)
if Task.isCancelled { return }
DispatchQueue.main.async {
self.allTags = (MoebooruTagXMLParser().parse(data: data)).sorted { $0.count > $1.count }
}
} catch {
if (error as? URLError)?.code != .cancelled {
#if DEBUG
print(error)
#endif
}
}
}
}
}
|