diff --git a/FurAffinity/Helper Views/ProgressiveLoadItem.swift b/FurAffinity/Helper Views/ProgressiveLoadItem.swift index ea15d69..c865e58 100644 --- a/FurAffinity/Helper Views/ProgressiveLoadItem.swift +++ b/FurAffinity/Helper Views/ProgressiveLoadItem.swift @@ -38,7 +38,9 @@ struct ProgressiveLoadItem: View { .onChange(of: currentData) { _, newData in if needsMoreData && newData.canLoadMore { Task { + guard needsMoreData else { return } try await Task.sleep(for: crawlingDelay) + guard needsMoreData else { return } loadMoreData(newData) } } diff --git a/FurAffinity/User/RemoteUserGalleryLikeView.swift b/FurAffinity/User/RemoteUserGalleryLikeView.swift index bb08b72..a9fad3b 100644 --- a/FurAffinity/User/RemoteUserGalleryLikeView.swift +++ b/FurAffinity/User/RemoteUserGalleryLikeView.swift @@ -16,12 +16,22 @@ struct RemoteUserGalleryLikeView: View { var body: some View { RemoteView(url: url, contentsLoader: { await model.session?.galleryLike(for: url) - }) { gallery, _ in + }, contentsViewBuilder: { gallery, updateHandler in UserGalleryLikeView( galleryType: galleryType, - gallery: gallery - ) - } + gallery: gallery) { latestGallery in + guard let nextUrl = latestGallery.nextPageUrl else { + logger.error("Next page requested but there is none!") + return + } + + Task { + let nextGallery = await model.session?.galleryLike(for: nextUrl) + let updated = nextGallery.map { latestGallery.appending($0) } + updateHandler.update(with: updated) + } + } + }) } } diff --git a/FurAffinity/User/UserGalleryLikeView.swift b/FurAffinity/User/UserGalleryLikeView.swift index e0c6722..1265a97 100644 --- a/FurAffinity/User/UserGalleryLikeView.swift +++ b/FurAffinity/User/UserGalleryLikeView.swift @@ -18,9 +18,16 @@ enum GalleryType { } } +extension FAUserGalleryLike: ProgressiveData { + var canLoadMore: Bool { + nextPageUrl != nil + } +} + struct UserGalleryLikeView: View { var galleryType: GalleryType var gallery: FAUserGalleryLike + var loadMore: (_ galleryLike: FAUserGalleryLike) -> Void var body: some View { Group { @@ -37,23 +44,30 @@ struct UserGalleryLikeView: View { } } else { GeometryReader { geometry in - List(gallery.previews) { preview in - NavigationLink( - value: FAURL.submission(url: preview.url, previewData: preview) - ) { - if galleryType.shouldDisplayAuthor { - SubmissionFeedItemView(submission: preview) - } else { - SubmissionFeedItemView(submission: preview) + List { + ForEach(gallery.previews) { preview in + NavigationLink( + value: FAURL.submission(url: preview.url, previewData: preview) + ) { + if galleryType.shouldDisplayAuthor { + SubmissionFeedItemView(submission: preview) + } else { + SubmissionFeedItemView(submission: preview) + } } + .id(preview.sid) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) } - .id(preview.sid) - .listRowSeparator(.hidden) - .listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)) + + ProgressiveLoadItem( + label: "Loading more submissions…", + currentData: gallery, + loadMoreData: loadMore + ) } .listStyle(.plain) - .onAppear { - // Note: onAppear won't be enough once infinite scroll is implemented + .onChange(of: gallery.previews, initial: true) { let thumbnailsWidth = geometry.size.width - 28.333 let previews = gallery.previews prefetchThumbnails(for: previews, availableWidth: thumbnailsWidth) @@ -72,7 +86,8 @@ struct UserGalleryLikeView: View { NavigationStack { UserGalleryLikeView( galleryType: .favorites, - gallery: .init(displayAuthor: "Some User", previews: OfflineFASession.default.submissionPreviews) + gallery: .init(displayAuthor: "Some User", previews: OfflineFASession.default.submissionPreviews, nextPageUrl: nil), + loadMore: { _ in } ) } .environmentObject(Model.demo) @@ -82,7 +97,8 @@ struct UserGalleryLikeView: View { NavigationStack { UserGalleryLikeView( galleryType: .favorites, - gallery: .init(displayAuthor: "Some User", previews: []) + gallery: .init(displayAuthor: "Some User", previews: [], nextPageUrl: nil), + loadMore: { _ in } ) } .environmentObject(Model.empty)