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

@@ -119,6 +119,8 @@
0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDDD2EE81508006CC1D5 /* KBShopVM.m */; }; 0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDDD2EE81508006CC1D5 /* KBShopVM.m */; };
0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */; }; 0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */; };
0498BDE42EEA885D006CC1D5 /* KBShopThemeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */; }; 0498BDE42EEA885D006CC1D5 /* KBShopThemeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */; };
49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */; };
EB72B60040437E3C0A4890FC /* KBShopThemeDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B9F60894E529C3EDAF6BAC3D /* KBShopThemeDetailModel.m */; };
049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */; }; 049FB20B2EC1C13800FAB05D /* KBSkinBottomActionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */; };
049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20D2EC1CD2800FAB05D /* KBAlert.m */; }; 049FB20E2EC1CD2800FAB05D /* KBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB20D2EC1CD2800FAB05D /* KBAlert.m */; };
049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2102EC1F72F00FAB05D /* KBMyListCell.m */; }; 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 049FB2102EC1F72F00FAB05D /* KBMyListCell.m */; };
@@ -419,6 +421,10 @@
0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopStyleModel.m; sourceTree = "<group>"; }; 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopStyleModel.m; sourceTree = "<group>"; };
0498BDE22EEA885D006CC1D5 /* KBShopThemeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeModel.h; sourceTree = "<group>"; }; 0498BDE22EEA885D006CC1D5 /* KBShopThemeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeModel.h; sourceTree = "<group>"; };
0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopThemeModel.m; sourceTree = "<group>"; }; 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopThemeModel.m; sourceTree = "<group>"; };
35E2B1C590E060D912A4E7F4 /* KBShopThemeTagModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeTagModel.h; sourceTree = "<group>"; };
E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopThemeTagModel.m; sourceTree = "<group>"; };
9A38793DBF4AB38A006D4F44 /* KBShopThemeDetailModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBShopThemeDetailModel.h; sourceTree = "<group>"; };
B9F60894E529C3EDAF6BAC3D /* KBShopThemeDetailModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBShopThemeDetailModel.m; sourceTree = "<group>"; };
049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinBottomActionView.h; sourceTree = "<group>"; }; 049FB2092EC1C13800FAB05D /* KBSkinBottomActionView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBSkinBottomActionView.h; sourceTree = "<group>"; };
049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinBottomActionView.m; sourceTree = "<group>"; }; 049FB20A2EC1C13800FAB05D /* KBSkinBottomActionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBSkinBottomActionView.m; sourceTree = "<group>"; };
049FB20C2EC1CD2800FAB05D /* KBAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAlert.h; sourceTree = "<group>"; }; 049FB20C2EC1CD2800FAB05D /* KBAlert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAlert.h; sourceTree = "<group>"; };
@@ -782,6 +788,10 @@
0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */, 0498BDE02EEA87C8006CC1D5 /* KBShopStyleModel.m */,
0498BDE22EEA885D006CC1D5 /* KBShopThemeModel.h */, 0498BDE22EEA885D006CC1D5 /* KBShopThemeModel.h */,
0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */, 0498BDE32EEA885D006CC1D5 /* KBShopThemeModel.m */,
35E2B1C590E060D912A4E7F4 /* KBShopThemeTagModel.h */,
E2A844CD2D8584596DBE6316 /* KBShopThemeTagModel.m */,
9A38793DBF4AB38A006D4F44 /* KBShopThemeDetailModel.h */,
B9F60894E529C3EDAF6BAC3D /* KBShopThemeDetailModel.m */,
); );
path = M; path = M;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1864,6 +1874,8 @@
04C6EABF2EAF86530089C901 /* main.m in Sources */, 04C6EABF2EAF86530089C901 /* main.m in Sources */,
0498BD6E2EE0285D006CC1D5 /* KBForgetVerPwdVC.m in Sources */, 0498BD6E2EE0285D006CC1D5 /* KBForgetVerPwdVC.m in Sources */,
0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */, 0498BDE12EEA87C9006CC1D5 /* KBShopStyleModel.m in Sources */,
49B63DBAEE9076C591E13D68 /* KBShopThemeTagModel.m in Sources */,
EB72B60040437E3C0A4890FC /* KBShopThemeDetailModel.m in Sources */,
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */, 04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
0479205A2EDEE1FC004E8522 /* CRBoxTextView.m in Sources */, 0479205A2EDEE1FC004E8522 /* CRBoxTextView.m in Sources */,
0479205B2EDEE1FC004E8522 /* CRSecrectImageView.m in Sources */, 0479205B2EDEE1FC004E8522 /* CRSecrectImageView.m in Sources */,

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]; [KBHUD show];
} }
__weak typeof(self) weakSelf = self; __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(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
if (showHUD) { if (showHUD) {
[KBHUD dismiss]; [KBHUD dismiss];
@@ -289,9 +289,9 @@ static const CGFloat JXheightForHeaderInSection = 50;
[KBHUD showInfo:msg]; [KBHUD showInfo:msg];
return; return;
} }
// double amountValue = balance.doubleValue; double amountValue = balance.doubleValue;
// NSString *amountString = [NSString stringWithFormat:@"%.2f", amountValue]; NSString *amountString = [NSString stringWithFormat:@"%.2f", amountValue];
[weakSelf.userHeaderView updatePoints:balance]; [weakSelf.userHeaderView updatePoints:amountString];
}); });
}]; }];
} }

View File

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

View File

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

View File

@@ -127,9 +127,17 @@
completion:^(NSDictionary * _Nullable json, completion:^(NSDictionary * _Nullable json,
NSURLResponse * _Nullable response, NSURLResponse * _Nullable response,
NSError * _Nullable error) { NSError * _Nullable error) {
if (completion) { if (error) {
completion(json, 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);
}]; }];
} }