summaryrefslogtreecommitdiff
path: root/Sora/Views
diff options
context:
space:
mode:
Diffstat (limited to 'Sora/Views')
-rw-r--r--Sora/Views/ContentView.swift10
-rw-r--r--Sora/Views/Post/Details/Carousel/PostDetailsCarouselItemView.swift50
-rw-r--r--Sora/Views/Post/Details/Carousel/PostDetailsCarouselView.swift15
-rw-r--r--Sora/Views/Post/Details/PostDetailsImageView.swift44
-rw-r--r--Sora/Views/Post/Details/PostDetailsTagsView.swift53
-rw-r--r--Sora/Views/Post/Details/PostDetailsView.swift130
-rw-r--r--Sora/Views/Post/Grid/PostGridView.swift2
7 files changed, 154 insertions, 150 deletions
diff --git a/Sora/Views/ContentView.swift b/Sora/Views/ContentView.swift
index 63f128a..85294ee 100644
--- a/Sora/Views/ContentView.swift
+++ b/Sora/Views/ContentView.swift
@@ -36,12 +36,8 @@ struct ContentView: View {
PostGridTabSwitcherView(selectedTab: $selectedTab, selectedPost: $selectedPost)
}
} detail: {
- if let post = selectedPost.post, let manager = selectedPost.manager {
- PostDetailsView(
- post: post,
- manager: manager,
- selectedPost: $selectedPost
- )
+ if selectedPost.post != nil && selectedPost.manager != nil {
+ PostDetailsView(selectedPost: $selectedPost)
} else {
Text("Select a Post")
.foregroundColor(.secondary)
@@ -60,7 +56,7 @@ struct ContentView: View {
)
) {
if let post = selectedPost.post, let manager = selectedPost.manager {
- PostDetailsView(post: post, manager: manager, selectedPost: $selectedPost)
+ PostDetailsView(selectedPost: $selectedPost)
}
}
}
diff --git a/Sora/Views/Post/Details/Carousel/PostDetailsCarouselItemView.swift b/Sora/Views/Post/Details/Carousel/PostDetailsCarouselItemView.swift
index 9d2d95e..fc39ca3 100644
--- a/Sora/Views/Post/Details/Carousel/PostDetailsCarouselItemView.swift
+++ b/Sora/Views/Post/Details/Carousel/PostDetailsCarouselItemView.swift
@@ -1,8 +1,6 @@
import SwiftUI
struct PostDetailsCarouselItemView: View {
- var post: BooruPost
- var manager: BooruManager
var index: Int
@Binding var loadingStage: BooruPostLoadingState
var imageURL: (BooruPost) -> URL?
@@ -15,33 +13,35 @@ struct PostDetailsCarouselItemView: View {
return Color.gray
#endif
}
+ @Binding var selectedPost: (post: BooruPost?, manager: BooruManager?)
var body: some View {
- ZStack {
- PostDetailsImageView(
- url: post.previewURL,
- loadingStage: $loadingStage,
- manager: manager
- ) {
- GeometryReader { geometry in
- ProgressView()
- .frame(width: geometry.size.width, height: geometry.size.height)
- .position(x: geometry.size.width / 2, y: geometry.size.height / 2)
- .padding()
+ if let post = selectedPost.post {
+ ZStack {
+ PostDetailsImageView(
+ url: post.previewURL,
+ loadingStage: $loadingStage,
+ selectedPost: $selectedPost
+ ) {
+ GeometryReader { geometry in
+ ProgressView()
+ .frame(width: geometry.size.width, height: geometry.size.height)
+ .position(x: geometry.size.width / 2, y: geometry.size.height / 2)
+ .padding()
+ }
}
+
+ PostDetailsImageView(
+ url: imageURL(post),
+ loadingStage: $loadingStage,
+ selectedPost: $selectedPost,
+ finalLoadingState: .loaded
+ )
+ .background(
+ loadingStage == .loaded ? systemBackgroundColor : Color.clear
+ )
}
-
- PostDetailsImageView(
- url: imageURL(post),
- loadingStage: $loadingStage,
- manager: manager,
- finalLoadingState: .loaded,
- post: post
- )
- .background(
- loadingStage == .loaded ? systemBackgroundColor : Color.clear
- )
+ .tag(index)
}
- .tag(index)
}
}
diff --git a/Sora/Views/Post/Details/Carousel/PostDetailsCarouselView.swift b/Sora/Views/Post/Details/Carousel/PostDetailsCarouselView.swift
index 88714c3..3ead408 100644
--- a/Sora/Views/Post/Details/Carousel/PostDetailsCarouselView.swift
+++ b/Sora/Views/Post/Details/Carousel/PostDetailsCarouselView.swift
@@ -1,24 +1,24 @@
import SwiftUI
struct PostDetailsCarouselView: View {
- @ObservedObject var manager: BooruManager
@EnvironmentObject var settings: SettingsManager
let posts: [BooruPost]
let focusedPost: BooruPost?
@Binding var loadingStage: BooruPostLoadingState
@State private var currentIndex: Int
private let cacheManager = ImageCacheManager.shared
+ @Binding var selectedPost: (post: BooruPost?, manager: BooruManager?)
init(
posts: [BooruPost],
loadingStage: Binding<BooruPostLoadingState>,
focusedPost: BooruPost? = nil,
- manager: ObservedObject<BooruManager>
+ selectedPost: Binding<(post: BooruPost?, manager: BooruManager?)>
) {
self.posts = posts
self.focusedPost = focusedPost
_loadingStage = loadingStage
- _manager = manager
+ _selectedPost = selectedPost
if let focused = focusedPost,
let index = posts.firstIndex(where: { $0.id == focused.id })
@@ -46,18 +46,19 @@ struct PostDetailsCarouselView: View {
TabView(selection: $currentIndex) {
ForEach(Array(posts.enumerated()), id: \.offset) { index, post in
PostDetailsCarouselItemView(
- post: post,
- manager: manager,
index: index,
loadingStage: $loadingStage,
- imageURL: imageURL
+ imageURL: imageURL,
+ selectedPost: $selectedPost
)
}
}
.onChange(of: currentIndex) {
+ guard let manager = selectedPost.manager else { return }
+
if currentIndex == posts.count - 1 { manager.loadNextPage() }
- manager.selectedPost = posts[currentIndex]
+ selectedPost.post = posts[currentIndex]
preloadNearbyImages()
}
diff --git a/Sora/Views/Post/Details/PostDetailsImageView.swift b/Sora/Views/Post/Details/PostDetailsImageView.swift
index 7d818f2..334dcc8 100644
--- a/Sora/Views/Post/Details/PostDetailsImageView.swift
+++ b/Sora/Views/Post/Details/PostDetailsImageView.swift
@@ -4,16 +4,15 @@ import UserNotifications
struct PostDetailsImageView<Placeholder: View>: View {
@EnvironmentObject var settings: SettingsManager
- @ObservedObject var manager: BooruManager
var url: URL?
@Binding var loadingState: BooruPostLoadingState
var finalLoadingState: BooruPostLoadingState
let placeholder: () -> Placeholder
- let post: BooruPost?
@State private var currentScale: CGFloat = 1.0
@State private var finalScale: CGFloat = 1.0
@State private var currentOffset: CGSize = .zero
@State private var finalOffset: CGSize = .zero
+ @Binding private var selectedPost: (post: BooruPost?, manager: BooruManager?)
#if os(iOS)
var keyWindow: UIWindow? {
@@ -74,12 +73,12 @@ struct PostDetailsImageView<Placeholder: View>: View {
#endif
Button {
- openURL(postURL(for: post?.id ?? ""))
+ openURL(postURL(for: selectedPost.post?.id ?? ""))
} label: {
Label("Open Post in Safari", systemImage: "safari")
}
- if let source = post?.source {
+ if let source = selectedPost.post?.source {
Button {
openURL(URL(string: source)!)
} label: {
@@ -119,20 +118,20 @@ struct PostDetailsImageView<Placeholder: View>: View {
}
func movePostCursor(by direction: Int) {
- guard let selectedPost = manager.selectedPost,
- let index = manager.postIndexMap[selectedPost.id],
+ guard let post = selectedPost.post,
+ let manager = selectedPost.manager,
+ let index = manager.postIndexMap[post.id],
(0..<manager.posts.count).contains(index + direction)
else { return }
- manager.selectedPost = manager.posts[index + direction]
+ selectedPost.post = manager.posts[index + direction]
}
init(
url: URL?,
loadingStage: Binding<BooruPostLoadingState>,
- manager: BooruManager,
+ selectedPost: Binding<(post: BooruPost?, manager: BooruManager?)>,
finalLoadingState: BooruPostLoadingState = .loadingFile,
- post: BooruPost? = nil,
@ViewBuilder placeholder: @escaping () -> Placeholder = {
GeometryReader { _ in
// ProgressView()
@@ -146,31 +145,36 @@ struct PostDetailsImageView<Placeholder: View>: View {
_loadingState = loadingStage
self.finalLoadingState = finalLoadingState
self.placeholder = placeholder
- self.post = post
- self.manager = manager
+ _selectedPost = selectedPost
}
private func postURL(for id: String) -> URL {
- switch manager.flavor {
- case .moebooru:
- return URL(string: "https://\(manager.domain)/post/show/\(id)")!
+ if let manager = selectedPost.manager {
+ switch manager.flavor {
+ case .moebooru:
+ return URL(string: "https://\(manager.domain)/post/show/\(id)")!
- case .gelbooru:
- return URL(string: "https://\(manager.domain)/index.php?page=post&s=view&id=\(id)")!
+ case .gelbooru:
+ return URL(string: "https://\(manager.domain)/index.php?page=post&s=view&id=\(id)")!
- case .danbooru:
- return URL(string: "https://\(manager.domain)/posts/\(id)")!
+ case .danbooru:
+ return URL(string: "https://\(manager.domain)/posts/\(id)")!
+ }
}
+
+ return URL(string: "#")!
}
#if os(macOS)
private func saveImageToPicturesFolder() {
- guard let url = self.url else { return }
+ guard let url = self.url, let manager = selectedPost.manager else {
+ return
+ }
let provider = manager.provider
URLSession.shared.dataTask(with: url) { data, _, _ in
- guard let data, let post else { return }
+ guard let data, let post = selectedPost.post else { return }
let picturesURL = FileManager.default.homeDirectoryForCurrentUser
.appendingPathComponent("Pictures/Sora/\(provider.rawValue)")
diff --git a/Sora/Views/Post/Details/PostDetailsTagsView.swift b/Sora/Views/Post/Details/PostDetailsTagsView.swift
index 107c9f3..cecb63d 100644
--- a/Sora/Views/Post/Details/PostDetailsTagsView.swift
+++ b/Sora/Views/Post/Details/PostDetailsTagsView.swift
@@ -1,50 +1,53 @@
import SwiftUI
struct PostDetailsTagsView: View {
- @ObservedObject var manager: BooruManager
@EnvironmentObject var settings: SettingsManager
@Binding var isPresented: Bool
var tags: [String]
@Binding var selectedPost: (post: BooruPost?, manager: BooruManager?)
var body: some View {
- List {
- ForEach(tags, id: \.self) { tag in
- Button(action: {
- manager.searchText = tag
- selectedPost = (nil, nil)
-
- search()
- }) {
- Text(tag)
- }
- .contextMenu {
+ if let manager = selectedPost.manager {
+ List {
+ ForEach(tags, id: \.self) { tag in
Button(action: {
- manager.searchText += " \(tag)"
+ manager.searchText = tag
selectedPost = (nil, nil)
search()
}) {
- Label("Add to Search", systemImage: "plus")
+ Text(tag)
}
+ .contextMenu {
+ Button(action: {
+ manager.searchText += " \(tag)"
+ selectedPost = (nil, nil)
- Button(action: {
- settings.addBookmark(provider: settings.preferredBooru, tags: [tag])
- }) {
- Label("Bookmark Tag", systemImage: "bookmark")
+ search()
+ }) {
+ Label("Add to Search", systemImage: "plus")
+ }
+
+ Button(action: {
+ settings.addBookmark(provider: settings.preferredBooru, tags: [tag])
+ }) {
+ Label("Bookmark Tag", systemImage: "bookmark")
+ }
}
}
- }
- #if os(macOS)
+#if os(macOS)
.buttonStyle(.plain)
- #endif
+#endif
+ }
}
}
private func search() {
- manager.selectedPost = nil
-
- manager.performSearch(settings: settings)
- isPresented.toggle()
+ if let manager = selectedPost.manager {
+ manager.selectedPost = nil
+
+ manager.performSearch(settings: settings)
+ isPresented.toggle()
+ }
}
}
diff --git a/Sora/Views/Post/Details/PostDetailsView.swift b/Sora/Views/Post/Details/PostDetailsView.swift
index ba81b65..a7693a5 100644
--- a/Sora/Views/Post/Details/PostDetailsView.swift
+++ b/Sora/Views/Post/Details/PostDetailsView.swift
@@ -2,116 +2,116 @@ import SwiftUI
struct PostDetailsView: View {
@EnvironmentObject var settings: SettingsManager
- let post: BooruPost
- @ObservedObject var manager: BooruManager
@State private var loadingStage: BooruPostLoadingState = .loadingPreview
private var imageURL: URL? {
+ guard let post = selectedPost.post else { return nil }
+
switch settings.detailViewQuality {
case .preview:
- post.previewURL
+ return post.previewURL
case .sample:
- post.sampleURL
+ return post.sampleURL
case .original:
- post.fileURL
+ return post.fileURL
}
}
@State private var isTagsSheetPresented = false
@Binding var selectedPost: (post: BooruPost?, manager: BooruManager?)
var filteredPosts: [BooruPost] {
- manager.posts
+ selectedPost.manager!.posts
.filter { settings.displayRatings.contains($0.rating) }
}
var body: some View {
- VStack(spacing: 0) {
- #if os(macOS)
+ if let post = selectedPost.post {
+ VStack(spacing: 0) {
+#if os(macOS)
PostDetailsImageView(
url: imageURL,
loadingStage: $loadingStage,
- manager: manager,
- finalLoadingState: .loaded,
- post: post
+ selectedPost: $selectedPost,
+ finalLoadingState: .loaded
) {
PostDetailsImageView(
url: post.previewURL,
loadingStage: $loadingStage,
- manager: manager
+ selectedPost: $selectedPost
)
.id(post.previewURL)
}
.id(imageURL)
- #else
+#else
PostDetailsCarouselView(
posts: filteredPosts,
loadingStage: $loadingStage,
focusedPost: post,
- manager: _manager
+ selectedPost: $selectedPost
)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
- #endif
+#endif
- if settings.displayDetailsInformationBar {
- VStack(spacing: 5) {
- HStack {
- Text(post.createdAt.formatted())
- .frame(maxWidth: .infinity, alignment: .leading)
+ if settings.displayDetailsInformationBar {
+ VStack(spacing: 5) {
+ HStack {
+ Text(post.createdAt.formatted())
+ .frame(maxWidth: .infinity, alignment: .leading)
- Group {
- switch loadingStage {
- case .loadingPreview:
- Text("Loading Preview…")
+ Group {
+ switch loadingStage {
+ case .loadingPreview:
+ Text("Loading Preview…")
- case .loadingFile:
- Text("Loading \(settings.detailViewQuality.rawValue)…")
+ case .loadingFile:
+ Text("Loading \(settings.detailViewQuality.rawValue)…")
- case .loaded:
- EmptyView()
+ case .loaded:
+ EmptyView()
+ }
}
+ .padding(.trailing, 5)
}
- .padding(.trailing, 5)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .foregroundStyle(.secondary)
}
- .frame(maxWidth: .infinity, alignment: .leading)
- .foregroundStyle(.secondary)
- }
- .padding(.horizontal, 10)
- .padding(.vertical, 10 / 1.33)
- .textSelection(.enabled)
- .font(.footnote)
- #if os(iOS)
+ .padding(.horizontal, 10)
+ .padding(.vertical, 10 / 1.33)
+ .textSelection(.enabled)
+ .font(.footnote)
+#if os(iOS)
.background(.ultraThinMaterial)
- #else
+#else
.background(.opacity(0.1))
- #endif
- .zIndex(1)
+#endif
+ .zIndex(1)
+ }
}
- }
- .navigationTitle("Details")
- #if os(iOS)
+ .navigationTitle("Details")
+#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(.ultraThinMaterial, for: .navigationBar)
- #endif
- .toolbar {
- #if !os(macOS)
- if manager.isLoading || loadingStage != .loaded {
+#endif
+ .toolbar {
+#if !os(macOS)
+ if selectedPost.manager?.isLoading != false || loadingStage != .loaded {
ToolbarItem {
ProgressView()
}
}
- #endif
+#endif
- ToolbarItem {
- Button(action: {
- isTagsSheetPresented.toggle()
- }) {
- Label("Tags", systemImage: "tag")
+ ToolbarItem {
+ Button(action: {
+ isTagsSheetPresented.toggle()
+ }) {
+ Label("Tags", systemImage: "tag")
+ }
}
- }
- #if os(macOS)
+#if os(macOS)
if settings.enableShareShortcut {
ToolbarItem {
ShareLink(item: imageURL!) {
@@ -119,16 +119,16 @@ struct PostDetailsView: View {
}
}
}
- #endif
- }
- .sheet(isPresented: $isTagsSheetPresented) {
- PostDetailsTagsView(
- manager: manager,
- isPresented: $isTagsSheetPresented,
- tags: post.tags,
- selectedPost: $selectedPost
- )
- .frame(minHeight: 250)
+#endif
+ }
+ .sheet(isPresented: $isTagsSheetPresented) {
+ PostDetailsTagsView(
+ isPresented: $isTagsSheetPresented,
+ tags: post.tags,
+ selectedPost: $selectedPost
+ )
+ .frame(minHeight: 250)
+ }
}
}
}
diff --git a/Sora/Views/Post/Grid/PostGridView.swift b/Sora/Views/Post/Grid/PostGridView.swift
index 2b9d29b..0b1d532 100644
--- a/Sora/Views/Post/Grid/PostGridView.swift
+++ b/Sora/Views/Post/Grid/PostGridView.swift
@@ -45,7 +45,7 @@ struct PostGridView: View {
manager.performSearch(settings: settings)
}
.navigationDestination(for: BooruPost.self) { post in
- PostDetailsView(post: post, manager: manager, selectedPost: $selectedPost)
+ PostDetailsView(selectedPost: $selectedPost)
}
.onChange(of: manager.searchText) { _, _ in
if manager.searchText.isEmpty, !isSearching {