summaryrefslogtreecommitdiff
path: root/Sora
diff options
context:
space:
mode:
Diffstat (limited to 'Sora')
-rw-r--r--Sora/Data/Booru/BooruManager.swift49
-rw-r--r--Sora/Data/Settings/SettingsManager.swift3
-rw-r--r--Sora/Views/MainView.swift7
-rw-r--r--Sora/Views/Settings/Section/SettingsSectionProviderView.swift4
4 files changed, 51 insertions, 12 deletions
diff --git a/Sora/Data/Booru/BooruManager.swift b/Sora/Data/Booru/BooruManager.swift
index 5753089..3c4374e 100644
--- a/Sora/Data/Booru/BooruManager.swift
+++ b/Sora/Data/Booru/BooruManager.swift
@@ -27,6 +27,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
private let cacheDuration: TimeInterval
private let credentials: BooruProviderCredentials?
private let userAgent: String
+ private let showHeldMoebooruPosts: Bool
private var urlCache: [String: URL] = [:]
private var lastPostCount = 0
@@ -45,13 +46,15 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
init(
_ provider: BooruProvider,
credentials: BooruProviderCredentials? = nil,
- cacheDuration: TimeInterval = BooruPageCacheEntry.defaultExpiration
+ cacheDuration: TimeInterval = BooruPageCacheEntry.defaultExpiration,
+ showHeldMoebooruPosts: Bool = false
) {
self.provider = provider
self.flavor = BooruProviderFlavor(provider: provider)
self.domain = provider.domain
self.credentials = credentials
self.cacheDuration = cacheDuration
+ self.showHeldMoebooruPosts = showHeldMoebooruPosts
pageCache.countLimit = 50
pageCache.totalCostLimit = 50 * 1_024 * 1_024
@@ -134,7 +137,6 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
flavor: flavor,
provider: provider
)
- .sorted { $0.createdAt > $1.createdAt }
continuation.resume(returning: parsedPosts)
}
@@ -312,8 +314,31 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
}
// MARK: - Private Methods
- private func danbooruPageToken(for page: Int) -> String {
+ private func moebooruTagString(for tags: [String]) -> String {
+ let hasExplicitHoldsFilter = tags.contains { tag in
+ tag.lowercased().hasPrefix("holds:")
+ }
+
+ if hasExplicitHoldsFilter {
+ return tags.joined(separator: "+")
+ }
+
+ guard !showHeldMoebooruPosts else {
+ return tags.joined(separator: "+")
+ }
+
+ return (tags + ["holds:false"]).joined(separator: "+")
+ }
+
+ private func hasExplicitSortTag(in tags: [String]) -> Bool {
+ tags.contains { tag in
+ tag.lowercased().hasPrefix("order:")
+ }
+ }
+
+ private func danbooruPageToken(for page: Int, tags: [String]) -> String {
guard page > 1 else { return "1" }
+ guard !hasExplicitSortTag(in: tags) else { return String(page) }
guard let minimumPostID = posts.lazy.compactMap({ Int($0.id) }).min() else {
return String(page)
@@ -324,7 +349,8 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
func url(forPosts page: Int, limit: Int, tags: [String]) -> URL? {
let tagString = tags.joined(separator: "+")
- let pageCacheValue = flavor == .danbooru ? danbooruPageToken(for: page) : String(page)
+ let pageCacheValue =
+ flavor == .danbooru ? danbooruPageToken(for: page, tags: tags) : String(page)
let cacheKey = "posts_\(pageCacheValue)_\(limit)_\(tagString.hashValue)"
if let cachedURL = urlCache[cacheKey] {
@@ -342,7 +368,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
components.path = "/posts.json"
var queryItems = [
- URLQueryItem(name: "page", value: danbooruPageToken(for: page)),
+ URLQueryItem(name: "page", value: danbooruPageToken(for: page, tags: tags)),
URLQueryItem(name: "limit", value: String(limit)),
URLQueryItem(name: "tags", value: tagString),
]
@@ -361,6 +387,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
case .moebooru:
var components = URLComponents()
+ let moebooruTags = moebooruTagString(for: tags)
components.scheme = "https"
components.host = domain
@@ -368,7 +395,7 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
components.queryItems = [
URLQueryItem(name: "page", value: String(page)),
URLQueryItem(name: "limit", value: String(limit)),
- URLQueryItem(name: "tags", value: tagString),
+ URLQueryItem(name: "tags", value: moebooruTags),
]
url = components.url
@@ -499,13 +526,15 @@ class BooruManager: ObservableObject { // swiftlint:disable:this type_body_leng
flavor == .danbooru
? DanbooruPostParser(data: data).parse()
: BooruPostXMLParser(data: data, provider: provider).parse()
- var uniquePosts: [String: BooruPost] = [:]
- for post in parsedPosts {
- uniquePosts[post.id] = post
+ var seenPostIDs = Set<String>()
+ var orderedUniquePosts: [BooruPost] = []
+
+ for post in parsedPosts where seenPostIDs.insert(post.id).inserted {
+ orderedUniquePosts.append(post)
}
- return Array(uniquePosts.values)
+ return orderedUniquePosts
}
private func updatePosts(_ newPosts: [BooruPost], replace: Bool) {
diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift
index ddeb1e4..b07b38c 100644
--- a/Sora/Data/Settings/SettingsManager.swift
+++ b/Sora/Data/Settings/SettingsManager.swift
@@ -35,6 +35,9 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l
@AppStorage("uniformThumbnailGrid")
private var _uniformThumbnailGrid: Bool = false
+ @AppStorage("showHeldMoebooruPosts")
+ var showHeldMoebooruPosts = false
+
private var syncObservation: NSObjectProtocol?
#if os(macOS)
diff --git a/Sora/Views/MainView.swift b/Sora/Views/MainView.swift
index aa89aa3..770d424 100644
--- a/Sora/Views/MainView.swift
+++ b/Sora/Views/MainView.swift
@@ -19,6 +19,7 @@ struct MainView: View {
}
.onAppear(perform: initializeManager)
.onChange(of: settings.providerCredentials) { initializeManager() }
+ .onChange(of: settings.showHeldMoebooruPosts) { initializeManager() }
#if os(macOS)
.onChange(of: selectedTab) { _, newValue in
if newValue == 0 {
@@ -119,7 +120,8 @@ struct MainView: View {
manager = BooruManager(
provider,
credentials: settings.providerCredentials
- .first { $0.provider == settings.preferredBooru }
+ .first { $0.provider == settings.preferredBooru },
+ showHeldMoebooruPosts: settings.showHeldMoebooruPosts
)
manager.searchText = previousSearchText
@@ -136,7 +138,8 @@ struct MainView: View {
manager = BooruManager(
settings.preferredBooru,
credentials: settings.providerCredentials
- .first { $0.provider == settings.preferredBooru }
+ .first { $0.provider == settings.preferredBooru },
+ showHeldMoebooruPosts: settings.showHeldMoebooruPosts
)
Task(priority: .userInitiated) {
diff --git a/Sora/Views/Settings/Section/SettingsSectionProviderView.swift b/Sora/Views/Settings/Section/SettingsSectionProviderView.swift
index 172ddc6..9ba7610 100644
--- a/Sora/Views/Settings/Section/SettingsSectionProviderView.swift
+++ b/Sora/Views/Settings/Section/SettingsSectionProviderView.swift
@@ -22,6 +22,10 @@ struct SettingsSectionProviderView: View {
}
}
+ Section(header: Text("Moebooru Feed")) {
+ Toggle("Show Held Posts", isOn: $settings.showHeldMoebooruPosts)
+ }
+
Section(header: Text("API Credentials")) {
SecureField(
"API Key",