main
swift 95 lines 2.88 KB
Raw
1 //
2 // ShelfSection.swift
3 // JomloCollectionView Example
4 //
5 // Created by Seto Elkahfi on 2026-01-27.
6 // Copyright © 2026 Seto Elkahfi. All rights reserved.
7 //
8
9 import JomloCollectionView
10 import UIKit
11
12 @MainActor
13 final class ShelfSection: JomloSection {
14
15 let identifier: JomloSectionID
16 var onReloadNeeded: (@MainActor @Sendable () -> Void)?
17
18 private let title: String
19 private let posterItems: [PosterItem]
20 private let onItemSelected: (@MainActor (PosterItem) -> Void)?
21 weak var presenter: UIViewController?
22
23 init(
24 id: String,
25 title: String,
26 items: [PosterItem],
27 presenter: UIViewController? = nil,
28 onItemSelected: (@MainActor (PosterItem) -> Void)? = nil
29 ) {
30 self.identifier = JomloSectionID(id)
31 self.title = title
32 self.posterItems = items
33 self.presenter = presenter
34 self.onItemSelected = onItemSelected
35 }
36
37 func items() -> [any JomloItem] {
38 posterItems
39 }
40
41 func layoutSection(
42 environment: NSCollectionLayoutEnvironment,
43 sectionIndex: Int
44 ) -> NSCollectionLayoutSection {
45 JomloLayoutFactory.horizontalShelf(
46 itemWidth: .absolute(140),
47 itemHeight: .absolute(250),
48 interItemSpacing: 12,
49 headerHeight: .estimated(44)
50 )
51 }
52
53 func cell(
54 for item: any JomloItem,
55 in collectionView: UICollectionView,
56 at indexPath: IndexPath
57 ) -> UICollectionViewCell {
58 guard let posterItem = item as? PosterItem else {
59 return UICollectionViewCell()
60 }
61 return collectionView.dequeueJomloCell(PosterCell.self, for: indexPath, item: posterItem)
62 }
63
64 func supplementaryView(
65 ofKind kind: String,
66 in collectionView: UICollectionView,
67 at indexPath: IndexPath
68 ) -> UICollectionReusableView? {
69 guard kind == UICollectionView.elementKindSectionHeader else { return nil }
70 guard
71 let header = collectionView.dequeueReusableSupplementaryView(
72 ofKind: kind,
73 withReuseIdentifier: JomloSectionHeaderView.reuseIdentifier,
74 for: indexPath
75 ) as? JomloSectionHeaderView
76 else {
77 return nil
78 }
79 header.configure(title: title, actionTitle: "See All") { [weak self] in
80 guard let self else { return }
81 let seeAllVC = SeeAllViewController(title: self.title, items: self.posterItems)
82 self.presenter?.navigationController?.pushViewController(seeAllVC, animated: true)
83 }
84 return header
85 }
86
87 func didSelectItem(_ item: any JomloItem, at indexPath: IndexPath) {
88 guard let posterItem = item as? PosterItem else { return }
89 onItemSelected?(posterItem)
90 }
91
92 var displayAnimation: JomloAnimator.Animation? {
93 JomloAnimator.fadeIn(duration: 0.3, delayFactor: 0.05)
94 }
95 }