diff options
| author | Fuwn <[email protected]> | 2025-02-18 23:39:51 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-02-19 00:00:29 -0800 |
| commit | 320ce31337ed60cae24a0374fa2d6d79237a6bfe (patch) | |
| tree | ad1e93799efeb8e7a16521e3ab958c911f73f617 /Sora/Views/Post | |
| parent | feat: Initial commit (diff) | |
| download | sora-testing-320ce31337ed60cae24a0374fa2d6d79237a6bfe.tar.xz sora-testing-320ce31337ed60cae24a0374fa2d6d79237a6bfe.zip | |
feat: Development commit
Diffstat (limited to 'Sora/Views/Post')
| -rw-r--r-- | Sora/Views/Post/PostDetailView.swift | 75 | ||||
| -rw-r--r-- | Sora/Views/Post/PostDetailsView.swift | 83 | ||||
| -rw-r--r-- | Sora/Views/Post/PostFileType.swift | 6 | ||||
| -rw-r--r-- | Sora/Views/Post/PostGridView.swift | 77 | ||||
| -rw-r--r-- | Sora/Views/Post/PostThumbnailMode.swift | 5 | ||||
| -rw-r--r-- | Sora/Views/Post/PostView.swift | 20 |
6 files changed, 180 insertions, 86 deletions
diff --git a/Sora/Views/Post/PostDetailView.swift b/Sora/Views/Post/PostDetailView.swift deleted file mode 100644 index 799339c..0000000 --- a/Sora/Views/Post/PostDetailView.swift +++ /dev/null @@ -1,75 +0,0 @@ -import SwiftUI - -struct PostDetailView: View { - let post: MoebooruPost - @State var loadingStage: PostLoadingState = .loadingPreview - - var body: some View { - VStack { - Link(destination: URL(string: "https://yande.re/post/show/\(post.id)")!) { - AsyncImage(url: post.sampleURL) { image in - image - .resizable() - .scaledToFit() - .onAppear { - self.loadingStage = .loaded - } - } placeholder: { - AsyncImage(url: post.previewURL) { image in - image - .resizable() - .scaledToFit() - .onAppear { - self.loadingStage = .loadingFile - } - } placeholder: { - ProgressView() - .progressViewStyle(LinearProgressViewStyle()) - .padding() - .onAppear { - self.loadingStage = .loadingPreview - } - } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) - .id(post.fileURL) - } - .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) - .id(post.fileURL) - } - .buttonStyle(PlainButtonStyle()) - - Spacer() - - VStack(spacing: 5) { - HStack { - Text(post.tags.joined(separator: ", ")) - } - .frame(maxWidth: .infinity, alignment: .leading) - - HStack { - Text(post.createdAt.formatted()) - .frame(maxWidth: .infinity, alignment: .leading) - - Group { - switch loadingStage { - case .loadingPreview: - Text("Loading preview …") - case .loadingFile: - Text("Loading file …") - case .loaded: - EmptyView() - } - } - .padding(.trailing, 5) - } - .frame(maxWidth: .infinity, alignment: .leading) - .foregroundStyle(.secondary) - } - .padding(.horizontal, 10) - .padding(.vertical, 10 / 1.33) - .textSelection(.enabled) - .font(.footnote) - .background(.opacity(0.1)) - } - } -} diff --git a/Sora/Views/Post/PostDetailsView.swift b/Sora/Views/Post/PostDetailsView.swift new file mode 100644 index 0000000..8f8f1de --- /dev/null +++ b/Sora/Views/Post/PostDetailsView.swift @@ -0,0 +1,83 @@ +import SwiftUI + +struct PostDetailsView: View { + @EnvironmentObject var settings: Settings + let post: MoebooruPost + @State var loadingStage: PostLoadingState = .loadingPreview + private var imageURL: URL? { + switch settings.detailViewType { + case .preview: + return post.previewURL + case .sample: + return post.sampleURL + case .original: + return post.fileURL + case .compressed: + return post.jpegURL + } + } + + var body: some View { + VStack(spacing: 0) { + AsyncImageWithPreview( + url: imageURL, + loadingStage: $loadingStage, + finalLoadingState: .loaded, + postURL: URL(string: "https://yande.re/post/show/\(post.id)")! + ) { + AsyncImageWithPreview( + url: post.previewURL, + loadingStage: $loadingStage + ) + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .id(post.previewURL) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) + .id(imageURL) + .padding(0) + .zIndex(0) + + VStack(spacing: 5) { + HStack { + Text(post.tags.joined(separator: ", ")) + } + .frame(maxWidth: .infinity, alignment: .leading) + + HStack { + Text(post.createdAt.formatted()) + .frame(maxWidth: .infinity, alignment: .leading) + + Group { + switch loadingStage { + case .loadingPreview: + Text("Loading preview …") + case .loadingFile: + Text("Loading \(settings.detailViewType.rawValue) …") + case .loaded: + EmptyView() + } + } + .padding(.trailing, 5) + } + .frame(maxWidth: .infinity, alignment: .leading) + .foregroundStyle(.secondary) + } + .padding(.horizontal, 10) + .padding(.vertical, 10 / 1.33) + .textSelection(.enabled) + .font(.footnote) + #if os(iOS) + .background(.ultraThinMaterial) + #else + .background(.opacity(0.1)) + #endif + .zIndex(1) + } + .navigationTitle("Details") + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + .toolbarBackground(.visible, for: .navigationBar) + .toolbarBackground(.ultraThinMaterial, for: .navigationBar) + #endif + } +} diff --git a/Sora/Views/Post/PostFileType.swift b/Sora/Views/Post/PostFileType.swift new file mode 100644 index 0000000..a7b3ca6 --- /dev/null +++ b/Sora/Views/Post/PostFileType.swift @@ -0,0 +1,6 @@ +enum PostFileType: String, CaseIterable { + case original + case sample + case compressed + case preview +} diff --git a/Sora/Views/Post/PostGridView.swift b/Sora/Views/Post/PostGridView.swift new file mode 100644 index 0000000..4c43eeb --- /dev/null +++ b/Sora/Views/Post/PostGridView.swift @@ -0,0 +1,77 @@ +import SwiftUI +import WaterfallGrid + +struct PostGridView: View { + @EnvironmentObject var settings: Settings + @ObservedObject var manager: MoebooruManager + + var body: some View { + ScrollViewReader { _ in + ScrollView { + if manager.posts.isEmpty { + ProgressView() + .frame( + width: settings.softLimitAsCGFloat(), + height: settings.softLimitAsCGFloat() + ) + } + + WaterfallGrid(manager.posts, id: \.id) { post in + Group { + #if os(macOS) + Button { + manager.selectedPost = post + } label: { + PostView(post: post, manager: manager) + } + .buttonStyle(PlainButtonStyle()) + #else + NavigationLink(value: post) { + PostView(post: post, manager: manager) + } + #endif + } + } + .gridStyle(columns: settings.columns, spacing: 0) + } + .searchable(text: $manager.searchText, prompt: "Tags") + .searchSuggestions { + if settings.searchSuggestions { + SearchSuggestionsView( + tags: manager.allTags, + searchText: $manager.searchText + ) + } + } + .onSubmit(of: .search, manager.performSearch) + .task { + if manager.posts.isEmpty { + await manager.fetchPosts(page: manager.currentPage) + } + } + .navigationDestination(for: MoebooruPost.self) { post in + PostDetailsView(post: post) + } + #if os(macOS) + .toolbar { + ToolbarItem { + Button(action: { + Task { + await manager.fetchPosts(page: 1, tags: manager.tags, replace: true) + } + }) { + Label("Refresh", systemImage: "arrow.clockwise") + } + } + } + #endif + .navigationTitle("Posts") + .refreshable { + await manager.fetchPosts(page: 1, tags: manager.tags, replace: true) + } + #if os(iOS) + .navigationBarTitleDisplayMode(.inline) + #endif + } + } +} diff --git a/Sora/Views/Post/PostThumbnailMode.swift b/Sora/Views/Post/PostThumbnailMode.swift deleted file mode 100644 index 1e6c3b3..0000000 --- a/Sora/Views/Post/PostThumbnailMode.swift +++ /dev/null @@ -1,5 +0,0 @@ -enum PostThumbnailMode { - case preview - case sample - case file -} diff --git a/Sora/Views/Post/PostView.swift b/Sora/Views/Post/PostView.swift index 97e311c..d070aac 100644 --- a/Sora/Views/Post/PostView.swift +++ b/Sora/Views/Post/PostView.swift @@ -1,17 +1,19 @@ import SwiftUI struct PostView: View { + @EnvironmentObject var settings: Settings let post: MoebooruPost - var softLimit: CGFloat - var thumbnailMode: PostThumbnailMode = .preview + @ObservedObject var manager: MoebooruManager private var thumbnailURL: URL? { - switch thumbnailMode { + switch settings.thumbnailType { case .preview: return post.previewURL case .sample: return post.sampleURL - case .file: + case .original: return post.fileURL + case .compressed: + return post.jpegURL } } @@ -20,11 +22,17 @@ struct PostView: View { AsyncImage(url: thumbnailURL) { image in image .resizable() - .scaledToFit() + .aspectRatio(contentMode: .fit) + .onScrollVisibilityChange { visible in + if post == manager.posts.last && !manager.endOfData && visible { + Task { + manager.loadNextPage() + } + } + } } placeholder: { ProgressView() } - .frame(width: softLimit, height: softLimit) } } } |