Skip to content

Commit 6aabcd4

Browse files
committed
Add load more
1 parent aaace27 commit 6aabcd4

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

UI/Sources/UI/Resources/Localizable.xcstrings

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
},
4949
"Latest updates" : {
5050

51+
},
52+
"Load more" : {
53+
5154
},
5255
"Logged in as %@" : {
5356

UI/Sources/UI/Updates/ViewController/UpdatesViewController+DataSource.swift

+27
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,33 @@ extension UpdatesViewController {
7272
)
7373
}
7474
}
75+
76+
let loadMoreButtonRegistration = UICollectionView.SupplementaryRegistration<UICollectionViewCell>(
77+
elementKind: SupplementaryElementKind.loadMore
78+
) { [unowned viewModel] cell, _, _ in
79+
cell.contentConfiguration = UIHostingConfiguration {
80+
Button(String(localized: "Load more", bundle: .module)) {
81+
Task {
82+
try await viewModel.fetchFollowedFeed()
83+
}
84+
}
85+
.buttonStyle(.borderedProminent)
86+
.buttonBorderShape(.capsule)
87+
.frame(maxWidth: .infinity)
88+
}
89+
.margins(.vertical, 16)
90+
}
91+
92+
dataSource.supplementaryViewProvider = { collectionView, elementKind, indexPath in
93+
if elementKind == SupplementaryElementKind.loadMore {
94+
return collectionView.dequeueConfiguredReusableSupplementary(
95+
using: loadMoreButtonRegistration,
96+
for: indexPath
97+
)
98+
}
99+
100+
return nil
101+
}
75102
}
76103

77104
func updateDataSource(animated: Bool = true) {

UI/Sources/UI/Updates/ViewController/UpdatesViewController+Layout.swift

+23-2
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,37 @@
88
import UIKit
99

1010
extension UpdatesViewController {
11+
enum SupplementaryElementKind {
12+
static let loadMore = "loadMore"
13+
}
14+
1115
func makeCollectionViewLayout() -> UICollectionViewLayout {
12-
let sectionProvider: UICollectionViewCompositionalLayoutSectionProvider = { _, layoutEnvironment in
16+
let sectionProvider: UICollectionViewCompositionalLayoutSectionProvider = {
17+
[unowned self] sectionIndex, layoutEnvironment in
18+
1319
var listConfig = UICollectionLayoutListConfiguration(appearance: .plain)
1420
listConfig.headerMode = .firstItemInSection
1521
listConfig.separatorConfiguration.topSeparatorVisibility = .visible
1622
listConfig.separatorConfiguration.bottomSeparatorVisibility = .hidden
1723

18-
return NSCollectionLayoutSection.list(using: listConfig, layoutEnvironment: layoutEnvironment)
24+
let section = NSCollectionLayoutSection.list(using: listConfig, layoutEnvironment: layoutEnvironment)
25+
let sectionsCount = dataSource.numberOfSections(in: collectionView)
26+
if sectionIndex == sectionsCount - 1 {
27+
section.boundarySupplementaryItems.append(makeLoadMoreItem())
28+
}
29+
30+
return section
1931
}
2032

2133
return UICollectionViewCompositionalLayout(sectionProvider: sectionProvider)
2234
}
35+
36+
private func makeLoadMoreItem() -> NSCollectionLayoutBoundarySupplementaryItem {
37+
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(60))
38+
return NSCollectionLayoutBoundarySupplementaryItem(
39+
layoutSize: itemSize,
40+
elementKind: SupplementaryElementKind.loadMore,
41+
alignment: .bottom
42+
)
43+
}
2344
}

ViewModels/Sources/ViewModels/Updates/UpdatesViewModel.swift

+16-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public final class UpdatesViewModel: ObservableObject {
2525

2626
public func loadFollowedFeedFromStorage() throws {
2727
let context = modelContainer.mainContext
28-
let chapterEntities = try context.fetch(ChapterEntity.followedFeed(limit: 32))
28+
let chapterEntities = try context.fetch(ChapterEntity.followedFeed(limit: 32, offset: offset))
2929
let chaptersGroupedByMangaID: OrderedDictionary<UUID, [ChapterEntity]> =
3030
chapterEntities.reduce(into: [:]) { result, chapterEntity in
3131
guard let manga = chapterEntity.manga else {
@@ -48,8 +48,21 @@ public final class UpdatesViewModel: ObservableObject {
4848
return Section(mangaInfo: manga, chapters: IdentifiedArray(uniqueElements: chapters))
4949
}
5050

51-
offset = chapterEntities.count
52-
self.sections = IdentifiedArray(uniqueElements: sections)
51+
offset += chapterEntities.count
52+
53+
for section in sections {
54+
if let existingSection = self.sections[id: section.id] {
55+
// If section already exists, append its chapters
56+
// and use new manga info (since it's more up-to-date)
57+
let newSection = Section(
58+
mangaInfo: section.mangaInfo,
59+
chapters: IdentifiedArray(existingSection.chapters + section.chapters) { $1 }
60+
)
61+
self.sections[id: section.id] = newSection
62+
} else {
63+
self.sections.append(section)
64+
}
65+
}
5366
}
5467

5568
public func fetchFollowedFeed(resetsOffset: Bool = false) async throws {

0 commit comments

Comments
 (0)