summaryrefslogtreecommitdiff
path: root/Sora/Views/Post
diff options
context:
space:
mode:
authorFuwn <[email protected]>2025-02-18 23:39:51 -0800
committerFuwn <[email protected]>2025-02-19 00:00:29 -0800
commit320ce31337ed60cae24a0374fa2d6d79237a6bfe (patch)
treead1e93799efeb8e7a16521e3ab958c911f73f617 /Sora/Views/Post
parentfeat: Initial commit (diff)
downloadsora-testing-320ce31337ed60cae24a0374fa2d6d79237a6bfe.tar.xz
sora-testing-320ce31337ed60cae24a0374fa2d6d79237a6bfe.zip
feat: Development commit
Diffstat (limited to 'Sora/Views/Post')
-rw-r--r--Sora/Views/Post/PostDetailView.swift75
-rw-r--r--Sora/Views/Post/PostDetailsView.swift83
-rw-r--r--Sora/Views/Post/PostFileType.swift6
-rw-r--r--Sora/Views/Post/PostGridView.swift77
-rw-r--r--Sora/Views/Post/PostThumbnailMode.swift5
-rw-r--r--Sora/Views/Post/PostView.swift20
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)
}
}
}