Files
keyboard/keyBoard/Class/Shop/VC/KBSkinDetailVC.m

254 lines
9.9 KiB
Mathematica
Raw Normal View History

2025-11-08 22:25:57 +08:00
//
// KBSkinDetailVC.m
// keyBoard
#import "KBSkinDetailVC.h"
#import <Masonry/Masonry.h>
#import "UIColor+Extension.h"
#import "UICollectionViewLeftAlignedLayout.h"
#import "KBSkinDetailHeaderCell.h"
#import "KBSkinTagsContainerCell.h"
2025-11-10 15:29:21 +08:00
#import "KBSkinCardCell.h"
2025-11-08 22:25:57 +08:00
#import "KBSkinSectionTitleCell.h"
2025-11-10 15:29:21 +08:00
#import "KBSkinBottomActionView.h"
2025-12-11 15:00:58 +08:00
#import "KBShopVM.h"
2025-12-11 15:19:23 +08:00
#import "KBShopThemeTagModel.h"
2025-11-08 22:25:57 +08:00
static NSString * const kHeaderCellId = @"kHeaderCellId";
static NSString * const kTagsContainerCellId = @"kTagsContainerCellId";
static NSString * const kSectionTitleCellId = @"kSectionTitleCellId";
static NSString * const kGridCellId = @"kGridCellId"; // KBSkinCardCell
typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
KBSkinDetailSectionHeader = 0,
KBSkinDetailSectionTags,
KBSkinDetailSectionTitle,
KBSkinDetailSectionGrid,
KBSkinDetailSectionCount
};
@interface KBSkinDetailVC () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
@property (nonatomic, strong) UICollectionView *collectionView; //
2025-11-10 15:29:21 +08:00
@property (nonatomic, strong) KBSkinBottomActionView *bottomBar; //
2025-11-08 22:25:57 +08:00
@property (nonatomic, copy) NSArray<NSString *> *tags; //
@property (nonatomic, copy) NSArray<NSDictionary *> *gridData; //
2025-12-11 15:00:58 +08:00
@property (nonatomic, strong) KBShopVM *shopVM;
2025-12-11 15:19:23 +08:00
@property (nonatomic, strong, nullable) KBShopThemeDetailModel *detailModel;
2025-11-08 22:25:57 +08:00
@end
@implementation KBSkinDetailVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
2025-12-11 15:19:23 +08:00
self.tags = @[];
2025-11-08 22:25:57 +08:00
self.gridData = @[
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
];
2025-11-10 15:29:21 +08:00
// 1.
2025-11-08 22:25:57 +08:00
[self.view addSubview:self.collectionView];
2025-11-10 15:29:21 +08:00
// 2. 15 45
[self.view addSubview:self.bottomBar];
[self.bottomBar mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(15);
make.right.equalTo(self.view).offset(-15);
make.height.mas_equalTo([KBSkinBottomActionView preferredHeight]);
2025-11-17 20:07:39 +08:00
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-10);
2025-11-10 15:29:21 +08:00
}];
// 10
2025-11-08 22:25:57 +08:00
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
2025-11-17 14:53:23 +08:00
make.left.right.equalTo(self.view);
make.top.equalTo(self.view).offset(KB_NAV_TOTAL_HEIGHT);
2025-11-10 15:29:21 +08:00
make.bottom.equalTo(self.bottomBar.mas_top).offset(-10);
2025-11-08 22:25:57 +08:00
}];
2025-12-11 15:00:58 +08:00
[self fetchThemeDetailIfNeeded];
2025-11-08 22:25:57 +08:00
}
#pragma mark - UICollectionView DataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return KBSkinDetailSectionCount;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
switch (section) {
case KBSkinDetailSectionHeader: return 1; //
2025-12-11 15:19:23 +08:00
case KBSkinDetailSectionTags: return self.tags.count > 0 ? 1 : 0;
2025-11-08 22:25:57 +08:00
case KBSkinDetailSectionTitle: return 1; //
case KBSkinDetailSectionGrid: return self.gridData.count; // 2
}
return 0;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case KBSkinDetailSectionHeader: {
KBSkinDetailHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kHeaderCellId forIndexPath:indexPath];
2025-12-11 15:19:23 +08:00
NSString *title = self.detailModel.themeName.length ? self.detailModel.themeName : @"Dopamine";
NSString *download = self.detailModel.themeDownload.length ? self.detailModel.themeDownload : @"0";
NSString *right = [NSString stringWithFormat:@"%@: %@", KBLocalized(@"Download"), download];
[cell configWithTitle:title right:right];
2025-11-08 22:25:57 +08:00
return cell;
}
case KBSkinDetailSectionTags: {
KBSkinTagsContainerCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kTagsContainerCellId forIndexPath:indexPath];
[cell configWithTags:self.tags];
return cell;
}
case KBSkinDetailSectionTitle: {
KBSkinSectionTitleCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kSectionTitleCellId forIndexPath:indexPath];
[cell config:@"Recommended Skin"];
return cell;
}
case KBSkinDetailSectionGrid: {
KBSkinCardCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kGridCellId forIndexPath:indexPath];
NSDictionary *d = self.gridData[indexPath.item];
[cell configWithTitle:d[@"title"] imageURL:nil price:@"20"];
return cell;
}
}
return [UICollectionViewCell new];
}
#pragma mark - UICollectionView DelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
CGFloat W = collectionView.bounds.size.width;
CGFloat insetLR = 16.0;
CGFloat contentW = W - insetLR * 2;
switch (indexPath.section) {
case KBSkinDetailSectionHeader: {
// = 0.58W + 56
2025-11-17 15:39:03 +08:00
CGFloat h = KBFit(264) + 30;
2025-11-08 22:25:57 +08:00
return CGSizeMake(contentW, h);
}
case KBSkinDetailSectionTags: {
CGFloat h = [KBSkinTagsContainerCell heightForTags:self.tags width:W];
2025-12-11 15:19:23 +08:00
return CGSizeMake(contentW, MAX(h, 0.1));
2025-11-08 22:25:57 +08:00
}
case KBSkinDetailSectionTitle: {
return CGSizeMake(contentW, 44);
}
case KBSkinDetailSectionGrid: {
// 2
CGFloat spacing = 12.0;
CGFloat itemW = floor((contentW - spacing) / 2.0);
2025-11-17 15:06:05 +08:00
// CGFloat itemH = itemW * 0.75 + 56;
return CGSizeMake(itemW, KBFit(197));
2025-11-08 22:25:57 +08:00
}
}
return CGSizeZero;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
2025-11-17 15:39:03 +08:00
// Header Tags
switch (section) {
case KBSkinDetailSectionHeader:
// 12
return UIEdgeInsetsMake(12, 16, 4, 16);
case KBSkinDetailSectionTags:
// Header
return UIEdgeInsetsMake(14, 16, 5, 16);
default:
return UIEdgeInsetsMake(0, 16, 12, 16);
}
2025-11-08 22:25:57 +08:00
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 12.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
//
return 12.0;
}
#pragma mark - Lazy
- (UICollectionView *)collectionView {
if (!_collectionView) {
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
_collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor whiteColor];
_collectionView.dataSource = self;
_collectionView.delegate = self;
// cell
[_collectionView registerClass:KBSkinDetailHeaderCell.class forCellWithReuseIdentifier:kHeaderCellId];
[_collectionView registerClass:KBSkinTagsContainerCell.class forCellWithReuseIdentifier:kTagsContainerCellId];
[_collectionView registerClass:KBSkinSectionTitleCell.class forCellWithReuseIdentifier:kSectionTitleCellId];
[_collectionView registerClass:KBSkinCardCell.class forCellWithReuseIdentifier:kGridCellId];
}
return _collectionView;
}
2025-11-10 15:29:21 +08:00
#pragma mark - Lazy (Bottom Bar)
- (KBSkinBottomActionView *)bottomBar {
if (!_bottomBar) {
_bottomBar = [[KBSkinBottomActionView alloc] init];
// /
[_bottomBar configWithTitle:@"Download" price:@"20" icon:nil];
2025-11-10 15:38:30 +08:00
KBWeakSelf
2025-11-10 15:29:21 +08:00
_bottomBar.tapHandler = ^{
// /
// [KBHUD showText:@"点击了下载"];
// TODO: /
[weakSelf handleDownloadAction];
};
}
return _bottomBar;
}
#pragma mark - Actions
- (void)handleDownloadAction {
// /
}
2025-12-11 15:00:58 +08:00
- (void)fetchThemeDetailIfNeeded {
if (self.themeId.length == 0) {
NSLog(@"[KBSkinDetailVC] themeId is empty, skip detail request");
return;
}
__weak typeof(self) weakSelf = self;
2025-12-11 15:19:23 +08:00
[self.shopVM fetchThemeDetailWithId:self.themeId completion:^(KBShopThemeDetailModel * _Nullable detail, NSError * _Nullable error) {
2025-12-11 15:00:58 +08:00
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"[KBSkinDetailVC] fetch detail failed: %@", error);
return;
}
2025-12-11 15:19:23 +08:00
if (!detail) {
NSLog(@"[KBSkinDetailVC] theme detail is empty");
return;
}
weakSelf.detailModel = detail;
NSMutableArray<NSString *> *tagNames = [NSMutableArray array];
for (KBShopThemeTagModel *tag in detail.themeTag) {
if (tag.label.length) {
[tagNames addObject:tag.label];
}
}
weakSelf.tags = tagNames.copy;
2025-12-11 15:00:58 +08:00
[weakSelf.collectionView reloadData];
});
}];
}
- (KBShopVM *)shopVM {
if (!_shopVM) {
_shopVM = [[KBShopVM alloc] init];
}
return _shopVM;
}
2025-11-08 22:25:57 +08:00
@end