main
swift 181 lines 6.82 KB
Raw
1 //
2 // StreamingHomeViewController.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 StreamingHomeViewController: JomloCollectionViewController {
14
15 init() {
16 super.init(sections: [])
17 }
18
19 override func viewDidLoad() {
20 super.viewDidLoad()
21 title = "JomloCV"
22 #if os(iOS)
23 view.backgroundColor = .systemBackground
24 #endif
25
26 // Register cells
27 collectionView.registerJomloCell(HeroCell.self)
28 collectionView.registerJomloCell(PosterCell.self)
29 collectionView.registerJomloCell(CategoryCell.self)
30 collectionView.registerJomloCell(ContinueWatchingCell.self)
31
32 // Register header
33 collectionView.register(
34 JomloSectionHeaderView.self,
35 forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
36 withReuseIdentifier: JomloSectionHeaderView.reuseIdentifier
37 )
38
39 // Load content
40 loadContent()
41 }
42
43 private func loadContent() {
44 let sections: [any JomloSection] = [
45 makeHeroSection(),
46 makeContinueWatchingSection(),
47 makeTrendingSection(),
48 makeSeriesSection(),
49 makeCategoriesSection(),
50 makeMoviesSection(),
51 ]
52
53 setSections(sections, animated: true)
54 }
55
56 // MARK: - Section Factories
57
58 private func makeHeroSection() -> HeroSection {
59 HeroSection(items: [
60 HeroItem(
61 id: "hero-1",
62 title: "The Last Kingdom",
63 subtitle: "Season 5 Now Streaming",
64 gradientColors: (top: "#1a237e", bottom: "#4a148c")
65 ),
66 HeroItem(
67 id: "hero-2",
68 title: "Formula 1: Drive to Survive",
69 subtitle: "New Season Available",
70 gradientColors: (top: "#b71c1c", bottom: "#e65100")
71 ),
72 HeroItem(
73 id: "hero-3",
74 title: "Premier League Live",
75 subtitle: "Every Match, Every Week",
76 gradientColors: (top: "#1b5e20", bottom: "#004d40")
77 ),
78 ])
79 }
80
81 private func makeContinueWatchingSection() -> ContinueWatchingSection {
82 ContinueWatchingSection(items: [
83 ContinueWatchingItem(
84 id: "cw-1", title: "Breaking Bad", episodeInfo: "S3 E7 \u{00B7} One Minute",
85 progress: 0.65, colorHex: "#2e7d32"),
86 ContinueWatchingItem(
87 id: "cw-2", title: "The Bear", episodeInfo: "S2 E3 \u{00B7} Sundae", progress: 0.3,
88 colorHex: "#f57f17"),
89 ContinueWatchingItem(
90 id: "cw-3", title: "Succession", episodeInfo: "S4 E1 \u{00B7} The Munsters",
91 progress: 0.82, colorHex: "#1565c0"),
92 ContinueWatchingItem(
93 id: "cw-4", title: "Slow Horses", episodeInfo: "S3 E4 \u{00B7} Uninvited",
94 progress: 0.45, colorHex: "#6a1b9a"),
95 ])
96 }
97
98 private func makeTrendingSection() -> ShelfSection {
99 ShelfSection(
100 id: "trending",
101 title: "Trending Now",
102 items: [
103 PosterItem(id: "t-1", title: "Oppenheimer", year: "2023", colorHex: "#ff6f00"),
104 PosterItem(
105 id: "t-2", title: "Killers of the Flower Moon", year: "2023",
106 colorHex: "#4e342e"),
107 PosterItem(id: "t-3", title: "Past Lives", year: "2023", colorHex: "#00838f"),
108 PosterItem(
109 id: "t-4", title: "Anatomy of a Fall", year: "2023", colorHex: "#283593"),
110 PosterItem(id: "t-5", title: "The Holdovers", year: "2023", colorHex: "#2e7d32"),
111 PosterItem(id: "t-6", title: "Poor Things", year: "2023", colorHex: "#ad1457"),
112 ],
113 presenter: self
114 )
115 }
116
117 private func makeSeriesSection() -> ShelfSection {
118 ShelfSection(
119 id: "series",
120 title: "Popular Series",
121 items: [
122 PosterItem(id: "s-1", title: "The Bear", year: "2022\u{2013}", colorHex: "#e65100"),
123 PosterItem(
124 id: "s-2", title: "Slow Horses", year: "2022\u{2013}", colorHex: "#1a237e"),
125 PosterItem(
126 id: "s-3", title: "Severance", year: "2022\u{2013}", colorHex: "#004d40"),
127 PosterItem(id: "s-4", title: "Shogun", year: "2024", colorHex: "#b71c1c"),
128 PosterItem(id: "s-5", title: "True Detective", year: "2024", colorHex: "#311b92"),
129 PosterItem(id: "s-6", title: "Fallout", year: "2024", colorHex: "#33691e"),
130 ],
131 presenter: self
132 )
133 }
134
135 private func makeCategoriesSection() -> CategoriesGridSection {
136 CategoriesGridSection(items: [
137 CategoryItem(id: "cat-1", name: "Movies", iconName: "\u{1F3AC}", colorHex: "#c62828"),
138 CategoryItem(id: "cat-2", name: "Series", iconName: "\u{1F4FA}", colorHex: "#ad1457"),
139 CategoryItem(id: "cat-3", name: "Sports", iconName: "\u{26BD}", colorHex: "#1565c0"),
140 CategoryItem(id: "cat-4", name: "Kids", iconName: "\u{1F9F8}", colorHex: "#2e7d32"),
141 CategoryItem(
142 id: "cat-5", name: "Documentaries", iconName: "\u{1F30D}", colorHex: "#e65100"),
143 CategoryItem(id: "cat-6", name: "Live TV", iconName: "\u{1F4E1}", colorHex: "#4527a0"),
144 ])
145 }
146
147 private func makeMoviesSection() -> ShelfSection {
148 ShelfSection(
149 id: "movies",
150 title: "New Movies",
151 items: [
152 PosterItem(id: "m-1", title: "Dune: Part Two", year: "2024", colorHex: "#ff8f00"),
153 PosterItem(id: "m-2", title: "Civil War", year: "2024", colorHex: "#455a64"),
154 PosterItem(id: "m-3", title: "Challengers", year: "2024", colorHex: "#00695c"),
155 PosterItem(
156 id: "m-4", title: "The Zone of Interest", year: "2023", colorHex: "#37474f"),
157 PosterItem(
158 id: "m-5", title: "All of Us Strangers", year: "2023", colorHex: "#1a237e"),
159 ],
160 presenter: self
161 )
162 }
163 }
164
165 // MARK: - UIColor Hex Extension
166
167 extension UIColor {
168 convenience init?(hex: String) {
169 var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
170 hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
171
172 var rgb: UInt64 = 0
173 guard Scanner(string: hexSanitized).scanHexInt64(&rgb) else { return nil }
174
175 let r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
176 let g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
177 let b = CGFloat(rgb & 0x0000FF) / 255.0
178
179 self.init(red: r, green: g, blue: b, alpha: 1.0)
180 }
181 }