summaryrefslogtreecommitdiff
path: root/Sora/Views/Post/Grid
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-02-22 07:07:57 -0800
committerFuwn <[email protected]>2025-02-22 07:07:57 -0800
commitcafece91bae45194d64f4932bb04be018b82d21b (patch)
tree02d727a13fe530550e3b29b28b7ee9980262eef2 /Sora/Views/Post/Grid
parentfeat: Development commit (diff)
downloadsora-testing-cafece91bae45194d64f4932bb04be018b82d21b.tar.xz
sora-testing-cafece91bae45194d64f4932bb04be018b82d21b.zip
feat: Development commit
Diffstat (limited to 'Sora/Views/Post/Grid')
-rw-r--r--Sora/Views/Post/Grid/PostGridBookmarkButtonView.swift37
-rw-r--r--Sora/Views/Post/Grid/PostGridThumbnailView.swift47
-rw-r--r--Sora/Views/Post/Grid/PostGridView.swift101
3 files changed, 185 insertions, 0 deletions
diff --git a/Sora/Views/Post/Grid/PostGridBookmarkButtonView.swift b/Sora/Views/Post/Grid/PostGridBookmarkButtonView.swift
new file mode 100644
index 0000000..9f85a20
--- /dev/null
+++ b/Sora/Views/Post/Grid/PostGridBookmarkButtonView.swift
@@ -0,0 +1,37 @@
+import SwiftUI
+
+struct PostGridBookmarkButtonView: View {
+ @EnvironmentObject private var manager: BooruManager
+ @EnvironmentObject private var settings: Settings
+
+ var contained: Bool {
+ let lowercaseTags = manager.tags.map { $0.lowercased() }
+
+ return settings.bookmarks
+ .contains { bookmark in
+ bookmark.tags == lowercaseTags
+ && bookmark.provider == manager.provider ?? settings.preferredBooru
+ }
+ }
+
+ var body: some View {
+ Button(
+ action: {
+ contained
+ ? settings
+ .removeBookmark(withTags: manager.tags)
+ : settings
+ .addBookmark(
+ provider: manager.provider ?? settings.preferredBooru,
+ tags: manager.tags
+ )
+ }
+ ) {
+ Label(
+ "Bookmark",
+ systemImage:
+ contained ? "bookmark.fill" : "bookmark"
+ )
+ }
+ }
+}
diff --git a/Sora/Views/Post/Grid/PostGridThumbnailView.swift b/Sora/Views/Post/Grid/PostGridThumbnailView.swift
new file mode 100644
index 0000000..e90b39b
--- /dev/null
+++ b/Sora/Views/Post/Grid/PostGridThumbnailView.swift
@@ -0,0 +1,47 @@
+import SwiftUI
+
+struct PostGridThumbnailView: View {
+ @EnvironmentObject var settings: Settings
+ @EnvironmentObject var manager: BooruManager
+ let post: BooruPost
+ let posts: [BooruPost]
+ private var thumbnailURL: URL? {
+ switch settings.thumbnailType {
+ case .preview:
+ post.previewURL
+
+ case .sample:
+ post.sampleURL
+
+ case .original:
+ post.fileURL
+ }
+ }
+
+ var body: some View {
+ VStack {
+ AsyncImage(url: thumbnailURL) { image in
+ image
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .onScrollVisibilityChange { visible in
+ if post == posts.last, !manager.endOfData, visible {
+ Task {
+ manager.loadNextPage()
+ }
+ }
+ }
+ .blur(
+ radius: settings.blurNSFWThumbnails
+ ? (post.rating != "s" && post.rating != "q") ? 10 : 0 : 0
+ )
+ .clipped()
+ .animation(.default, value: settings.blurNSFWThumbnails)
+ .clipShape(RoundedRectangle(cornerRadius: 8))
+ } placeholder: {
+ ProgressView()
+ .padding()
+ }
+ }
+ }
+}
diff --git a/Sora/Views/Post/Grid/PostGridView.swift b/Sora/Views/Post/Grid/PostGridView.swift
new file mode 100644
index 0000000..9738a15
--- /dev/null
+++ b/Sora/Views/Post/Grid/PostGridView.swift
@@ -0,0 +1,101 @@
+import SwiftUI
+import WaterfallGrid
+
+struct PostGridView: View {
+ @EnvironmentObject var settings: Settings
+ @EnvironmentObject var manager: BooruManager
+
+ @Environment(\.isSearching)
+ private var isSearching
+
+ var filteredPosts: [BooruPost] {
+ (settings.showNSFWPosts
+ ? manager.posts : manager.posts.filter { $0.rating == "s" || $0.rating == "q" })
+ .sorted { $0.id > $1.id }
+ }
+
+ var body: some View {
+ ScrollViewReader { _ in
+ ScrollView {
+ if filteredPosts.isEmpty {
+ ProgressView()
+ .padding()
+ }
+
+ WaterfallGrid(filteredPosts, id: \.id) { post in
+ Group {
+ #if os(macOS)
+ Button {
+ manager.selectedPost = post
+ } label: {
+ PostGridThumbnailView(
+ post: post,
+ posts: filteredPosts
+ )
+ }
+ .buttonStyle(PlainButtonStyle())
+ #else
+ NavigationLink(value: post) {
+ PostGridThumbnailView(
+ post: post,
+ posts: filteredPosts
+ )
+ }
+ #endif
+ }
+ }
+ .gridStyle(columns: settings.columns)
+ .padding(8)
+ }
+ .searchable(text: $manager.searchText, prompt: "Tags")
+ .searchSuggestions {
+ if settings.searchSuggestions {
+ SearchSuggestionsView(
+ tags: manager.allTags,
+ searchText: $manager.searchText
+ )
+ }
+ }
+ .onSubmit(of: .search, manager.performSearch)
+ .navigationDestination(for: BooruPost.self) { post in
+ PostDetailsView(post: post)
+ }
+ .onChange(of: manager.searchText) { _, _ in
+ if manager.searchText.isEmpty, !isSearching {
+ Task {
+ manager.performSearch()
+ }
+ }
+ }
+ .toolbar {
+ #if os(macOS)
+ ToolbarItem {
+ Button(action: {
+ Task {
+ await manager.fetchPosts(page: 1, tags: manager.tags, replace: true)
+ }
+ }) {
+ Label("Refresh", systemImage: "arrow.clockwise")
+ }
+ }
+ #endif
+
+ if !manager.tags.isEmpty {
+ #if os(macOS)
+ ToolbarItem {
+ PostGridBookmarkButtonView()
+ }
+ #else
+ ToolbarItem(placement: .bottomBar) {
+ PostGridBookmarkButtonView()
+ }
+ #endif
+ }
+ }
+ .navigationTitle("Posts")
+ .refreshable {
+ await manager.fetchPosts(page: 1, tags: manager.tags, replace: true)
+ }
+ }
+ }
+}