diff options
| author | Fuwn <[email protected]> | 2025-02-22 07:07:57 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-02-22 07:07:57 -0800 |
| commit | cafece91bae45194d64f4932bb04be018b82d21b (patch) | |
| tree | 02d727a13fe530550e3b29b28b7ee9980262eef2 /Sora/Views/Post/Grid | |
| parent | feat: Development commit (diff) | |
| download | sora-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.swift | 37 | ||||
| -rw-r--r-- | Sora/Views/Post/Grid/PostGridThumbnailView.swift | 47 | ||||
| -rw-r--r-- | Sora/Views/Post/Grid/PostGridView.swift | 101 |
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) + } + } + } +} |