This commit is contained in:
2025-12-11 13:40:32 +08:00
parent d348b35984
commit 45695364e9
11 changed files with 123 additions and 29 deletions

View File

@@ -53,7 +53,7 @@
_useEmptyDataSet = YES; //
_emptyShouldAllowScroll = YES; //
_emptyVerticalOffset = 0; //
_emptyTitleText = KBLocalized(@"暂无数据"); //
_emptyTitleText = KBLocalized(@"No data"); //
#if KB_HAS_DZN
self.emptyDataSetSource = self;
@@ -148,7 +148,7 @@
self.useEmptyDataSet = NO;
//
NSString *t = title ?: KBLocalized(@"暂无数据");
NSString *t = title ?: KBLocalized(@"No data");
LYEmptyView *ev = nil;
if (buttonTitle.length > 0) {

View File

@@ -22,7 +22,7 @@
tapHandler:(KBEmptyAction)tapHandler
buttonHandler:(KBEmptyAction)buttonHandler {
#if KB_HAS_LY
NSString *t = title ?: KBLocalized(@"暂无数据");
NSString *t = title ?: KBLocalized(@"No data");
LYEmptyView *ev = nil;
if (buttonTitle.length > 0) {

View File

@@ -0,0 +1,25 @@
//
// KBMyTheme.h
// keyBoard
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
/// “我的皮肤”页已购主题模型
@interface KBMyTheme : NSObject
@property (nonatomic, copy, nullable) NSString *themeId;
@property (nonatomic, copy, nullable) NSString *themeName;
@property (nonatomic, assign) CGFloat themePrice;
@property (nonatomic, copy, nullable) NSArray<NSString *> *themeTag;
@property (nonatomic, copy, nullable) NSString *themeDownload;
@property (nonatomic, assign) NSInteger themeStyle;
@property (nonatomic, assign) BOOL themeStatus;
@property (nonatomic, assign) NSInteger themePurchasesNumber;
@property (nonatomic, assign) NSInteger sort;
@property (nonatomic, assign) BOOL isFree;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,17 @@
//
// KBMyTheme.m
// keyBoard
//
#import "KBMyTheme.h"
#import <MJExtension/MJExtension.h>
@implementation KBMyTheme
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
return @{
@"themeId": @"id"
};
}
@end

View File

@@ -11,6 +11,9 @@
#import "UIScrollView+KBEmptyView.h" // LYEmptyView
#import "MySkinCell.h"
#import "KBMyVM.h"
#import "KBMyTheme.h"
#import "KBHUD.h"
static NSString * const kMySkinCellId = @"kMySkinCellId";
@@ -20,8 +23,8 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
@property (nonatomic, strong) UILabel *selectedLabel; //
@property (nonatomic, strong) UIButton *deleteButton; //
@property (nonatomic, strong) NSMutableArray<NSDictionary *> *data; //
@property (nonatomic, assign) NSInteger loadCount; // /
@property (nonatomic, strong) NSMutableArray<KBMyTheme *> *data; //
@property (nonatomic, strong) KBMyVM *viewModel;
@property (nonatomic, assign, getter=isEditingMode) BOOL editingMode; //
@end
@@ -62,9 +65,9 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
// LYEmptyView +
KBWeakSelf
[self.collectionView kb_makeDefaultEmptyViewWithImage:nil
title:KBLocalized(@"No skins yet")
title:KBLocalized(@"No data")
detail:KBLocalized(@"Pull down to refresh")
buttonTitle:KBLocalized(@"Retry")
buttonTitle:KBLocalized(@"")
tapHandler:nil
buttonHandler:^{ [weakSelf.collectionView.mj_header beginRefreshing]; }];
[self.collectionView kb_setLYAutoShowEnabled:NO]; //
@@ -73,7 +76,7 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
[self.collectionView kb_endLoadingForEmpty];
// +
self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(fetchData)];
self.collectionView.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(fetchPurchasedThemes)];
//
[self.collectionView.mj_header beginRefreshing];
@@ -82,25 +85,25 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
self.bottomView.hidden = YES;
}
#pragma mark - Data
- (void)fetchData {
// 1.0s
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.loadCount += 1;
// /
[self.data removeAllObjects];
if (self.loadCount % 2 == 0) {
for (int i = 0; i < 8; i++) {
[self.data addObject:@{ @"title": @"Dopamine" }];
- (void)fetchPurchasedThemes {
KBWeakSelf
[self.viewModel fetchPurchasedThemesWithCompletion:^(NSArray<KBMyTheme *> * _Nullable themes, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakSelf.collectionView.mj_header isRefreshing]) {
[weakSelf.collectionView.mj_header endRefreshing];
}
}
[self.collectionView reloadData];
[self.collectionView kb_endLoadingForEmpty]; // / emptyView
[self.collectionView.mj_header endRefreshing];
});
if (error) {
[weakSelf.collectionView kb_endLoadingForEmpty];
return;
}
[weakSelf.data removeAllObjects];
if (themes.count > 0) {
[weakSelf.data addObjectsFromArray:themes];
}
[weakSelf.collectionView reloadData];
[weakSelf.collectionView kb_endLoadingForEmpty];
});
}];
}
#pragma mark - Actions
@@ -190,8 +193,8 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MySkinCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kMySkinCellId forIndexPath:indexPath];
NSDictionary *d = self.data[indexPath.item];
[cell configWithTitle:d[@"title"] image:nil];
KBMyTheme *theme = self.data[indexPath.item];
[cell configWithTitle:theme.themeName image:nil];
cell.editing = self.isEditingMode; //
//
BOOL selected = [[collectionView indexPathsForSelectedItems] containsObject:indexPath];
@@ -306,4 +309,11 @@ static NSString * const kMySkinCellId = @"kMySkinCellId";
return _deleteButton;
}
- (KBMyVM *)viewModel {
if (!_viewModel) {
_viewModel = [[KBMyVM alloc] init];
}
return _viewModel;
}
@end

