Skip to content

Commit f272081

Browse files
committed
Browser update
1 parent 8331ce5 commit f272081

File tree

5 files changed

+146
-92
lines changed

5 files changed

+146
-92
lines changed

LocalPackages/App/Sources/App/BrowserModule/Modules/BrowserExplore/BrowserExploreSection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33
enum BrowserExploreSection: Hashable {
4-
case regular(title: String, hasAll: Bool, items: [AnyHashable])
4+
case regular(title: String?, hasAll: Bool, items: [AnyHashable])
55
case featured(items: [BrowserExploreFeatureSectionItem])
66
}
77

LocalPackages/App/Sources/App/BrowserModule/Modules/BrowserExplore/BrowserExploreViewController.swift

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ private extension BrowserExploreViewController {
121121
let snapshot = dataSource.snapshot()
122122
let section = snapshot.sectionIdentifiers[sectionIndex]
123123
switch section {
124-
case .regular:
124+
case let .regular(title,_ ,_):
125125
return regularSectionLayout(
126126
snapshot: snapshot,
127+
hasTitle: title != nil,
127128
section: section,
128129
environment: environment
129130
)
@@ -136,59 +137,52 @@ private extension BrowserExploreViewController {
136137
}
137138

138139
func regularSectionLayout(snapshot: NSDiffableDataSourceSnapshot<BrowserExploreSection, AnyHashable>,
140+
hasTitle: Bool,
139141
section: BrowserExploreSection,
140142
environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
141143
let itemSize = NSCollectionLayoutSize(
142-
widthDimension: .fractionalWidth(1),
143-
heightDimension: .absolute(84)
144+
widthDimension: .fractionalWidth(1/4),
145+
heightDimension: .absolute(104)
144146
)
145147
let item = NSCollectionLayoutItem(layoutSize: itemSize)
146148
item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 8)
147-
148-
let itemsCount = snapshot.numberOfItems(inSection: section)
149-
let groupItemsCount = itemsCount < 3 ? itemsCount : 3
150-
151-
let widthDimension: NSCollectionLayoutDimension
152-
if itemsCount <= 3 {
153-
widthDimension = .absolute(environment.container.effectiveContentSize.width - 24)
154-
} else {
155-
widthDimension = .fractionalWidth(0.88)
156-
}
149+
157150
let groupSize = NSCollectionLayoutSize(
158-
widthDimension: widthDimension,
159-
heightDimension: .absolute(CGFloat(groupItemsCount) * 84)
151+
widthDimension: .fractionalWidth(1),
152+
heightDimension: .estimated(104)
160153
)
161154

162155
let group: NSCollectionLayoutGroup
163-
156+
164157
if #available(iOS 16.0, *) {
165-
group = NSCollectionLayoutGroup.verticalGroup(
158+
group = NSCollectionLayoutGroup.horizontalGroup(
166159
with: groupSize,
167160
repeatingSubitem: item,
168-
count: groupItemsCount
161+
count: 4
169162
)
170163
} else {
171-
group = NSCollectionLayoutGroup.vertical(
164+
group = NSCollectionLayoutGroup.horizontal(
172165
layoutSize: groupSize,
173166
subitem: item,
174-
count: groupItemsCount
167+
count: 4
175168
)
176169
}
177170

178171
let section = NSCollectionLayoutSection(group: group)
179-
section.orthogonalScrollingBehavior = .groupPaging
180-
section.contentInsets = .init(top: 10, leading: 16, bottom: 16, trailing: 0)
172+
section.contentInsets = .init(top: 10, leading: 12, bottom: 16, trailing: 12)
181173

182-
let headerSize = NSCollectionLayoutSize(
183-
widthDimension: .fractionalWidth(1.0),
184-
heightDimension: .estimated(56)
185-
)
186-
let header = NSCollectionLayoutBoundarySupplementaryItem(
187-
layoutSize: headerSize,
188-
elementKind: BrowserExploreSectionHeaderView.reuseIdentifier,
189-
alignment: .top
190-
)
191-
section.boundarySupplementaryItems = [header]
174+
if hasTitle {
175+
let headerSize = NSCollectionLayoutSize(
176+
widthDimension: .fractionalWidth(1.0),
177+
heightDimension: .estimated(56)
178+
)
179+
let header = NSCollectionLayoutBoundarySupplementaryItem(
180+
layoutSize: headerSize,
181+
elementKind: BrowserExploreSectionHeaderView.reuseIdentifier,
182+
alignment: .top
183+
)
184+
section.boundarySupplementaryItems = [header]
185+
}
192186

193187
return section
194188
}
@@ -212,10 +206,14 @@ private extension BrowserExploreViewController {
212206
}
213207

214208
func createDataSource() -> DataSource {
215-
let dataSource = DataSource(collectionView: customView.collectionView) { [featuredView, listItemCellConfiguration] collectionView, indexPath, itemIdentifier in
209+
let connectedAppCellConfiguration = UICollectionView.CellRegistration<BrowserAppCollectionViewCell, BrowserAppCollectionViewCell.Configuration> { cell, indexPath, itemIdentifier in
210+
cell.configure(configuration: itemIdentifier)
211+
}
212+
213+
let dataSource = DataSource(collectionView: customView.collectionView) { [featuredView] collectionView, indexPath, itemIdentifier in
216214
switch itemIdentifier {
217-
case let listCellConfiguration as TKUIListItemCell.Configuration:
218-
return collectionView.dequeueConfiguredReusableCell(using: listItemCellConfiguration, for: indexPath, item: listCellConfiguration)
215+
case let item as BrowserAppCollectionViewCell.Configuration:
216+
return collectionView.dequeueConfiguredReusableCell(using: connectedAppCellConfiguration, for: indexPath, item: item)
219217
case _ as BrowserExploreFeatureSectionItem:
220218
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ContainerCell", for: indexPath)
221219
cell.contentView.addSubview(featuredView)
@@ -241,7 +239,7 @@ private extension BrowserExploreViewController {
241239
)
242240

243241
sectionHeader.configure(model: BrowserExploreSectionHeaderView.Model(
244-
title: title,
242+
title: title ?? "",
245243
isAllHidden: !hasAll,
246244
allTapAction: { [weak self] in
247245
self?.viewModel.didSelectCategoryAll(index: indexPath.section)

LocalPackages/App/Sources/App/BrowserModule/Modules/BrowserExplore/BrowserExploreViewModel.swift

Lines changed: 13 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -244,74 +244,33 @@ private extension BrowserExploreViewModelImplementation {
244244
let filter = composeCountryFilter()
245245

246246
return categories.compactMap { category in
247-
let items: [TKUIListItemCell.Configuration?] = category.apps.compactMap {
247+
let items: [BrowserAppCollectionViewCell.Configuration?] = category.apps.compactMap {
248248
if let filter, isDappContainsCountriesFilter(filter, dapp: $0) {
249249
return nil
250250
}
251251

252252
return mapDapp($0)
253253
}
254254

255+
let categoryTitle = category.id == "digital_nomads" ? nil : category.title
256+
255257
return BrowserExploreSection.regular(
256-
title: category.title ?? "",
258+
title: categoryTitle,
257259
hasAll: items.count > 3,
258260
items: items
259261
)
260262
}
261263
}
262264

263-
func mapDapp(_ dapp: Dapp) -> TKUIListItemCell.Configuration? {
264-
let id = UUID().uuidString
265-
return TKUIListItemCell.Configuration(
266-
id: id,
267-
listItemConfiguration: TKUIListItemView.Configuration(
268-
iconConfiguration: TKUIListItemIconView.Configuration(
269-
iconConfiguration: .image(
270-
TKUIListItemImageIconView.Configuration(
271-
image: .asyncImage(
272-
dapp.icon,
273-
TKCore.ImageDownloadTask(
274-
closure: {
275-
[imageLoader] imageView,
276-
size,
277-
cornerRadius in
278-
return imageLoader.loadImage(
279-
url: dapp.icon,
280-
imageView: imageView,
281-
size: size,
282-
cornerRadius: cornerRadius
283-
)
284-
}
285-
)
286-
),
287-
tintColor: .clear,
288-
backgroundColor: .clear,
289-
size: CGSize(width: 44, height: 44),
290-
cornerRadius: 12
291-
)
292-
),
293-
alignment: .center
294-
),
295-
contentConfiguration: TKUIListItemContentView.Configuration(
296-
leftItemConfiguration: TKUIListItemContentLeftItem.Configuration(
297-
title: dapp.name.withTextStyle(.label2, color: .Text.primary),
298-
tagViewModel: nil,
299-
subtitle: nil,
300-
description: dapp.description?.withTextStyle(.body3Alternate, color: .Text.secondary),
301-
descriptionNumberOfLines: 2
302-
),
303-
rightItemConfiguration: nil,
304-
isVerticalCenter: true
305-
),
306-
accessoryConfiguration: .image(.init(image: .TKUIKit.Icons.Size16.chevronRight, tintColor: .Icon.tertiary, padding: .zero))
307-
),
308-
selectionClosure: { [weak self] in
309-
self?.didSelectDapp?(dapp)
310-
self?.analyticsProvider.logEvent(eventKey: .clickDapp,
311-
args: ["name": dapp.name,
312-
"url": dapp.url.absoluteString,
313-
"from": "browser"])
314-
}
265+
func mapDapp(_ dapp: Dapp) -> BrowserAppCollectionViewCell.Configuration {
266+
return BrowserAppCollectionViewCell.Configuration(
267+
id: UUID(),
268+
title: dapp.name,
269+
iconModel: TKImageView.Model(
270+
image: .urlImage(dapp.icon),
271+
size: .size(CGSize(width: 64, height: 64)),
272+
corners: .cornerRadius(cornerRadius: 16)
273+
)
315274
)
316275
}
317276

LocalPackages/App/Sources/App/BrowserModule/Modules/BrowserExplore/Views/BrowserExploreSectionHeaderView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,9 @@ private extension BrowserExploreSectionHeaderView {
7777

7878
func setupConstraints() {
7979
stackView.snp.makeConstraints { make in
80-
make.top.left.bottom.equalTo(self).priority(.medium)
80+
make.top.bottom.equalTo(self).priority(.medium)
8181
make.right.equalTo(self).inset(18).priority(.medium)
82+
make.left.equalTo(self).inset(4).priority(.medium)
8283
}
8384
}
8485

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import UIKit
2+
import TKUIKit
3+
4+
final class BrowserAppCollectionViewCell: UICollectionViewCell, ReusableView, TKConfigurableView {
5+
6+
var didLongPress: (() -> Void)?
7+
8+
let iconImageView = TKImageView()
9+
let titleLabel = UILabel()
10+
11+
override var isHighlighted: Bool {
12+
didSet {
13+
alpha = isHighlighted ? 0.48 : 1
14+
}
15+
}
16+
17+
override init(frame: CGRect) {
18+
super.init(frame: frame)
19+
setup()
20+
}
21+
22+
required init?(coder: NSCoder) {
23+
fatalError("init(coder:) has not been implemented")
24+
}
25+
26+
override func prepareForReuse() {
27+
super.prepareForReuse()
28+
iconImageView.prepareForReuse()
29+
}
30+
31+
struct Configuration: Hashable {
32+
let id: UUID
33+
let title: NSAttributedString
34+
let iconModel: TKImageView.Model
35+
36+
func hash(into hasher: inout Hasher) {
37+
hasher.combine(id)
38+
}
39+
40+
static func ==(lhs: Configuration, rhs: Configuration) -> Bool {
41+
return lhs.id == rhs.id
42+
}
43+
44+
init(id: UUID,
45+
title: String,
46+
iconModel: TKImageView.Model) {
47+
self.id = id
48+
self.title = title.withTextStyle(
49+
.body3,
50+
color: .Text.secondary,
51+
alignment: .center,
52+
lineBreakMode: .byTruncatingTail
53+
)
54+
self.iconModel = iconModel
55+
}
56+
}
57+
58+
func configure(configuration: Configuration) {
59+
titleLabel.attributedText = configuration.title
60+
iconImageView.configure(model: configuration.iconModel)
61+
setNeedsLayout()
62+
}
63+
}
64+
65+
private extension BrowserAppCollectionViewCell {
66+
func setup() {
67+
addSubview(titleLabel)
68+
addSubview(iconImageView)
69+
70+
iconImageView.snp.makeConstraints { make in
71+
make.top.equalTo(self)
72+
make.centerX.equalTo(self)
73+
make.size.equalTo(64)
74+
}
75+
76+
titleLabel.snp.makeConstraints { make in
77+
make.top.equalTo(iconImageView.snp.bottom)
78+
make.left.right.equalTo(self)
79+
make.bottom.equalTo(self).offset(-8)
80+
}
81+
82+
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(longPressGestureHandler(recognizer:)))
83+
longPressGesture.minimumPressDuration = 0.5
84+
addGestureRecognizer(longPressGesture)
85+
}
86+
87+
@objc
88+
func longPressGestureHandler(recognizer: UILongPressGestureRecognizer) {
89+
switch recognizer.state {
90+
case .began:
91+
didLongPress?()
92+
default:
93+
break
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)