This commit is contained in:
2025-12-11 15:19:23 +08:00
parent 04c7d19c37
commit 4fd0a52a36
9 changed files with 125 additions and 16 deletions

View File

@@ -0,0 +1,27 @@
//
// KBShopThemeDetailModel.h
// keyBoard
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import "KBShopThemeTagModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface KBShopThemeDetailModel : NSObject
@property (nonatomic, copy, nullable) NSString *themeId;
@property (nonatomic, copy, nullable) NSString *themeName;
@property (nonatomic, assign) CGFloat themePrice;
@property (nonatomic, strong, nullable) NSArray<KBShopThemeTagModel *> *themeTag;
@property (nonatomic, copy, nullable) NSString *themeDownload;
@property (nonatomic, assign) NSInteger themeStyle;
@property (nonatomic, copy, nullable) NSString *themePreviewImageUrl;
@property (nonatomic, assign) BOOL themeStatus;
@property (nonatomic, assign) NSInteger themePurchasesNumber;
@property (nonatomic, assign) NSInteger sort;
@property (nonatomic, assign) BOOL isFree;
@property (nonatomic, assign) BOOL isPurchased;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,23 @@
//
// KBShopThemeDetailModel.m
// keyBoard
//
#import "KBShopThemeDetailModel.h"
#import <MJExtension/MJExtension.h>
@implementation KBShopThemeDetailModel
+ (NSDictionary *)mj_objectClassInArray {
return @{
@"themeTag" : KBShopThemeTagModel.class
};
}
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
return @{
@"themeId" : @"id"
};
}
@end

View File

@@ -0,0 +1,15 @@
//
// KBShopThemeTagModel.h
// keyBoard
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface KBShopThemeTagModel : NSObject
@property (nonatomic, copy, nullable) NSString *label;
@property (nonatomic, copy, nullable) NSString *color;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,9 @@
//
// KBShopThemeTagModel.m
// keyBoard
//
#import "KBShopThemeTagModel.h"
@implementation KBShopThemeTagModel
@end

View File

@@ -279,7 +279,7 @@ static const CGFloat JXheightForHeaderInSection = 50;
[KBHUD show];
}
__weak typeof(self) weakSelf = self;
[self.shopVM fetchWalletBalanceWithCompletion:^(NSString * _Nullable balance, NSError * _Nullable error) {
[self.shopVM fetchWalletBalanceWithCompletion:^(NSNumber * _Nullable balance, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (showHUD) {
[KBHUD dismiss];
@@ -289,9 +289,9 @@ static const CGFloat JXheightForHeaderInSection = 50;
[KBHUD showInfo:msg];
return;
}
// double amountValue = balance.doubleValue;
// NSString *amountString = [NSString stringWithFormat:@"%.2f", amountValue];
[weakSelf.userHeaderView updatePoints:balance];
double amountValue = balance.doubleValue;
NSString *amountString = [NSString stringWithFormat:@"%.2f", amountValue];
[weakSelf.userHeaderView updatePoints:amountString];
});
}];
}

View File

@@ -12,6 +12,7 @@
#import "KBSkinSectionTitleCell.h"
#import "KBSkinBottomActionView.h"
#import "KBShopVM.h"
#import "KBShopThemeTagModel.h"
static NSString * const kHeaderCellId = @"kHeaderCellId";
static NSString * const kTagsContainerCellId = @"kTagsContainerCellId";
@@ -32,6 +33,7 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
@property (nonatomic, copy) NSArray<NSString *> *tags; //
@property (nonatomic, copy) NSArray<NSDictionary *> *gridData; //
@property (nonatomic, strong) KBShopVM *shopVM;
@property (nonatomic, strong, nullable) KBShopThemeDetailModel *detailModel;
@end
@implementation KBSkinDetailVC
@@ -40,8 +42,7 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
//
self.tags = @[ @"Cute", @"Fresh", @"Cute", @"Fresh", @"Cute", @"Fresh" ];
self.tags = @[];
self.gridData = @[
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@{ @"title": @"Dopamine" }, @{ @"title": @"Dopamine" },
@@ -80,7 +81,7 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
switch (section) {
case KBSkinDetailSectionHeader: return 1; //
case KBSkinDetailSectionTags: return 1; //
case KBSkinDetailSectionTags: return self.tags.count > 0 ? 1 : 0;
case KBSkinDetailSectionTitle: return 1; //
case KBSkinDetailSectionGrid: return self.gridData.count; // 2
}
@@ -91,7 +92,10 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
switch (indexPath.section) {
case KBSkinDetailSectionHeader: {
KBSkinDetailHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kHeaderCellId forIndexPath:indexPath];
[cell configWithTitle:@"Dopamine" right:@"Download: 1 Million"];
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];
return cell;
}
case KBSkinDetailSectionTags: {
@@ -128,7 +132,7 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
}
case KBSkinDetailSectionTags: {
CGFloat h = [KBSkinTagsContainerCell heightForTags:self.tags width:W];
return CGSizeMake(contentW, 25);
return CGSizeMake(contentW, MAX(h, 0.1));
}
case KBSkinDetailSectionTitle: {
return CGSizeMake(contentW, 44);
@@ -216,14 +220,24 @@ typedef NS_ENUM(NSInteger, KBSkinDetailSection) {
return;
}
__weak typeof(self) weakSelf = self;
[self.shopVM fetchThemeDetailWithId:self.themeId completion:^(NSDictionary * _Nullable json, NSError * _Nullable error) {
[self.shopVM fetchThemeDetailWithId:self.themeId completion:^(KBShopThemeDetailModel * _Nullable detail, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
NSLog(@"[KBSkinDetailVC] fetch detail failed: %@", error);
return;
}
NSLog(@"[KBSkinDetailVC] theme detail json: %@", json);
// TODO: parse json into models once the structure is finalized.
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;
[weakSelf.collectionView reloadData];
});
}];

View File

@@ -9,6 +9,7 @@
#import <CoreGraphics/CoreGraphics.h>
#import "KBShopStyleModel.h"
#import "KBShopThemeModel.h"
#import "KBShopThemeDetailModel.h"
NS_ASSUME_NONNULL_BEGIN
@@ -18,9 +19,9 @@ typedef void(^KBShopStylesCompletion)(NSArray<KBShopStyleModel *> *_Nullable sty
NSError *_Nullable error);
typedef void(^KBShopThemesCompletion)(NSArray<KBShopThemeModel *> *_Nullable themes,
NSError *_Nullable error);
typedef void(^KBShopBalanceCompletion)(NSString *_Nullable balance,
typedef void(^KBShopBalanceCompletion)(NSNumber *_Nullable balance,
NSError *_Nullable error);
typedef void(^KBShopDetailCompletion)(NSDictionary *_Nullable json,
typedef void(^KBShopDetailCompletion)(KBShopThemeDetailModel *_Nullable detail,
NSError *_Nullable error);
@interface KBShopVM : NSObject

View File

@@ -127,9 +127,17 @@
completion:^(NSDictionary * _Nullable json,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
if (completion) {
completion(json, error);
if (error) {
if (completion) completion(nil, error);
return;
}
id dataObj = json[KBData] ?: json[@"data"];
if (![dataObj isKindOfClass:[NSDictionary class]]) {
if (completion) completion(nil, [self kb_invalidResponseError]);
return;
}
KBShopThemeDetailModel *detail = [KBShopThemeDetailModel mj_objectWithKeyValues:dataObj];
if (completion) completion(detail, nil);
}];
}