summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-07-11 06:32:46 -0700
committerFuwn <[email protected]>2025-07-11 06:32:46 -0700
commit2e079945cb3c68ed05750757b59f0acc59155010 (patch)
tree23901f3b5ef4956f7983bccc2922b9b9378dfcbb
parentfeat: Development commit (diff)
downloadsora-testing-2e079945cb3c68ed05750757b59f0acc59155010.tar.xz
sora-testing-2e079945cb3c68ed05750757b59f0acc59155010.zip
feat: Development commit
-rw-r--r--Sora/Data/CollectionPickerOption.swift9
-rw-r--r--Sora/Data/Danbooru/DanbooruPostParser.swift4
-rw-r--r--Sora/Data/ImageCacheManager.swift25
-rw-r--r--Sora/Data/Scroll/ScrollPositionPreference.swift6
-rw-r--r--Sora/Data/Scroll/ScrollPositionPreferenceKey.swift19
-rw-r--r--Sora/Data/Settings/SettingsManager.swift7
-rw-r--r--Sora/Views/Generic/GenericListView.swift16
-rw-r--r--Sora/Views/Post/Details/PostDetailsImageView.swift8
-rw-r--r--project.yml1
9 files changed, 38 insertions, 57 deletions
diff --git a/Sora/Data/CollectionPickerOption.swift b/Sora/Data/CollectionPickerOption.swift
index 008d559..751e71c 100644
--- a/Sora/Data/CollectionPickerOption.swift
+++ b/Sora/Data/CollectionPickerOption.swift
@@ -18,16 +18,17 @@ enum CollectionPickerOption: Identifiable, Hashable {
}
}
- var name: (_ settings: SettingsManager) -> String {
+ @MainActor
+ func name(settings: SettingsManager) -> String {
switch self {
case .all:
- return { _ in "All" }
+ return "All"
case .folder(let id):
- return { settings in settings.folderName(forID: id) ?? "Unknown Folder" }
+ return settings.folderName(forID: id) ?? "Unknown Folder"
case .uncategorized:
- return { _ in "Uncategorised" }
+ return "Uncategorised"
}
}
}
diff --git a/Sora/Data/Danbooru/DanbooruPostParser.swift b/Sora/Data/Danbooru/DanbooruPostParser.swift
index fa62b5b..73db0cc 100644
--- a/Sora/Data/Danbooru/DanbooruPostParser.swift
+++ b/Sora/Data/Danbooru/DanbooruPostParser.swift
@@ -11,7 +11,7 @@ class DanbooruPostParser {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom { decoder in
- self.parseDate(
+ Self.parseDate(
try (try decoder.singleValueContainer()).decode(String.self)
) ?? Date()
}
@@ -25,7 +25,7 @@ class DanbooruPostParser {
}
}
- private func parseDate(_ input: String) -> Date? {
+ private static func parseDate(_ input: String) -> Date? {
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
diff --git a/Sora/Data/ImageCacheManager.swift b/Sora/Data/ImageCacheManager.swift
index ed68c67..8b886df 100644
--- a/Sora/Data/ImageCacheManager.swift
+++ b/Sora/Data/ImageCacheManager.swift
@@ -1,6 +1,7 @@
import Combine
import SwiftUI
+@MainActor
final class ImageCacheManager {
// MARK: - Singleton
static let shared = ImageCacheManager()
@@ -13,9 +14,6 @@ final class ImageCacheManager {
.appendingPathComponent("SoraImageCache", isDirectory: true)
)
private var cancellables = Set<AnyCancellable>()
- private let cancellablesQueue = DispatchQueue(
- label: "\(Bundle.main.bundleIdentifier!).ImageCacheManager.cancellablesQueue"
- )
private let downloadQueue = OperationQueue()
// MARK: - Initialisation
@@ -25,16 +23,19 @@ final class ImageCacheManager {
// MARK: - Public Methods
func preloadImages(_ urls: [URL]) {
- urls.forEach { url in
+ for url in urls {
downloadQueue.addOperation {
- self.cancellablesQueue.sync {
- URLSession.shared.dataTaskPublisher(for: url)
- .map { CachedURLResponse(response: $0.response, data: $0.data) }
- .sink(
- receiveCompletion: { _ in () },
- receiveValue: { [self] in cache.storeCachedResponse($0, for: URLRequest(url: url)) }
- )
- .store(in: &self.cancellables)
+ let cancellable = URLSession.shared.dataTaskPublisher(for: url)
+ .map { CachedURLResponse(response: $0.response, data: $0.data) }
+ .sink(
+ receiveCompletion: { _ in () },
+ receiveValue: { [weak self] cachedResponse in
+ self?.cache.storeCachedResponse(cachedResponse, for: URLRequest(url: url))
+ }
+ )
+
+ DispatchQueue.main.async { [weak self] in
+ self?.cancellables.insert(cancellable)
}
}
}
diff --git a/Sora/Data/Scroll/ScrollPositionPreference.swift b/Sora/Data/Scroll/ScrollPositionPreference.swift
deleted file mode 100644
index fb36bb1..0000000
--- a/Sora/Data/Scroll/ScrollPositionPreference.swift
+++ /dev/null
@@ -1,6 +0,0 @@
-import SwiftUI
-
-struct ScrollPositionPreference: Equatable {
- let id: BooruPost.ID
- let yPosition: CGFloat
-}
diff --git a/Sora/Data/Scroll/ScrollPositionPreferenceKey.swift b/Sora/Data/Scroll/ScrollPositionPreferenceKey.swift
deleted file mode 100644
index 6b78bdc..0000000
--- a/Sora/Data/Scroll/ScrollPositionPreferenceKey.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-import SwiftUI
-
-struct ScrollPositionPreferenceKey: PreferenceKey {
- typealias Value = ScrollPositionPreference?
-
- static var defaultValue: Value = nil
-
- static func reduce(value: inout Value, nextValue: () -> Value) {
- guard let next = nextValue() else { return }
-
- if let current = value {
- if abs(next.yPosition) < abs(current.yPosition) {
- value = next
- }
- } else {
- value = next
- }
- }
-}
diff --git a/Sora/Data/Settings/SettingsManager.swift b/Sora/Data/Settings/SettingsManager.swift
index 58583f1..435df1c 100644
--- a/Sora/Data/Settings/SettingsManager.swift
+++ b/Sora/Data/Settings/SettingsManager.swift
@@ -2,6 +2,7 @@
import SwiftUI
+@MainActor
class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_length
// MARK: - Stored Properties
@AppStorage("detailViewType")
@@ -34,7 +35,7 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l
@AppStorage("uniformThumbnailGrid")
private var _uniformThumbnailGrid: Bool = false
- private var syncObservation: NSObjectProtocol?
+ @preconcurrency private var syncObservation: (any NSObjectProtocol & Sendable)?
#if os(macOS)
@AppStorage("saveTagsToFile")
@@ -262,7 +263,9 @@ class SettingsManager: ObservableObject { // swiftlint:disable:this type_body_l
object: NSUbiquitousKeyValueStore.default,
queue: .main
) { [weak self] _ in
- self?.syncFromCloud()
+ Task { @MainActor in
+ self?.syncFromCloud()
+ }
}
loadBookmarksCache()
diff --git a/Sora/Views/Generic/GenericListView.swift b/Sora/Views/Generic/GenericListView.swift
index 7c568d6..004a278 100644
--- a/Sora/Views/Generic/GenericListView.swift
+++ b/Sora/Views/Generic/GenericListView.swift
@@ -121,12 +121,12 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View {
.pickerStyle(.menu)
Picker("Collection", selection: $selectedCollectionOption) {
- Text(CollectionPickerOption.all.name(settings)).tag(CollectionPickerOption.all)
+ Text(CollectionPickerOption.all.name(settings: settings))
+ .tag(CollectionPickerOption.all)
if items.contains(where: { $0.folder == nil }) {
- Text(CollectionPickerOption.uncategorized.name(settings)).tag(
- CollectionPickerOption.uncategorized
- )
+ Text(CollectionPickerOption.uncategorized.name(settings: settings))
+ .tag(CollectionPickerOption.uncategorized)
}
ForEach(settings.folders.filter { $0.topLevelName == nil }, id: \.id) { folder in
@@ -225,12 +225,12 @@ struct GenericListView<T: Identifiable & Hashable & GenericItem>: View {
Menu {
Picker("Collection", selection: $selectedCollectionOption) {
- Text(CollectionPickerOption.all.name(settings)).tag(CollectionPickerOption.all)
+ Text(CollectionPickerOption.all.name(settings: settings))
+ .tag(CollectionPickerOption.all)
if items.contains(where: { $0.folder == nil }) {
- Text(CollectionPickerOption.uncategorized.name(settings)).tag(
- CollectionPickerOption.uncategorized
- )
+ Text(CollectionPickerOption.uncategorized.name(settings: settings))
+ .tag(CollectionPickerOption.uncategorized)
}
ForEach(settings.folders.filter { $0.topLevelName == nil }, id: \.id) { folder in
diff --git a/Sora/Views/Post/Details/PostDetailsImageView.swift b/Sora/Views/Post/Details/PostDetailsImageView.swift
index a62171e..9ec2079 100644
--- a/Sora/Views/Post/Details/PostDetailsImageView.swift
+++ b/Sora/Views/Post/Details/PostDetailsImageView.swift
@@ -187,6 +187,8 @@ struct PostDetailsImageView<Placeholder: View>: View {
guard let url = self.url else { return }
let provider = manager.provider
+ let detailViewQuality = settings.detailViewQuality
+ let saveTagsToFile = settings.saveTagsToFile
URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data, let post else { return }
@@ -203,11 +205,11 @@ struct PostDetailsImageView<Placeholder: View>: View {
to:
picturesURL
.appendingPathComponent(
- "\(post.id)_\(settings.detailViewQuality.rawValue.lowercased()).\(url.pathExtension)"
+ "\(post.id)_\(detailViewQuality.rawValue.lowercased()).\(url.pathExtension)"
)
)
- if settings.saveTagsToFile {
+ if saveTagsToFile {
try post.tags.joined(separator: "\n").write(
to: picturesURL.appendingPathComponent(
"\(post.id).txt"
@@ -221,7 +223,7 @@ struct PostDetailsImageView<Placeholder: View>: View {
Task {
await sendLocalNotification(
title: "Sora",
- body: "Image \(settings.saveTagsToFile ? "and tags" : "") saved (\(post.id))"
+ body: "Image \(saveTagsToFile ? "and tags" : "") saved (\(post.id))"
)
}
#endif
diff --git a/project.yml b/project.yml
index 255527d..94bfdf3 100644
--- a/project.yml
+++ b/project.yml
@@ -72,7 +72,6 @@ targets:
SUPPORTED_PLATFORMS: iphoneos iphonesimulator macosx xros xrsimulator
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: YES
SWIFT_EMIT_LOC_STRINGS: YES
- SWIFT_VERSION: 5.0
TARGETED_DEVICE_FAMILY: 1,2,7
XROS_DEPLOYMENT_TARGET: 1.0
ENABLE_APP_SANDBOX: YES