View File

@@ -7,6 +7,7 @@
#import <Foundation/Foundation.h>
#import "KBCharacter.h"
#import "KBMyTheme.h"
@class KBUser;
NS_ASSUME_NONNULL_BEGIN
@@ -22,6 +23,7 @@ typedef void(^KBUpLoadAvatarCompletion)(BOOL success, NSError * _Nullable error)
typedef void(^KBUpdateUserInfoCompletion)(BOOL success, NSError * _Nullable error);
typedef void(^KBUpdateCharacterSortCompletion)(BOOL success, NSError * _Nullable error);
typedef void(^KBDeleteUserCharacterCompletion)(BOOL success, NSError * _Nullable error);
typedef void(^KBMyPurchasedThemesCompletion)(NSArray<KBMyTheme *> *_Nullable themes, NSError *_Nullable error);
@interface KBMyVM : NSObject
@@ -30,6 +32,8 @@ typedef void(^KBDeleteUserCharacterCompletion)(BOOL success, NSError * _Nullable
/// 用户人设列表(/character/listByUser
- (void)fetchCharacterListByUserWithCompletion:(KBCharacterListCompletion)completion;
/// 已购买主题列表(/themes/purchased
- (void)fetchPurchasedThemesWithCompletion:(KBMyPurchasedThemesCompletion)completion;
/// 更新用户人设排序
- (void)updateUserCharacterSortWithSortArray:(NSArray<NSNumber *> *)sortArray
completion:(KBUpdateCharacterSortCompletion)completion;

View File

@@ -86,6 +86,34 @@ NSString * const KBUserCharacterDeletedNotification = @"KBUserCharacterDeletedNo
}];
}
- (void)fetchPurchasedThemesWithCompletion:(KBMyPurchasedThemesCompletion)completion {
[[KBNetworkManager shared] GET:API_THEME_PURCHASED
parameters:nil
headers:nil
autoShowBusinessError:NO
completion:^(NSDictionary *jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSString *msg = KBBizMessageFromJSONObject(jsonOrData) ?: error.localizedDescription ?: KBLocalized(@"Network error");
[KBHUD showInfo:msg];
if (completion) completion(nil, error);
return;
}
id dataObj = jsonOrData[KBData] ?: jsonOrData[@"data"];
if (![dataObj isKindOfClass:[NSArray class]]) {
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
code:KBNetworkErrorInvalidResponse
userInfo:@{NSLocalizedDescriptionKey: KBLocalized(@"Invalid response")}];
[KBHUD showInfo:e.localizedDescription];
if (completion) completion(nil, e);
return;
}
NSArray<KBMyTheme *> *themes = [KBMyTheme mj_objectArrayWithKeyValuesArray:(NSArray *)dataObj];
if (completion) completion(themes, nil);
}];
}
///
- (void)updateUserCharacterSortWithSortArray:(NSArray<NSNumber *> *)sortArray
completion:(KBUpdateCharacterSortCompletion)completion {