diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 38571c52..e37e8b13 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -499,6 +499,8 @@ 4C6E1F752CEAEC3C0073D0A3 /* ShoppingMallTagView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F742CEAEC3C0073D0A3 /* ShoppingMallTagView.m */; }; 4C6E1F792CEB12780073D0A3 /* UIView+GradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */; }; 4C6E1F7C2CEB25B10073D0A3 /* ShoppingMallItemPreview.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */; }; + 4CC6195A2CEC7770008C1EE8 /* MyDressingDataPresent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.m */; }; + 4CC6195D2CEC996E008C1EE8 /* MyDressingDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6195C2CEC996E008C1EE8 /* MyDressingDataModel.m */; }; 540EC1D02C89925F00F3BF0D /* GiftComboView.m in Sources */ = {isa = PBXBuildFile; fileRef = 540EC1CF2C89925F00F3BF0D /* GiftComboView.m */; }; 540EC1D32C89998500F3BF0D /* GiftComboManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 540EC1D22C89998500F3BF0D /* GiftComboManager.m */; }; 5412E0F42C4E460300FDD668 /* XPMineCenterAgencyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5412E0F32C4E460300FDD668 /* XPMineCenterAgencyView.m */; }; @@ -2584,6 +2586,10 @@ 4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+GradientLayer.m"; sourceTree = ""; }; 4C6E1F7A2CEB25B10073D0A3 /* ShoppingMallItemPreview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShoppingMallItemPreview.h; sourceTree = ""; }; 4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShoppingMallItemPreview.m; sourceTree = ""; }; + 4CC619582CEC7770008C1EE8 /* MyDressingDataPresent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyDressingDataPresent.h; sourceTree = ""; }; + 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyDressingDataPresent.m; sourceTree = ""; }; + 4CC6195B2CEC996E008C1EE8 /* MyDressingDataModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyDressingDataModel.h; sourceTree = ""; }; + 4CC6195C2CEC996E008C1EE8 /* MyDressingDataModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MyDressingDataModel.m; sourceTree = ""; }; 540EC1CE2C89925F00F3BF0D /* GiftComboView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiftComboView.h; sourceTree = ""; }; 540EC1CF2C89925F00F3BF0D /* GiftComboView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GiftComboView.m; sourceTree = ""; }; 540EC1D12C89998500F3BF0D /* GiftComboManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiftComboManager.h; sourceTree = ""; }; @@ -6600,8 +6606,12 @@ 54283CE22CE48884009729B5 /* ShoppingMall */ = { isa = PBXGroup; children = ( + 4CC6195B2CEC996E008C1EE8 /* MyDressingDataModel.h */, + 4CC6195C2CEC996E008C1EE8 /* MyDressingDataModel.m */, 54283CEC2CE48B97009729B5 /* ShoppingMallDataPresent.h */, 54283CED2CE48B97009729B5 /* ShoppingMallDataPresent.m */, + 4CC619582CEC7770008C1EE8 /* MyDressingDataPresent.h */, + 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.m */, 54283CE32CE48A69009729B5 /* ShoppingMallViewController.h */, 54283CE42CE48A69009729B5 /* ShoppingMallViewController.m */, 54283CE62CE48ABB009729B5 /* MyDressingViewController.h */, @@ -12284,6 +12294,7 @@ E84A2E992A52817E00D6AF8A /* XPIncomeRecordView.m in Sources */, E801274B27E327DA00BAC3F2 /* XPRoomPKTypeTableViewCell.m in Sources */, 2331C1B02A60F32D00E1D940 /* XPCandyTreeMoreView.m in Sources */, + 4CC6195D2CEC996E008C1EE8 /* MyDressingDataModel.m in Sources */, E8412FB02779CB4D006E1101 /* XPRoomSettingPresenter.m in Sources */, E87DF4B02A429B32009C1185 /* XPFirstRechargeView.m in Sources */, E878893C273A54C300BF1D57 /* Api+Gift.m in Sources */, @@ -12861,6 +12872,7 @@ 239D0FA82BFCB88D002977CE /* XPRoomBackContainerView.m in Sources */, 23D321DF2ADFCEB2006B259C /* PIRedPacketChooseTypeView.m in Sources */, E81AF32827F1EE69003B9E43 /* XPRoomPKPanelUserView.m in Sources */, + 4CC6195A2CEC7770008C1EE8 /* MyDressingDataPresent.m in Sources */, E84150BF27747BD300A7F548 /* Api+FirstRecharge.m in Sources */, E84B0E422727EE0A008818C6 /* XPRoomMessageHeaderView.m in Sources */, 238B37AC2AC55A2C00BFC9D5 /* TreasureFailryMessageModel.m in Sources */, diff --git a/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/Contents.json b/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/Contents.json new file mode 100644 index 00000000..fa9dd572 --- /dev/null +++ b/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "组 8240@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/组 8240@3x.png b/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/组 8240@3x.png new file mode 100644 index 00000000..13ff6a1f Binary files /dev/null and b/YuMi/Assets.xcassets/1.0.30/mall_item_not_used.imageset/组 8240@3x.png differ diff --git a/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/Contents.json b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/Contents.json new file mode 100644 index 00000000..bde95ce1 --- /dev/null +++ b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "矩形 2941@3x-2.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/矩形 2941@3x-2.png b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/矩形 2941@3x-2.png new file mode 100644 index 00000000..1cd22b44 Binary files /dev/null and b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_normal_bg.imageset/矩形 2941@3x-2.png differ diff --git a/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/Contents.json b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/Contents.json new file mode 100644 index 00000000..afa6fd50 --- /dev/null +++ b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "矩形 2941@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/矩形 2941@3x.png b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/矩形 2941@3x.png new file mode 100644 index 00000000..7c3bf742 Binary files /dev/null and b/YuMi/Assets.xcassets/1.0.30/mu_dressing_card_selected_bg.imageset/矩形 2941@3x.png differ diff --git a/YuMi/Assets.xcassets/RoomType/RoomType/Contents.json b/YuMi/Assets.xcassets/RoomType/RoomType/Contents.json deleted file mode 100644 index 73c00596..00000000 --- a/YuMi/Assets.xcassets/RoomType/RoomType/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/YuMi/Modules/ShoppingMall/MyDressingDataModel.h b/YuMi/Modules/ShoppingMall/MyDressingDataModel.h new file mode 100644 index 00000000..c769d772 --- /dev/null +++ b/YuMi/Modules/ShoppingMall/MyDressingDataModel.h @@ -0,0 +1,51 @@ +// +// MyDressingDataModel.h +// YuMi +// +// Created by P on 2024/11/19. +// + +#import "PIBaseModel.h" +#import "CarModel.h" +#import "NobleCardModel.h" +#import "NameplateModel.h" +#import "ChatBubbleModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MyDressingDataModel : PIBaseModel + +//dressId = 191; +//dressType = 0; +//effect = "https://image.pekolive.com/Vip1headdress.svga"; +//effectType = 2; +//expireDays = 44; +//expireTime = 1735812327000; +//hasExpired = 0; +//name = "VIP1\U982d\U98fe"; +//obtainWay = 1; +//pic = "https://image.pekolive.com/Vip1headdress.png"; +//used = 0; + +@property(nonatomic, assign) NSInteger id; +@property(nonatomic, assign) NSInteger dressId; +@property(nonatomic, assign) NSInteger dressType; +@property(nonatomic, copy) NSString *effect; +@property(nonatomic, assign) NSInteger effectType; +@property(nonatomic, assign) NSInteger expireDays; +@property(nonatomic, assign) NSInteger expireTime; +@property(nonatomic, assign) BOOL hasExpired; +@property(nonatomic, copy) NSString *name; +@property(nonatomic, assign) NSInteger obtainWay; // "获得方式,1-普通,2-活动" +@property(nonatomic, copy) NSString *pic; +@property(nonatomic, assign) NSInteger used; + +- (NSString *)expiredContent; + ++ (MyDressingDataModel *)modelFromVehicle:(CarModel *)model; ++ (MyDressingDataModel *)modelFromNameplate:(NameplateModel *)model; ++ (MyDressingDataModel *)modelFromNobelCard:(NobleCardModel *)model; ++ (MyDressingDataModel *)modelFromChatBubble:(ChatBubbleModel *)model; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/ShoppingMall/MyDressingDataModel.m b/YuMi/Modules/ShoppingMall/MyDressingDataModel.m new file mode 100644 index 00000000..77d56218 --- /dev/null +++ b/YuMi/Modules/ShoppingMall/MyDressingDataModel.m @@ -0,0 +1,77 @@ +// +// MyDressingDataModel.m +// YuMi +// +// Created by P on 2024/11/19. +// + +#import "MyDressingDataModel.h" + +@implementation MyDressingDataModel + +- (NSString *)expiredContent { + if (self.hasExpired) { + return YMLocalizedString(@"XPMineCarTableViewCell1"); + } else { + NSString *content = @""; + if (self.expireDays < 1) { + content = YMLocalizedString(@"1.0.30_text_13"); + } else { + content = [NSString stringWithFormat:YMLocalizedString(@"1.0.18_8"), @(self.expireDays)]; + } + return content; + } +} + ++ (MyDressingDataModel *)modelFromVehicle:(CarModel *)model { + MyDressingDataModel *myDressingVehicle = [[MyDressingDataModel alloc] init]; + myDressingVehicle.dressId = model.carID.integerValue; + myDressingVehicle.pic = model.pic; + myDressingVehicle.name = model.name; + myDressingVehicle.used = model.isUsed; + myDressingVehicle.expireDays = model.expireDate; + myDressingVehicle.hasExpired = model.status != 3; + myDressingVehicle.dressType = 1; + return myDressingVehicle; +} + ++ (MyDressingDataModel *)modelFromNameplate:(NameplateModel *)model { + MyDressingDataModel *myDressingNameplate = [[MyDressingDataModel alloc] init]; + myDressingNameplate.pic = model.nameplateImage; + myDressingNameplate.name = model.nameplateName; + myDressingNameplate.used = model.isUsing; + myDressingNameplate.expireTime = model.expireTime; + myDressingNameplate.hasExpired = model.isExpired; + myDressingNameplate.id = model.nId.integerValue; + myDressingNameplate.dressId = model.nameplateId; + myDressingNameplate.dressType = 2; + return myDressingNameplate; +} + ++ (MyDressingDataModel *)modelFromNobelCard:(NobleCardModel *)model { + MyDressingDataModel *myDressingNobrlCard = [[MyDressingDataModel alloc] init]; + myDressingNobrlCard.pic = model.pic; + myDressingNobrlCard.effect = model.pic; + myDressingNobrlCard.name = model.name; + myDressingNobrlCard.used = model.used; + myDressingNobrlCard.expireDays = model.expireDays; + myDressingNobrlCard.expireTime = model.expireTime.integerValue; + myDressingNobrlCard.hasExpired = model.hasExpired; + myDressingNobrlCard.dressId = model.cardId.integerValue; + myDressingNobrlCard.dressType = 3; + return myDressingNobrlCard; +} + ++ (MyDressingDataModel *)modelFromChatBubble:(ChatBubbleModel *)model { + MyDressingDataModel *myDressingBubble = [[MyDressingDataModel alloc] init]; + myDressingBubble.pic = model.bubbleUrl; + myDressingBubble.dressId = model.bubbleId.integerValue; + myDressingBubble.expireDays = model.expireDays; + myDressingBubble.name = model.name; + myDressingBubble.used = model.hasUsed; + myDressingBubble.hasExpired = model.hasExpired; + myDressingBubble.dressType = 4; + return myDressingBubble; +} + +@end diff --git a/YuMi/Modules/ShoppingMall/MyDressingDataPresent.h b/YuMi/Modules/ShoppingMall/MyDressingDataPresent.h new file mode 100644 index 00000000..4adf2631 --- /dev/null +++ b/YuMi/Modules/ShoppingMall/MyDressingDataPresent.h @@ -0,0 +1,51 @@ +// +// MyDressingDataPresent.h +// YuMi +// +// Created by P on 2024/11/19. +// + +#import "BaseMvpPresenter.h" +#import "CarModel.h" +#import "UserInfoModel.h" +#import "NobleCardModel.h" +#import "HeadwearModel.h" +#import "NameplateModel.h" +#import "ChatBubbleModel.h" +#import "MyDressingDataModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MyDressingDataPresent : BaseMvpPresenter + +- (void)loadVehicles:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure; + +- (void)loadNameplate:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure; + +- (void)loadRoomCard:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure; + +- (void)loadBubble:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure; + +- (void)loadMyDressingItems:(NSInteger)type + page:(NSInteger)page + success:(void(^)(NSArray *array, NSInteger type))success + failure:(void(^)(NSError *error))failure; + +- (void)useDressBy:(NSInteger)type + dressID:(NSInteger)dressID + success:(void(^)(UserInfoModel *userInfo))success + failure:(void(^)(NSError *error))failure; + +//- (void)reloadUserInfo:(void(^)(UserInfoModel *userInfo))success +// failure:(void(^)(NSError *error))failure; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/ShoppingMall/MyDressingDataPresent.m b/YuMi/Modules/ShoppingMall/MyDressingDataPresent.m new file mode 100644 index 00000000..350a5c17 --- /dev/null +++ b/YuMi/Modules/ShoppingMall/MyDressingDataPresent.m @@ -0,0 +1,152 @@ +// +// MyDressingDataPresent.m +// YuMi +// +// Created by P on 2024/11/19. +// + +#import "MyDressingDataPresent.h" +#import "Api+DressUp.h" + +@implementation MyDressingDataPresent + +- (void)loadHeadWears:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api headwearList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [HeadwearModel modelsWithArray:data.data]; + if (success) { + success(array); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + if (failure) { + failure([NSError errorWithDomain:msg code:code userInfo:nil]); + } + } showLoading:YES errorToast:YES] ticket:ticket uid:uid]; +} + +- (void)loadVehicles:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api carList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray * array = [CarModel modelsWithArray:data.data]; + if (success) { + success(array); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + if (failure) { + failure([NSError errorWithDomain:msg code:code userInfo:nil]); + } + } showLoading:YES errorToast:YES] ticket:ticket uid:uid]; +} + +- (void)loadNameplate:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api nameplateList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + if (success) { + NSArray *array = [NameplateModel modelsWithArray:data.data[@"nameplateList"]]; + success(array); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + + } showLoading:YES errorToast:YES] + ticket:ticket + uid:uid + page:@(page).stringValue + pageSize:@"2"]; +} + +- (void)loadRoomCard:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure { + NSString * uid = [AccountInfoStorage instance].getUid; + NSString * ticket = [AccountInfoStorage instance].getTicket; + [Api nobleCardList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + if (success) { + NSArray * array = [NobleCardModel modelsWithArray:data.data]; + success(array); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + + } showLoading:YES errorToast:YES] + ticket:ticket + uid:uid + page:@(page).stringValue + pageSize:@"2"]; +} + +- (void)loadBubble:(NSInteger)page + success:(void(^)(NSArray *array))success + failure:(void(^)(NSError *error))failure { + [Api chatBubbleList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + + if (success) { + NSArray *array = [ChatBubbleModel modelsWithArray:data.data]; + success(array); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + + } showLoading:YES errorToast:YES] page:@(page).stringValue pageSize:@"2"]; +} + +- (void)loadMyDressingItems:(NSInteger)type + page:(NSInteger)page + success:(void(^)(NSArray *array, NSInteger type))success + failure:(void(^)(NSError *error))failure { + [Api mineDressItems:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + if (success) { + NSArray *models = [MyDressingDataModel modelsWithArray:data.data]; + success(models, type); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + + } showLoading:YES errorToast:YES] + page:@(page).stringValue + pageSize:@"2" + dressType:@(type).stringValue]; +} + +- (void)useDressBy:(NSInteger)type + dressID:(NSInteger)dressID + success:(void(^)(UserInfoModel *userInfo))success + failure:(void(^)(NSError *error))failure { + @kWeakify(self); + [Api optDress:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + @kStrongify(self); + @kWeakify(self); + [self reloadUserInfo:^(UserInfoModel *userInfo) { + if (success) { + success(userInfo); + } + } failure:nil]; + } fail:^(NSInteger code, NSString * _Nullable msg) { + if (failure) { + failure([NSError errorWithDomain:msg code:code userInfo:nil]); + } + } showLoading:YES errorToast:YES] + dressType:@(type).stringValue + dressId:@(dressID).stringValue]; +} + +- (void)reloadUserInfo:(void(^)(UserInfoModel *userInfo))success + failure:(void(^)(NSError *error))failure { + NSString * uid = [[AccountInfoStorage instance] getUid]; + if (uid.length == 0) { + return; + } + @kWeakify(self); + [Api getUserInfo:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + @kStrongify(self); + if (success) { + UserInfoModel * infoModel = [UserInfoModel modelWithDictionary:data.data]; + success(infoModel); + } + } fail:nil showLoading:YES errorToast:YES] uid:uid]; +} + +@end diff --git a/YuMi/Modules/ShoppingMall/MyDressingViewController.m b/YuMi/Modules/ShoppingMall/MyDressingViewController.m index ee9d4e4d..10859aa6 100644 --- a/YuMi/Modules/ShoppingMall/MyDressingViewController.m +++ b/YuMi/Modules/ShoppingMall/MyDressingViewController.m @@ -6,26 +6,448 @@ // #import "MyDressingViewController.h" +#import +#import +#import "UserInfoModel.h" +#import "MyDressingDataPresent.h" +#import "ShoppingMallItemPreview.h" +#import "XPSkillCardPlayerManager.h" +#import "ShoppingMallCategoryListView.h" + +static NSArray *> *MyDressUpOptions(void) { + return @[ + @{YMLocalizedString(@"XPMineDressUpViewController2") : @1}, // 座驾 + @{YMLocalizedString(@"XPMineDressUpViewController1") : @0}, // 头饰 + @{YMLocalizedString(@"XPMineDressUpViewController3") : @2}, // 铭牌 + @{YMLocalizedString(@"XPMineDressUpViewController4") : @3}, // 资料卡 + @{YMLocalizedString(@"XPMineDressUpViewController5") : @4}, // 聊天气泡 + @{YMLocalizedString(@"1.0.30_text_9") : @5} // 個人頁裝飾 + ]; +} @interface MyDressingViewController () +@property(nonatomic, strong) UserInfoModel *userInfo; + +@property(nonatomic, strong) NetImageView *avatarView; +@property(nonatomic, strong) NetImageView *avatarHeadViewImageView; +@property(nonatomic, strong) SVGAImageView *avatarHeadWearSVGA; + +@property (nonatomic, strong) UIView *playEffectMask; +@property (nonatomic, strong) VAPView *mp4Effect; +@property (nonatomic, strong) SVGAImageView *svgaEffect; +@property(nonatomic, strong) UIActivityIndicatorView *loading; + +@property(nonatomic, strong) MyDressingDataModel *selectedModel; + @end @implementation MyDressingViewController +- (MyDressingDataPresent *)createPresenter { + return [[MyDressingDataPresent alloc] init]; +} + +- (BOOL)isHiddenNavBar { + return YES; +} + - (void)viewDidLoad { [super viewDidLoad]; - // Do any additional setup after loading the view. + + self.userInfo = [XPSkillCardPlayerManager shareInstance].userInfoModel; + + [self setupUI]; + [self updateAvatar]; } -/* -#pragma mark - Navigation - -// In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { - // Get the new view controller using [segue destinationViewController]. - // Pass the selected object to the new view controller. +- (void)setupUI { + [self setupBackground]; + [self setupNavigationBar]; + [self setupAvatar]; + [self setupContentList]; +} + +- (void)setupBackground { + self.view.backgroundColor = UIColorFromRGB(0x02061D); + UIImageView *topBG = [[UIImageView alloc] initWithImage:kImage(@"mall_top_bg")]; + [self.view addSubview:topBG]; + [topBG mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.leading.trailing.mas_equalTo(self.view); + make.height.mas_equalTo(kGetScaleWidth(200)); + }]; +} + +- (void)setupNavigationBar { + UILabel *titleLabel = [self titleLabel]; + UIButton *backButton = [self backButton]; + [self.view addSubview:titleLabel]; + [self.view addSubview:backButton]; + + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(self.view).offset(44 + 11); + make.height.mas_equalTo(22); + }]; + + [backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.view).offset(16); + make.centerY.mas_equalTo(titleLabel); + make.size.mas_equalTo(CGSizeMake(22, 22)); + }]; +} + +- (void)setupAvatar { + [self.view addSubview:self.avatarView]; + [self.avatarView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(100); + make.centerX.mas_equalTo(self.view); + make.size.mas_equalTo(CGSizeMake(73, 73)); + }]; + + [self.view addSubview:self.avatarHeadViewImageView]; + [self.avatarHeadViewImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.avatarView); + make.size.mas_equalTo(self.avatarView).multipliedBy(1.3); + }]; + + [self.view addSubview:self.avatarHeadWearSVGA]; + [self.avatarHeadWearSVGA mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.avatarView); + make.size.mas_equalTo(self.avatarView).multipliedBy(1.3); + }]; +} + +- (void)setupContentList { + NSInteger bottom = kSafeAreaBottomHeight; + // 内部列表使用 frame 布局,这里要计算 height + ShoppingMallCategoryListView *listView = [[ShoppingMallCategoryListView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight - 100 - 73)]; + listView.isForMyDressingPage = YES; + listView.bottomSpace = bottom; + [self.view addSubview:listView]; + [listView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.avatarView.mas_bottom).offset(14); + make.leading.trailing.bottom.mas_equalTo(self.view); + }]; + @kWeakify(self); + listView.fetchDataForMyDressingPage = ^(NSInteger pageIndex, NSInteger pageNum, FetchDataForMyDressingCompletion _Nonnull completion) { + @kStrongify(self); + [self fetchDataForPage:pageIndex + pageNum:pageNum + completion:completion]; + }; + listView.didTapItemPlay = ^(NSString * _Nonnull resourcePath) { + @kStrongify(self); + [self playItemEffect:resourcePath]; + }; + listView.returnMyDressingSelectedModel = ^(MyDressingDataModel * _Nonnull model, NSInteger type) { + @kStrongify(self); + [self handTapItem:model type:type]; + }; + + listView.items = MyDressUpOptions(); +} + +- (void)updateAvatar { + self.avatarView.imageUrl = self.userInfo.avatar; + if ([NSString isEmpty:self.userInfo.headwearEffect]) { + [self.avatarHeadWearSVGA stopAnimation]; + self.avatarHeadWearSVGA.hidden = YES; + } else { + if ([self.userInfo.headwearEffect.lowercaseString hasSuffix:@"svga"]) { + self.avatarHeadWearSVGA.hidden = NO; + self.avatarHeadViewImageView.hidden = YES; + SVGAParser *p = [[SVGAParser alloc] init]; + [p parseWithURL:[NSURL URLWithString:self.userInfo.headwearEffect] + completionBlock:^(SVGAVideoEntity * _Nullable videoItem) { + self.avatarHeadWearSVGA.videoItem = videoItem; + [self.avatarHeadWearSVGA startAnimation]; + self.avatarHeadWearSVGA.hidden = NO; + } failureBlock:^(NSError * _Nullable error) {}]; + } else { + self.avatarHeadWearSVGA.hidden = YES; + self.avatarHeadViewImageView.hidden = NO; + self.avatarHeadViewImageView.imageUrl = self.userInfo.headwearEffect; + } + } +} + +#pragma mark - +- (void)fetchDataForPage:(NSInteger)pageIndex + pageNum:(NSInteger)pageNum + completion:(FetchDataForMyDressingCompletion)completion { + switch (pageIndex) { + case 0: { + [self.presenter loadMyDressingItems:0 + page:pageNum + success:^(NSArray * _Nonnull array, NSInteger type) { + if (completion) { + completion(array); + } + } failure:^(NSError * _Nonnull error) { + + }]; + } + break; + case 1: { + [self.presenter loadVehicles:^(NSArray * _Nonnull array) { + if (completion) { + NSMutableArray *transArray = @[].mutableCopy; + for (CarModel *car in array) { + MyDressingDataModel *model = [MyDressingDataModel modelFromVehicle:car]; + [transArray addObject:model]; + } + completion(transArray); + } + } failure:^(NSError * _Nonnull error) { }]; + } + break; + case 2: { + [self.presenter loadNameplate:pageNum + success:^(NSArray * _Nonnull array) { + if (completion) { + NSMutableArray *transArray = @[].mutableCopy; + for (NameplateModel *nameplate in array) { + MyDressingDataModel *model = [MyDressingDataModel modelFromNameplate:nameplate]; + [transArray addObject:model]; + } + completion(transArray); + } + } failure:^(NSError * _Nonnull error) { + + }]; + } + break; + case 3: { + [self.presenter loadRoomCard:pageNum + success:^(NSArray * _Nonnull array) { + if (completion) { + NSMutableArray *transArray = @[].mutableCopy; + for (NobleCardModel *nobleCard in array) { + MyDressingDataModel *model = [MyDressingDataModel modelFromNobelCard:nobleCard]; + [transArray addObject:model]; + } + completion(transArray); + } + } failure:^(NSError * _Nonnull error) { + + }]; + } + break; + case 4: { + [self.presenter loadBubble:pageNum + success:^(NSArray * _Nonnull array) { + if (completion) { + NSMutableArray *transArray = @[].mutableCopy; + for (ChatBubbleModel *bubble in array) { + MyDressingDataModel *model = [MyDressingDataModel modelFromChatBubble:bubble]; + [transArray addObject:model]; + } + completion(transArray); + } + } failure:^(NSError * _Nonnull error) { + + }]; + } + break; + case 5: { + [self.presenter loadMyDressingItems:5 + page:pageNum + success:^(NSArray * _Nonnull array, NSInteger type) { + if (completion) { + completion(array); + } + } failure:^(NSError * _Nonnull error) { + + }]; + } + break; + default: + break; + } +} + +- (void)handTapItem:(MyDressingDataModel *)model type:(NSInteger)type { + + if (model.hasExpired) { + // 弹窗购买 + ShoppingMallItemPreview *preview = [[ShoppingMallItemPreview alloc] initWithMyDress:model + isVaild:model.obtainWay<=1]; + preview.frame = CGRectMake(0, 0, 284, 353); + [TTPopup popupView:preview style:TTPopupStyleAlert]; +// @kWeakify(self); +// [preview setBuyWith:^(DressUpShopModel * _Nonnull model) { +// @kStrongify(self); +// @kWeakify(self); +// [self.presenter buyItem:model.dressUpId +// success:^(id _Nonnull obj) { +// @kStrongify(self); +// [TTPopup dismiss]; +// [self showSuccessToast:YMLocalizedString(@"XPDressUpShopListViewController0")]; +// } failure:^(NSError * _Nonnull error) { +// // @kStrongify(self); +// // [self showErrorToast:error.localizedDescription]; +// }]; +// }]; + } else { + // 直接使用 + NSInteger dressID = 0; + if (model) { + dressID = model.dressId; + } + @kWeakify(self); + [self.presenter useDressBy:type + dressID:dressID + success:^(UserInfoModel *userInfo){ + @kStrongify(self); + self.userInfo = userInfo; + [XPSkillCardPlayerManager shareInstance].userInfoModel = userInfo; + [self updateAvatar]; + // TODO: 更新列表的选中状态 + } failure:^(NSError * _Nonnull error) { + + }]; + } +} + +#pragma mark - +- (void)didTapBack { + [self.navigationController popViewControllerAnimated:YES]; +} + +#pragma mark - +- (void)playItemEffect:(NSString *)path { + if (!_playEffectMask) { + [self.view addSubview:self.playEffectMask]; + [self.playEffectMask mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.view); + }]; + + [self.playEffectMask addSubview:self.svgaEffect]; + [self.svgaEffect mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.playEffectMask).insets(UIEdgeInsetsMake(0, 0, 0, 0)); + }]; + } + self.playEffectMask.hidden = NO; + [self.loading startAnimating]; + + if ([path.lowercaseString hasSuffix:@"svga"]) { + @kWeakify(self); + SVGAParser *p = [[SVGAParser alloc] init]; + [p parseWithURL:[NSURL URLWithString:path] + completionBlock:^(SVGAVideoEntity * _Nullable videoItem) { + @kStrongify(self); + if (!self.playEffectMask.hidden) { + [self.loading stopAnimating]; + self.svgaEffect.hidden = NO; + self.svgaEffect.videoItem = videoItem; + [self.svgaEffect startAnimation]; + } + } failureBlock:^(NSError * _Nullable error) { + @kStrongify(self); + [self stopItemSVGAEffect]; + }]; + } else if ([path.lowercaseString hasSuffix:@"mp4"]) { + + } +} + +- (void)stopItemSVGAEffect { + [self.loading stopAnimating]; + [self.svgaEffect stopAnimation]; + self.svgaEffect.hidden = YES; + self.playEffectMask.hidden = YES; +} + +#pragma mark - +- (UIButton *)backButton { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b setImage:[kImage(@"vip_center_back_button") ms_SetImageForRTL] + forState:UIControlStateNormal]; + [b addTarget:self + action:@selector(didTapBack) + forControlEvents:UIControlEventTouchUpInside]; + return b; +} + +- (UILabel *)titleLabel { + UILabel *label = [[UILabel alloc] init]; + label.textAlignment = NSTextAlignmentCenter; + label.font = kFontMedium(17); + label.text = YMLocalizedString(@"1.0.30_text_8"); + label.textColor = UIColorFromRGB(0xD9E7F7); + return label; +} + +- (UIView *)playEffectMask { + if (!_playEffectMask) { + _playEffectMask = [[UIView alloc] initWithFrame:self.view.bounds]; + _playEffectMask.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5f]; + [_playEffectMask addSubview:self.loading]; + [self.loading mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(_playEffectMask); + }]; + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stopItemSVGAEffect)]; + [_playEffectMask addGestureRecognizer:tap]; + } + return _playEffectMask; +} + +- (SVGAImageView *)svgaEffect { + if (!_svgaEffect) { + _svgaEffect = [[SVGAImageView alloc] init]; + _svgaEffect.contentMode = UIViewContentModeScaleAspectFit; + _svgaEffect.autoPlay = YES; + _svgaEffect.loops = 0; + _svgaEffect.clearsAfterStop = YES; + _svgaEffect.hidden = YES; + _svgaEffect.userInteractionEnabled = YES; + } + return _svgaEffect; +} + +- (UIActivityIndicatorView *)loading { + if (!_loading) { + UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + indicator.translatesAutoresizingMaskIntoConstraints = NO; + indicator.hidesWhenStopped = YES; + _loading = indicator; + } + return _loading; +} + +- (NetImageView *)avatarHeadViewImageView { + if (!_avatarHeadViewImageView) { + _avatarHeadViewImageView = [[NetImageView alloc] init]; + _avatarHeadViewImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _avatarHeadViewImageView; +} + +- (NetImageView *)avatarView { + if (!_avatarView) { + NetImageConfig * config = [[NetImageConfig alloc]init]; + config.imageType = ImageTypeUserIcon; + config.placeHolder = [UIImageConstant defaultAvatarPlaceholder]; + _avatarView = [[NetImageView alloc] initWithConfig:config]; + [_avatarView setCornerRadius:73/2 + corners:kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner | kCALayerMinXMaxYCorner | kCALayerMaxXMaxYCorner + borderWidth:2 + borderColor:UIColorFromRGB(0xFBD99A)]; + } + return _avatarView; +} + +- (SVGAImageView *)avatarHeadWearSVGA { + if (!_avatarHeadWearSVGA) { + _avatarHeadWearSVGA = [[SVGAImageView alloc] init]; + _avatarHeadWearSVGA.contentMode = UIViewContentModeScaleAspectFit; + _avatarHeadWearSVGA.autoPlay = YES; + _avatarHeadWearSVGA.loops = 0; + _avatarHeadWearSVGA.clearsAfterStop = YES; + } + return _avatarHeadWearSVGA; } -*/ @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.h b/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.h index 78ba1092..5f6e4bf2 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.h +++ b/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.h @@ -8,21 +8,29 @@ #import #import "DressUpShopModel.h" +#import "MyDressingDataModel.h" NS_ASSUME_NONNULL_BEGIN typedef void (^DidTapPlay)(NSString *resourcePath); + typedef void (^FetchDataCompletion)(NSArray * modelList); typedef void (^FetchDataForPage)(NSInteger pageIndex, FetchDataCompletion completion); - +typedef void (^FetchDataForMyDressingCompletion)(NSArray * modelList); +typedef void (^FetchDataForMyDressingPage)(NSInteger pageIndex, NSInteger pageNum, FetchDataForMyDressingCompletion completion); @interface ShoppingMallCategoryListView : UIView -// 名称:类型 +@property(nonatomic, assign) CGFloat bottomSpace; +@property(nonatomic, assign) CGFloat isForMyDressingPage; + +/// 每个 category 的定义,{名称:类型} @property (nonatomic, copy) NSArray *> *items; @property (nonatomic, copy) FetchDataForPage fetchDataForPage; +@property(nonatomic, copy) FetchDataForMyDressingPage fetchDataForMyDressingPage; @property (nonatomic, copy) DidTapPlay didTapItemPlay; @property(nonatomic, copy) void(^returnSelectedModel)(DressUpShopModel * _Nullable model); +@property(nonatomic, copy) void(^returnMyDressingSelectedModel)(MyDressingDataModel * _Nullable model, NSInteger type); @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.m b/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.m index ada8fbba..86ec79a5 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.m +++ b/YuMi/Modules/ShoppingMall/ShoppingMallCategoryListView.m @@ -7,7 +7,10 @@ #import "ShoppingMallCategoryListView.h" +#import +#import "MyDressingDataModel.h" #import "ShoppingMallTagView.h" +#import "XPRoomGiftAnimationParser.h" @interface ShoppingMallEmptyCard : UICollectionViewCell @@ -55,13 +58,273 @@ @end +@interface ShoppingMallRoomCardView : UIView + +@property(nonatomic, copy) NSString *imagePath; +@property(nonatomic, strong) NetImageView *imageView; + +@end + +@implementation ShoppingMallRoomCardView + +- (instancetype)init { + if (self = [super init]) { + self.backgroundColor = [UIColor whiteColor]; + + self.imageView = [[NetImageView alloc] init]; + self.imageView.contentMode = UIViewContentModeScaleAspectFill; + [self addSubview:self.imageView]; + [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(-6); + make.leading.trailing.mas_equalTo(self); + make.height.mas_equalTo(30); + }]; + + [self setCornerRadius:8]; + } + return self; +} + +- (void)setImagePath:(NSString *)imagePath { + _imagePath = imagePath; + self.imageView.imageUrl = imagePath; +} + +@end + +@interface MyDressingItemCard : UICollectionViewCell + +@property(nonatomic, strong) MyDressingDataModel *model; + +@property(nonatomic, strong) VAPView *mp4View; +@property(nonatomic, strong) XPRoomGiftAnimationParser *vapParser; +@property (nonatomic, strong) UIImageView *bgImageView; +@property (nonatomic, strong) UIView *itemBGView; +@property (nonatomic, strong) NetImageView *itemImageView; +@property(nonatomic, strong) ShoppingMallRoomCardView *roomCardView; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIButton *playButton; +@property (nonatomic, strong) ShoppingMallTagView *statusLabel; +@property (nonatomic, copy) DidTapPlay didTapPlay; +@end + +@implementation MyDressingItemCard + +- (void)dealloc +{ + [self.mp4View stopHWDMP4]; + [self.mp4View removeFromSuperview]; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + [self.mp4View stopHWDMP4]; +} + +- (void)setSelected:(BOOL)selected { + self.bgImageView.image = selected ? kImage(@"mu_dressing_card_selected_bg") : kImage(@"mu_dressing_card_normal_bg") ; +} + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + self.backgroundColor = [UIColor clearColor]; + + [self.contentView addSubview:self.bgImageView]; + [self.bgImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; + + [self.contentView addSubview:self.itemBGView]; + [self.itemBGView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.leading.trailing.mas_equalTo(self.contentView).inset(9); + make.height.mas_equalTo(self.itemBGView.mas_width); + }]; + + [self.contentView addSubview:self.itemImageView]; + [self.itemImageView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.itemBGView); + make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.8f); + }]; + + [self.contentView addSubview:self.mp4View]; + [self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.itemBGView); + make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.8f); + }]; + + [self.contentView addSubview:self.roomCardView]; + [self.roomCardView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.centerX.mas_equalTo(self.itemBGView); + make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.8f); + }]; + + [self.contentView addSubview:self.playButton]; + [self.playButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.bottom.trailing.mas_equalTo(self.itemBGView).offset(-4); + make.size.mas_equalTo(CGSizeMake(26, 22)); + }]; + + [self.contentView addSubview:self.titleLabel]; + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.itemBGView); + make.top.mas_equalTo(self.itemBGView.mas_bottom).offset(5); + make.height.mas_equalTo(20); + }]; + + [self.contentView addSubview:self.statusLabel]; + [self.statusLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.leading.mas_equalTo(self.bgImageView).offset(1); + make.width.mas_equalTo(50); + make.height.mas_equalTo(22); + }]; + } + return self; +} + +- (void)setModel:(MyDressingDataModel *)model { + _model = model; + if (model) { + self.titleLabel.text = model.name; + + if (model.dressType == 3) { + [self play:model.effect]; + self.playButton.hidden = YES; + self.itemImageView.hidden = YES; + } else { + self.playButton.hidden = !([model.effect.lowercaseString hasSuffix:@"svga"] || [model.effect.lowercaseString hasSuffix:@"mp4"]); + self.itemImageView.imageUrl = model.pic; + } + + if (model.hasExpired) { + [self.statusLabel updateBackgroundColors:@[UIColorFromRGB(0xC1CDDB)] textColor:UIColorFromRGB(0x2F3450)]; + } else { + [self.statusLabel updateBackgroundColors:@[UIColorFromRGB(0xA1CAFD)] textColor:UIColorFromRGB(0x172055)]; + } + self.statusLabel.text = [model expiredContent]; + [self.statusLabel mas_updateConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo([self.statusLabel textWidth]); + }]; + [self layoutIfNeeded]; + } else { + self.playButton.hidden = YES; + self.itemImageView.image = kImage(@"mall_item_not_used"); + self.titleLabel.text = YMLocalizedString(@"1.0.30_text_12"); + } +} + +- (void)play:(NSString *)effect { + NSString *encodingUrl = [effect stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet]; + @kWeakify(self); + [self.vapParser parseWithURL:[encodingUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]] completionBlock:^(NSString * _Nullable videoUrl) { + @kStrongify(self); + if (videoUrl.length) { + [self.mp4View setMute:YES]; + [self.mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:self]; + } + } failureBlock:^(NSError * _Nullable error) { + }]; +} + +- (void)handleTapPlay:(id)sender { + if (_didTapPlay) { + self.didTapPlay(self.model.effect); + } +} + +#pragma mark - HWDMP4PlayDelegate +//即将开始播放时询问,true马上开始播放,false放弃播放 +- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config { + return YES; +} + +#pragma mark - +- (UIImageView *)bgImageView { + if (!_bgImageView) { + _bgImageView = [[UIImageView alloc] initWithImage:kImage(@"mu_dressing_card_normal_bg")]; + } + return _bgImageView; +} + +- (UIView *)itemBGView { + if (!_itemBGView) { + _itemBGView = [[UIView alloc] init]; + _itemBGView.backgroundColor = UIColorFromRGB(0x04184A); + [_itemBGView setCornerRadius:6]; + } + + return _itemBGView; +} + +- (NetImageView *)itemImageView { + if (!_itemImageView) { + _itemImageView = [[NetImageView alloc] init]; + _itemImageView.contentMode = UIViewContentModeScaleAspectFit; + } + return _itemImageView; +} + +- (ShoppingMallRoomCardView *)roomCardView { + if (!_roomCardView) { + _roomCardView = [[ShoppingMallRoomCardView alloc] init]; + _roomCardView.hidden = YES; + } + return _roomCardView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [UILabel labelInitWithText:@"" + font:kFontMedium(14) + textColor:UIColorFromRGB(0xD9E7F7)]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UIButton *)playButton { + if (!_playButton) { + _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_playButton setImage:kImage(@"mall_play_icon") forState:UIControlStateNormal]; + [_playButton addTarget:self + action:@selector(handleTapPlay:) + forControlEvents:UIControlEventTouchUpInside]; + } + return _playButton; +} + +- (ShoppingMallTagView *)statusLabel { + if (!_statusLabel) { + _statusLabel = [[ShoppingMallTagView alloc] init]; + } + return _statusLabel; +} + +- (XPRoomGiftAnimationParser *)vapParser { + if (!_vapParser) { + _vapParser = [[XPRoomGiftAnimationParser alloc] init]; + } + return _vapParser; +} + +- (VAPView *)mp4View { + if (!_mp4View) { + _mp4View = [[VAPView alloc] init]; + _mp4View.contentMode = UIViewContentModeScaleAspectFill; + } + return _mp4View; +} + +@end + @interface ShoppingMallItemCard : UICollectionViewCell +@property (nonatomic, strong) DressUpShopModel *cellModel; + @property (nonatomic, strong) UIImageView *bgImageView; @property (nonatomic, strong) UIView *itemBGView; @property (nonatomic, strong) NetImageView *itemImageView; +@property(nonatomic, strong) ShoppingMallRoomCardView *roomCardView; @property (nonatomic, strong) UILabel *titleLabel; -@property (nonatomic, strong) DressUpShopModel *cellModel; @property (nonatomic, strong) UIButton *playButton; @property (nonatomic, strong) UILabel *pricePerDayLabel; @property (nonatomic, strong) UILabel *description_1_label; @@ -70,8 +333,6 @@ @property (nonatomic, copy) DidTapPlay didTapPlay; -@property (nonatomic, copy) DidTapPlay didTapPlay; - @end @implementation ShoppingMallItemCard @@ -87,14 +348,20 @@ [self.contentView addSubview:self.itemBGView]; [self.itemBGView mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.leading.trailing.mas_equalTo(self.contentView).inset(15); + make.top.leading.trailing.mas_equalTo(self.contentView).inset(9); make.height.mas_equalTo(self.itemBGView.mas_width); }]; [self.contentView addSubview:self.itemImageView]; - [self.itemImageView mas_makeConstraints:^(MASConstraintMaker *make) { + [self.itemImageView mas_remakeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(self.itemBGView); - make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.7f); + make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.8f); + }]; + + [self.contentView addSubview:self.roomCardView]; + [self.roomCardView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.top.centerX.mas_equalTo(self.itemBGView); + make.width.height.mas_equalTo(self.itemBGView.mas_width).multipliedBy(0.8f); }]; [self.contentView addSubview:self.playButton]; @@ -143,35 +410,53 @@ - (void)setCellModel:(DressUpShopModel *)cellModel { _cellModel = cellModel; - self.titleLabel.text = cellModel.name; - self.itemImageView.imageUrl = cellModel.pic; - if (cellModel.vipLevel > 0) { - self.pricePerDayLabel.attributedText = [cellModel pricePerDayForVIP]; + + if (cellModel.dressType == 3) { + self.itemImageView.hidden = YES; + self.roomCardView.hidden = NO; + self.roomCardView.imagePath = cellModel.pic; } else { - self.pricePerDayLabel.attributedText = [cellModel pricePerDay]; + self.itemImageView.hidden = NO; + self.roomCardView.hidden = YES; + self.itemImageView.imageUrl = cellModel.pic; } - if (cellModel.obtainWay == 1) { - self.pricePerDayLabel.hidden = NO; - self.description_1_label.hidden = NO; - self.description_2_label.hidden = YES; - self.description_1_label.text = YMLocalizedString(@"1.0.30_text_1"); - } else { + self.titleLabel.text = cellModel.name; + self.pricePerDayLabel.attributedText = [cellModel generateAttributedStringWithIncludeOriginalPrice:YES]; + + if (cellModel.obtainWay > 1) { self.pricePerDayLabel.hidden = YES; self.description_1_label.hidden = YES; self.description_2_label.hidden = NO; self.description_2_label.text = YMLocalizedString(@"1.0.30_text_2"); + } else { + self.pricePerDayLabel.hidden = NO; + self.description_1_label.hidden = NO; + self.description_2_label.hidden = YES; + if (cellModel.vipLevel == 0) { + self.description_1_label.text = YMLocalizedString(@"1.0.30_text_1"); + } else { + self.description_1_label.text = [NSString stringWithFormat:YMLocalizedString(@"1.0.30_text_10"), @(cellModel.vipLevel), @(cellModel.discount)]; + } } - self.statusLabel.text = YMLocalizedString(@"1.0.30_text_4"); - self.statusLabel.hidden = (cellModel.dressLimitStatus == 0); - - [self.statusLabel mas_updateConstraints:^(MASConstraintMaker *make) { - make.width.mas_equalTo([self.statusLabel textWidth]); - }]; - [self.statusLabel layoutIfNeeded]; - self.playButton.hidden = !([cellModel.effect.lowercaseString hasSuffix:@"svga"] || [cellModel.effect.lowercaseString hasSuffix:@"mp4"]); + + [self.titleLabel mas_updateConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(self.itemBGView.mas_bottom).offset(5 + (cellModel.obtainWay > 1 ? 5 : 0)); + }]; + + if (cellModel.dressLimitStatus == 0) { + self.statusLabel.text = YMLocalizedString(@"1.0.30_text_4"); + self.statusLabel.hidden = NO; + [self.statusLabel mas_updateConstraints:^(MASConstraintMaker *make) { + make.width.mas_equalTo([self.statusLabel textWidth]); + }]; + } else { + self.statusLabel.hidden = YES; + } + + [self layoutIfNeeded]; } - (void)handleTapPlay:(id)sender { @@ -210,6 +495,13 @@ return _itemImageView; } +- (ShoppingMallRoomCardView *)roomCardView { + if (!_roomCardView) { + _roomCardView = [[ShoppingMallRoomCardView alloc] init]; + } + return _roomCardView; +} + - (UILabel *)titleLabel { if (!_titleLabel) { _titleLabel = [UILabel labelInitWithText:@"" @@ -261,22 +553,21 @@ _description_2_label.numberOfLines = 0; [_description_2_label setCornerRadius:11 cornerMask:kCALayerMinXMaxYCorner | kCALayerMaxXMaxYCorner]; - -#if DEBUG - _description_2_label.alpha = 0.3; -#endif } return _description_2_label; } - (ShoppingMallTagView *)statusLabel { if (!_statusLabel) { - // TODO: 需要单独处理 - _statusLabel = [[ShoppingMallTagView alloc] init]; + _statusLabel = [[ShoppingMallTagView alloc] initWithBackgroundColors:@[UIColorFromRGB(0xE29030), UIColorFromRGB(0xFCC074)] + font:kFontMedium(12) + textColor:UIColorFromRGB(0x51281B)]; } return _statusLabel; } + + @end @interface ShoppingMallCategoryCard : UIView @@ -367,14 +658,15 @@ @end @interface ShoppingMallCategoryListView () -@property (nonatomic, strong) UIScrollView *container1ScrollView; -@property (nonatomic, strong) UIScrollView *container2ScrollView; -@property (nonatomic, strong) NSMutableArray *itemViews1; -@property (nonatomic, strong) NSMutableArray *itemViews2; -@property (nonatomic, strong) NSMutableDictionary*> *dataCache; // 缓存每页数据 -@property (nonatomic, strong) NSMutableSet *requestedPages; // 记录已经请求的数据页 +@property (nonatomic, strong) UIScrollView *shoppoingMallCategoryScrollView; +@property (nonatomic, strong) UIScrollView *mallItemsScrollView; +@property (nonatomic, strong) NSMutableArray *categoryCardArray; +@property (nonatomic, strong) NSMutableArray *itemCollectionViewArray; +@property (nonatomic, strong) NSMutableDictionary*> *dataCache; // 缓存每页数据 - 商城页 +@property (nonatomic, strong) NSMutableDictionary*> *myDressingDataCache; // 缓存每页数据 - 我的装扮页 +@property (nonatomic, strong) NSMutableSet *requestedPages; // 记录已经请求的数据页, 通过下标判断 @property (nonatomic, strong) NSIndexPath *selectedIndexPath; - +@property(nonatomic, strong) NSMutableArray *myDressingDataPagesNumbers; //缓存我的装扮页每页的当前 API 分页 @end @implementation ShoppingMallCategoryListView @@ -382,8 +674,6 @@ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setupUI]; - -// [self loadDataForPageAtIndex:0]; } return self; } @@ -398,28 +688,30 @@ - (void)setupUI { self.backgroundColor = [UIColor clearColor]; self.dataCache = @{}.mutableCopy; + self.myDressingDataCache = @{}.mutableCopy; + self.myDressingDataPagesNumbers = @[].mutableCopy; self.requestedPages = [NSMutableSet set]; // 初始化请求记录 - self.container2ScrollView.delegate = self; // 设置代理 + self.mallItemsScrollView.delegate = self; // 设置代理 CGFloat screenWidth = KScreenWidth; CGFloat screenHeight = self.bounds.size.height; // 容器-1 (顶部) - self.container1ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(15, 0, screenWidth-15, 90)]; - self.container1ScrollView.contentInset = UIEdgeInsetsMake(0, 15, 0, 15); - self.container1ScrollView.showsHorizontalScrollIndicator = NO; - self.container1ScrollView.clipsToBounds = NO; - [self addSubview:self.container1ScrollView]; + self.shoppoingMallCategoryScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(15, 0, screenWidth-15, 90)]; + self.shoppoingMallCategoryScrollView.contentInset = UIEdgeInsetsMake(0, 15, 0, 15); + self.shoppoingMallCategoryScrollView.showsHorizontalScrollIndicator = NO; + self.shoppoingMallCategoryScrollView.clipsToBounds = NO; + [self addSubview:self.shoppoingMallCategoryScrollView]; // 容器-2 (底部) - self.container2ScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, screenWidth, screenHeight - 100)]; - self.container2ScrollView.pagingEnabled = YES; - self.container2ScrollView.delegate = self; - self.container2ScrollView.showsHorizontalScrollIndicator = NO; - [self addSubview:self.container2ScrollView]; + self.mallItemsScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 100, screenWidth, screenHeight - 100)]; + self.mallItemsScrollView.pagingEnabled = YES; + self.mallItemsScrollView.delegate = self; + self.mallItemsScrollView.showsHorizontalScrollIndicator = NO; + [self addSubview:self.mallItemsScrollView]; - self.itemViews1 = [NSMutableArray array]; - self.itemViews2 = [NSMutableArray array]; + self.categoryCardArray = [NSMutableArray array]; + self.itemCollectionViewArray = [NSMutableArray array]; } - (void)setItems:(NSArray *)items { @@ -431,8 +723,8 @@ CGFloat container1ItemSpacing = 12; // 设置 container1 和 container2 的内容大小 - self.container1ScrollView.contentSize = CGSizeMake(items.count * (container1ItemWidth + container1ItemSpacing), 90); - self.container2ScrollView.contentSize = CGSizeMake(items.count * screenWidth, self.container2ScrollView.frame.size.height); + self.shoppoingMallCategoryScrollView.contentSize = CGSizeMake(items.count * (container1ItemWidth + container1ItemSpacing), 90); + self.mallItemsScrollView.contentSize = CGSizeMake(items.count * screenWidth, self.mallItemsScrollView.frame.size.height); // 添加 item view-1 到 container1ScrollView for (int i = 0; i < items.count; i++) { @@ -445,8 +737,8 @@ UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleItemTap:)]; [itemView1 addGestureRecognizer:tapGesture]; - [self.container1ScrollView addSubview:itemView1]; - [self.itemViews1 addObject:itemView1]; + [self.shoppoingMallCategoryScrollView addSubview:itemView1]; + [self.categoryCardArray addObject:itemView1]; } // 添加 item view-2 到 container2ScrollView @@ -455,9 +747,9 @@ layout.itemSize = CGSizeZero;// CGSizeMake((screenWidth-30) / 2 - 10, kGetScaleWidth(244)); layout.minimumInteritemSpacing = 10; layout.minimumLineSpacing = 10; - layout.sectionInset = UIEdgeInsetsMake(0, 15, 10, 15); + layout.sectionInset = UIEdgeInsetsMake(0, 15, self.bottomSpace + 10, 15); - UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(i * screenWidth, 0, screenWidth, self.container2ScrollView.frame.size.height) + UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(i * screenWidth, 0, screenWidth, self.mallItemsScrollView.frame.size.height) collectionViewLayout:layout]; collectionView.delegate = self; collectionView.dataSource = self; @@ -467,8 +759,16 @@ [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"]; [collectionView registerClass:[ShoppingMallItemCard class] forCellWithReuseIdentifier:@"ShoppingMallItemCard"]; [collectionView registerClass:[ShoppingMallEmptyCard class] forCellWithReuseIdentifier:@"ShoppingMallEmptyCard"]; - [self.container2ScrollView addSubview:collectionView]; - [self.itemViews2 addObject:collectionView]; + [collectionView registerClass:[MyDressingItemCard class] forCellWithReuseIdentifier:@"MyDressingItemCard"]; + [collectionView registerClass:[MyDressingItemCard class] forCellWithReuseIdentifier:@"MyDressingItemCard_NotUsed"]; + + [self.mallItemsScrollView addSubview:collectionView]; + [self.itemCollectionViewArray addObject:collectionView]; + + if (self.isForMyDressingPage) { + [self addRefreshControl:collectionView]; + [self addLoadMoreForCollectionView:collectionView]; + } } [self updateSelectionForItemAtIndex:0]; @@ -479,7 +779,7 @@ - (void)handleItemTap:(UITapGestureRecognizer *)gesture { NSInteger index = gesture.view.tag; CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; - [self.container2ScrollView setContentOffset:CGPointMake(index * screenWidth, 0) animated:YES]; + [self.mallItemsScrollView setContentOffset:CGPointMake(index * screenWidth, 0) animated:YES]; [self updateSelectionForItemAtIndex:index]; [self loadDataForPageAtIndex:index]; } @@ -490,7 +790,7 @@ if (![self.requestedPages containsObject:@(pageIndex)]) { [self.requestedPages addObject:@(pageIndex)]; // 标记该页已请求 - // 使用外部提供的回调或代理来请求数据 + // 使用外部提供的回调或代理来请求数据, 我的装扮和商城使用不同的数据 if (self.fetchDataForPage) { NSDictionary *itemDic = [self.items xpSafeObjectAtIndex:pageIndex]; NSNumber *type = [itemDic allValues].firstObject; @@ -498,41 +798,87 @@ self.fetchDataForPage(type.integerValue, ^(NSArray *data) { @kStrongify(self); if (self) { - // 更新数据到对应的 itemView-2 - [self updateContainer2WithData:data atIndex:pageIndex]; + [self updateItemCollectionViewWithShoppingMallData:data atIndex:pageIndex]; } }); + } else if (self.fetchDataForMyDressingPage) { + [self.myDressingDataPagesNumbers addObject:@(1)]; + [self loadMyDressingItems:pageIndex pageNum:1]; } } } +- (void)loadMyDressingItems:(NSInteger)pageIndex + pageNum:(NSInteger)pageNum{ + NSDictionary *itemDic = [self.items xpSafeObjectAtIndex:pageIndex]; + NSNumber *type = [itemDic allValues].firstObject; + @kWeakify(self); + self.fetchDataForMyDressingPage(type.integerValue, pageNum, ^(NSArray * _Nonnull modelList) { + @kStrongify(self); + if (self) { + [self updateItemCollectionViewWithMyDressingData:modelList pageNum:pageNum atIndex:pageIndex]; + } + }); +} + // 更新选中的 item view-1 - (void)updateSelectionForItemAtIndex:(NSInteger)index { - for (ShoppingMallCategoryCard *view in self.itemViews1) { + for (ShoppingMallCategoryCard *view in self.categoryCardArray) { view.isSelected = (view.tag == index); } self.selectedIndexPath = nil; if (self.returnSelectedModel) { self.returnSelectedModel(nil); } - for (UICollectionView *itemView in self.itemViews2) { + for (UICollectionView *itemView in self.itemCollectionViewArray) { [itemView reloadData]; } } -- (void)updateContainer2WithData:(NSArray *)data - atIndex:(NSInteger)index { +- (void)updateItemCollectionViewWithShoppingMallData:(NSArray *)data + atIndex:(NSInteger)index { self.dataCache[@(index)] = data; - if (index < self.itemViews2.count) { - UICollectionView *itemView = self.itemViews2[index]; + if (index < self.itemCollectionViewArray.count) { + UICollectionView *itemView = self.itemCollectionViewArray[index]; [itemView reloadData]; } } +- (void)updateItemCollectionViewWithMyDressingData:(NSArray *)data + pageNum:(NSInteger)pageNum + atIndex:(NSInteger)index { + if (pageNum == 1) { + self.myDressingDataCache[@(index)] = data; + } else { + NSMutableArray *array = self.myDressingDataCache[@(index)].mutableCopy; + [array addObjectsFromArray:data]; + self.myDressingDataCache[@(index)] = array.copy; + } + + if (index < self.itemCollectionViewArray.count) { + UICollectionView *itemView = self.itemCollectionViewArray[index]; + [itemView.refreshControl endRefreshing]; + [itemView.mj_header endRefreshing]; + [itemView.mj_footer endRefreshing]; + [itemView reloadData]; + + if (data.count == 0 || data.count < 2) { + [itemView.mj_footer endRefreshingWithNoMoreData]; + NSNumber *currentPageNum = [self.myDressingDataPagesNumbers xpSafeObjectAtIndex:itemView.tag]; + + if (currentPageNum.integerValue > 1) { + currentPageNum = @(currentPageNum.integerValue - 1); + [self.myDressingDataPagesNumbers replaceObjectAtIndex:itemView.tag + withObject:currentPageNum]; + } + } + } +} + #pragma mark - UIScrollView Delegate // 根据 container2ScrollView 的滑动位置更新 item view-1 的选中状态 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { - if (scrollView == self.container2ScrollView) { + if (scrollView == self.mallItemsScrollView) { NSInteger pageIndex = round(scrollView.contentOffset.x / scrollView.frame.size.width); [self updateSelectionForItemAtIndex:pageIndex]; [self loadDataForPageAtIndex:pageIndex]; @@ -541,43 +887,79 @@ #pragma mark - UICollectionView Delegate & DataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - NSArray *data = self.dataCache[@(collectionView.tag)]; - return data.count == 0 ? 1 : data.count; + if (self.isForMyDressingPage) { + NSArray *data = self.myDressingDataCache[@(collectionView.tag)]; + return data.count + 1; + } else { + NSArray *data = self.dataCache[@(collectionView.tag)]; + return data.count == 0 ? 1 : data.count; + } } -- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - NSArray *data = self.dataCache[@(collectionView.tag)]; - if (data.count == 0 ) { - return CGSizeMake(KScreenWidth, 200); +- (CGSize)collectionView:(UICollectionView *)collectionView + layout:(UICollectionViewLayout *)collectionViewLayout + sizeForItemAtIndexPath:(NSIndexPath *)indexPath { + if (self.isForMyDressingPage) { + return CGSizeMake((KScreenWidth-30) / 2 - 10, kGetScaleWidth(190)); } else { - return CGSizeMake((KScreenWidth-30) / 2 - 10, kGetScaleWidth(244)); + NSArray *data = self.dataCache[@(collectionView.tag)]; + if (data.count == 0 ) { + return CGSizeMake(KScreenWidth, 200); + } else { + return CGSizeMake((KScreenWidth-30) / 2 - 10, kGetScaleWidth(244)); + } } } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - - NSArray *data = self.dataCache[@(collectionView.tag)]; - if (data.count == 0) { - ShoppingMallEmptyCard *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ShoppingMallEmptyCard" forIndexPath:indexPath]; + if (self.isForMyDressingPage) { + MyDressingItemCard *cell = nil; + + if (indexPath.row == 0) { + cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyDressingItemCard_NotUsed" + forIndexPath:indexPath]; + cell.model = nil; + } else { + cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyDressingItemCard" + forIndexPath:indexPath]; + NSArray *data = self.myDressingDataCache[@(collectionView.tag)]; + cell.model = [data xpSafeObjectAtIndex:indexPath.row-1]; + cell.selected = cell.model.used; + + if (self.didTapItemPlay) { + @kWeakify(self); + cell.didTapPlay = ^(NSString * _Nonnull resourcePath) { + @kStrongify(self); + self.didTapItemPlay(resourcePath); + }; + } + } + return cell; } else { - ShoppingMallItemCard *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ShoppingMallItemCard" - forIndexPath:indexPath]; - cell.cellModel = [data xpSafeObjectAtIndex:indexPath.row]; - // 设置选中状态 - if ([indexPath isEqual:self.selectedIndexPath]) { - cell.selected = YES; + NSArray *data = self.dataCache[@(collectionView.tag)]; + if (data.count == 0) { + ShoppingMallEmptyCard *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ShoppingMallEmptyCard" forIndexPath:indexPath]; + return cell; } else { - cell.selected = NO; + ShoppingMallItemCard *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ShoppingMallItemCard" + forIndexPath:indexPath]; + cell.cellModel = [data xpSafeObjectAtIndex:indexPath.row]; + // 设置选中状态 + if ([indexPath isEqual:self.selectedIndexPath]) { + cell.selected = YES; + } else { + cell.selected = NO; + } + if (self.didTapItemPlay) { + @kWeakify(self); + cell.didTapPlay = ^(NSString * _Nonnull resourcePath) { + @kStrongify(self); + self.didTapItemPlay(resourcePath); + }; + } + return cell; } - if (self.didTapItemPlay) { - @kWeakify(self); - cell.didTapPlay = ^(NSString * _Nonnull resourcePath) { - @kStrongify(self); - self.didTapItemPlay(resourcePath); - }; - } - return cell; } } @@ -586,10 +968,30 @@ self.selectedIndexPath = indexPath; - if (self.returnSelectedModel) { + if (self.isForMyDressingPage) { + NSArray *data = self.myDressingDataCache[@(collectionView.tag)]; + if (self.returnMyDressingSelectedModel) { + NSInteger type = collectionView.tag; + if (type == 0) { + type = 1; + } else if (type == 1) { + type = 0; + } + if (indexPath.row > 0) { + MyDressingDataModel *model = [data xpSafeObjectAtIndex:indexPath.row - 1]; + if (model.used == 0) { + self.returnMyDressingSelectedModel(model, type); + } + } else { + self.returnMyDressingSelectedModel(nil, type); + } + } + } else { NSArray *data = self.dataCache[@(collectionView.tag)]; - DressUpShopModel *model = [data xpSafeObjectAtIndex:indexPath.row]; - self.returnSelectedModel(model); + if (self.returnSelectedModel) { + DressUpShopModel *model = [data xpSafeObjectAtIndex:indexPath.row]; + self.returnSelectedModel(model); + } } NSMutableArray *indexPathsToReload = [NSMutableArray array]; @@ -600,5 +1002,45 @@ [collectionView reloadItemsAtIndexPaths:indexPathsToReload]; } +#pragma mark - 上下拉刷新 +- (void)addRefreshControl:(UICollectionView *)collectionView { + +// MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(handlePullToRefresh:)]; +// header.stateLabel.font = [UIFont systemFontOfSize:10.0]; +// header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:10.0]; +// header.stateLabel.textColor = [DJDKMIMOMColor secondTextColor]; +// header.lastUpdatedTimeLabel.textColor = [DJDKMIMOMColor secondTextColor]; +// collectionView.mj_header = header; + UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; + refreshControl.tintColor = [UIColor lightGrayColor]; + [refreshControl addTarget:self action:@selector(handlePullToRefresh:) forControlEvents:UIControlEventValueChanged]; + collectionView.refreshControl = refreshControl; +} + +- (void)addLoadMoreForCollectionView:(UICollectionView *)collectionView { + if (collectionView.tag == 0) { + return; + } + @kWeakify(self); + collectionView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{ + @kStrongify(self); + NSNumber *currentPageNum = [self.myDressingDataPagesNumbers xpSafeObjectAtIndex:collectionView.tag]; + currentPageNum = @(currentPageNum.integerValue + 1); + [self.myDressingDataPagesNumbers replaceObjectAtIndex:collectionView.tag + withObject:currentPageNum]; + [self loadMyDressingItems:collectionView.tag pageNum:currentPageNum.integerValue]; + }]; +} + +- (void)handlePullToRefresh:(UIRefreshControl *)collectionViewRefreshControl { + UICollectionView *collectionView = (UICollectionView *)collectionViewRefreshControl.superview; + if (collectionView) { + [self.myDressingDataPagesNumbers replaceObjectAtIndex:collectionView.tag + withObject:@(1)]; + [self loadMyDressingItems:collectionView.tag pageNum:1]; + [collectionView.mj_footer resetNoMoreData]; + } + +} @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.h b/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.h index 397904ac..6e0b6b5c 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.h +++ b/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.h @@ -7,15 +7,17 @@ #import -@class DressUpShopModel; +@class DressUpShopModel, MyDressingDataModel; NS_ASSUME_NONNULL_BEGIN @interface ShoppingMallItemPreview : UIView @property(nonatomic, copy) void(^buyWith)(DressUpShopModel *model); +@property(nonatomic, copy) void(^giveWith)(DressUpShopModel *model); -- (instancetype)initWith:(DressUpShopModel *)model; +- (instancetype)initWith:(DressUpShopModel *)model isForGive:(BOOL)isForGive; +- (instancetype)initWithMyDress:(MyDressingDataModel *)model isVaild:(BOOL)isVaild; @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.m b/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.m index ea59dcef..3926791a 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.m +++ b/YuMi/Modules/ShoppingMall/ShoppingMallItemPreview.m @@ -7,14 +7,22 @@ #import "ShoppingMallItemPreview.h" #import "DressUpShopModel.h" +#import "MyDressingDataModel.h" @interface ShoppingMallItemPreview () +@property(nonatomic, assign) BOOL isForGive; +@property(nonatomic, assign) BOOL isVaild; @property(nonatomic, strong) DressUpShopModel *model; +@property(nonatomic, strong) MyDressingDataModel *myDressingModel; @property(nonatomic, strong) NetImageView *itemImageView; @property(nonatomic, strong) UILabel *nameLabel; @property(nonatomic, strong) UILabel *pricePerDayLabel; +@property(nonatomic, strong) UIButton *cancelButton; +@property(nonatomic, strong) UIButton *buyButton; +@property(nonatomic, strong) UIButton *giveButton; + @end @implementation ShoppingMallItemPreview @@ -26,20 +34,50 @@ return self; } -- (instancetype)initWith:(DressUpShopModel *)model { +- (instancetype)initWith:(DressUpShopModel *)model isForGive:(BOOL)isForGive { if (self = [super init]) { [self setupUI]; + self.isForGive = isForGive; self.model = model; } return self; } +- (instancetype)initWithMyDress:(MyDressingDataModel *)model isVaild:(BOOL)isVaild { + if (self = [super init]) { + [self setupUI]; + self.isVaild = isVaild; + self.myDressingModel = model; + } + return self; +} + - (void)setModel:(DressUpShopModel *)model { _model = model; self.itemImageView.imageUrl = model.pic; self.nameLabel.text = model.name; - self.pricePerDayLabel.attributedText = model.pricePerDay; + self.pricePerDayLabel.attributedText = [model generateAttributedStringWithIncludeOriginalPrice:YES]; +} + +- (void)setMyDressingModel:(MyDressingDataModel *)myDressingModel { + _myDressingModel = myDressingModel; + self.itemImageView.imageUrl = myDressingModel.pic; + self.nameLabel.text = myDressingModel.name; + if (self.isVaild) { + self.buyButton.hidden = NO; + } else { + self.buyButton.hidden = YES; + self.giveButton.hidden = YES; + [self.cancelButton setTitle:YMLocalizedString(@"TTAlertConfig0") forState:UIControlStateNormal]; + [self.cancelButton mas_remakeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self); + make.bottom.mas_equalTo(-38); + make.size.mas_equalTo(CGSizeMake(90, 32)); + }]; + self.pricePerDayLabel.text = YMLocalizedString(@"1.0.30_text_2"); + } +// self.pricePerDayLabel.attributedText = [model generateAttributedStringWithIncludeOriginalPrice:YES]; } - (void)setupUI { @@ -78,17 +116,22 @@ make.top.mas_equalTo(self.pricePerDayLabel.mas_bottom).offset(18); }]; - UIButton *cancel = [self cancelButton]; - [self addSubview:cancel]; - [cancel mas_makeConstraints:^(MASConstraintMaker *make) { + [self addSubview:self.cancelButton]; + [self.cancelButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(line.mas_bottom).offset(20); make.leading.mas_equalTo(46); make.size.mas_equalTo(CGSizeMake(90, 32)); }]; - UIButton *buy = [self buyButton]; - [self addSubview:buy]; - [buy mas_makeConstraints:^(MASConstraintMaker *make) { + [self addSubview:self.buyButton]; + [self.buyButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.mas_equalTo(line.mas_bottom).offset(20); + make.trailing.mas_equalTo(-46); + make.size.mas_equalTo(CGSizeMake(90, 32)); + }]; + + [self addSubview:self.giveButton]; + [self.giveButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(line.mas_bottom).offset(20); make.trailing.mas_equalTo(-46); make.size.mas_equalTo(CGSizeMake(90, 32)); @@ -96,6 +139,13 @@ } #pragma mark - + +- (void)setIsForGive:(BOOL)isForGive { + _isForGive = isForGive; + self.buyButton.hidden = isForGive; + self.giveButton.hidden = !isForGive; +} + - (void)didTapCancel { [TTPopup dismiss]; } @@ -106,6 +156,12 @@ } } +- (void)didTapGive { + if (self.giveWith) { + self.giveWith(self.model); + } +} + #pragma mark - - (UIImageView *)backgroundImageView { UIImageView *bgImageView = [[UIImageView alloc] initWithImage:kImage(@"mall_item_preview_bg")]; @@ -144,30 +200,59 @@ } - (UIButton *)cancelButton { - UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; - [b setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.3]]; - [b setAttributedTitle:[[NSAttributedString alloc] initWithString:YMLocalizedString(@"XPShareView7") - attributes:@{NSFontAttributeName: kFontMedium(14), - NSForegroundColorAttributeName: [UIColor whiteColor]}] - forState:UIControlStateNormal]; - [b addTarget:self action:@selector(didTapCancel) forControlEvents:UIControlEventTouchUpInside]; - [b setCornerRadius:16]; - return b; + if (!_cancelButton) { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b setBackgroundColor:[UIColor colorWithWhite:0 alpha:0.3]]; + [b setAttributedTitle:[[NSAttributedString alloc] initWithString:YMLocalizedString(@"XPShareView7") + attributes:@{NSFontAttributeName: kFontMedium(14), + NSForegroundColorAttributeName: [UIColor whiteColor]}] + forState:UIControlStateNormal]; + [b addTarget:self action:@selector(didTapCancel) forControlEvents:UIControlEventTouchUpInside]; + [b setCornerRadius:16]; + _cancelButton = b; + } + + return _cancelButton; } - (UIButton *)buyButton { - UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; - [b addGradientBackgroundWithColors:@[UIColorFromRGB(0xFFE3B2), UIColorFromRGB(0xE9A71D)] - startPoint:CGPointMake(0.0, 0.5) - endPoint:CGPointMake(1.0, 0.5) - cornerRadius:16]; - [b setAttributedTitle:[[NSAttributedString alloc] initWithString:YMLocalizedString(@"XPDressUpShopCardTableViewCell2") - attributes:@{NSFontAttributeName: kFontMedium(14), - NSForegroundColorAttributeName: UIColorFromRGB(0x51281b)}] - forState:UIControlStateNormal]; - [b addTarget:self action:@selector(didTapBuy) forControlEvents:UIControlEventTouchUpInside]; - [b setCornerRadius:16]; - return b; + if (!_buyButton) { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b addGradientBackgroundWithColors:@[UIColorFromRGB(0xFFE3B2), UIColorFromRGB(0xE9A71D)] + startPoint:CGPointMake(0.0, 0.5) + endPoint:CGPointMake(1.0, 0.5) + cornerRadius:16]; + [b setAttributedTitle:[[NSAttributedString alloc] initWithString:YMLocalizedString(@"XPDressUpShopCardTableViewCell2") + attributes:@{NSFontAttributeName: kFontMedium(14), + NSForegroundColorAttributeName: UIColorFromRGB(0x51281b)}] + forState:UIControlStateNormal]; + [b addTarget:self action:@selector(didTapBuy) forControlEvents:UIControlEventTouchUpInside]; + [b setCornerRadius:16]; + b.hidden = YES; + _buyButton = b; + } + + return _buyButton; +} + +- (UIButton *)giveButton { + if (!_giveButton) { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b addGradientBackgroundWithColors:@[UIColorFromRGB(0xB2FCFF), UIColorFromRGB(0x4DA2EA)] + startPoint:CGPointMake(0.0, 0.5) + endPoint:CGPointMake(1.0, 0.5) + cornerRadius:16]; + [b setAttributedTitle:[[NSAttributedString alloc] initWithString:YMLocalizedString(@"1.0.30_text_6") + attributes:@{NSFontAttributeName: kFontMedium(14), + NSForegroundColorAttributeName: UIColorFromRGB(0x172055)}] + forState:UIControlStateNormal]; + [b addTarget:self action:@selector(didTapGive) forControlEvents:UIControlEventTouchUpInside]; + [b setCornerRadius:16]; + b.hidden = YES; + _giveButton = b; + } + + return _giveButton; } @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallTagView.h b/YuMi/Modules/ShoppingMall/ShoppingMallTagView.h index 789c7e34..d22fe544 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallTagView.h +++ b/YuMi/Modules/ShoppingMall/ShoppingMallTagView.h @@ -13,6 +13,13 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, copy) NSString *text; +- (instancetype)initWithBackgroundColors:(NSArray *)colors + font:(UIFont *)font + textColor:(UIColor *)textColor; + +- (void)updateBackgroundColors:(NSArray *)colors + textColor:(UIColor *)textColor; + - (CGFloat)textWidth; @end diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallTagView.m b/YuMi/Modules/ShoppingMall/ShoppingMallTagView.m index 50194e8a..30350180 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallTagView.m +++ b/YuMi/Modules/ShoppingMall/ShoppingMallTagView.m @@ -16,16 +16,51 @@ @implementation ShoppingMallTagView +- (instancetype)initWithBackgroundColors:(NSArray *)colors + font:(UIFont *)font + textColor:(UIColor *)textColor { + if (self = [super init]) { + [self setCornerRadius:10 + cornerMask:kCALayerMinXMinYCorner | kCALayerMaxXMaxYCorner]; + self.clipsToBounds = YES; + if (colors.count>1) { + [self addGradientBackgroundWithColors:colors //@[UIColorFromRGB(0xE29030), UIColorFromRGB(0xFCC074)] + startPoint:CGPointMake(0.0, 0.0) + endPoint:CGPointMake(0.0, 1.0) + cornerRadius:0]; + } else if (colors.count == 1){ + self.backgroundColor = colors.firstObject; + } + + [self addSubview:self.label]; + [self.label mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self); + }]; + + self.label.font = font; + self.label.textColor = textColor; + } + return self; +} + +- (void)updateBackgroundColors:(NSArray *)colors + textColor:(UIColor *)textColor { + if (colors.count>1) { + [self addGradientBackgroundWithColors:colors //@[UIColorFromRGB(0xE29030), UIColorFromRGB(0xFCC074)] + startPoint:CGPointMake(0.0, 0.0) + endPoint:CGPointMake(0.0, 1.0) + cornerRadius:0]; + } else if (colors.count == 1){ + self.backgroundColor = colors.firstObject; + } + self.label.textColor = textColor; +} + - (instancetype)init { if (self = [super init]) { [self setCornerRadius:10 cornerMask:kCALayerMinXMinYCorner | kCALayerMaxXMaxYCorner]; self.clipsToBounds = YES; - - [self addGradientBackgroundWithColors:@[UIColorFromRGB(0xE29030), UIColorFromRGB(0xFCC074)] - startPoint:CGPointMake(0.0, 0.0) - endPoint:CGPointMake(0.0, 1.0) - cornerRadius:0]; [self addSubview:self.label]; [self.label mas_makeConstraints:^(MASConstraintMaker *make) { @@ -41,7 +76,7 @@ } - (CGFloat)textWidth { - return [self.text boundingRectWithSize:CGSizeMake(KScreenWidth/3, kFontMedium(12).lineHeight) + return [self.text boundingRectWithSize:CGSizeMake(KScreenWidth/3, self.label.font.lineHeight) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: kFontMedium(12)} context:nil].size.width + 20; diff --git a/YuMi/Modules/ShoppingMall/ShoppingMallViewController.m b/YuMi/Modules/ShoppingMall/ShoppingMallViewController.m index 5e6f25b4..546efee7 100644 --- a/YuMi/Modules/ShoppingMall/ShoppingMallViewController.m +++ b/YuMi/Modules/ShoppingMall/ShoppingMallViewController.m @@ -11,6 +11,7 @@ #import #import "MyDressingViewController.h" +#import "XPDressSearchViewController.h" #import "ShoppingMallItemPreview.h" #import "ShoppingMallDataPresent.h" @@ -29,6 +30,8 @@ static NSArray *> *DressUpOptions(void) { @interface ShoppingMallViewController () +@property(nonatomic, strong) ShoppingMallCategoryListView *listView; + @property (nonatomic, strong) UIView *playEffectMask; @property (nonatomic, strong) VAPView *mp4Effect; @property (nonatomic, strong) SVGAImageView *svgaEffect; @@ -63,6 +66,8 @@ static NSArray *> *DressUpOptions(void) { [self setupNavigationBar]; [self setupBottomControlBar]; [self setupContentList]; + + [self hideBottomControlArea]; } - (void)setupBackground { @@ -105,7 +110,8 @@ static NSArray *> *DressUpOptions(void) { - (void)setupBottomControlBar { [self.view addSubview:self.bottomControlArea]; [self.bottomControlArea mas_makeConstraints:^(MASConstraintMaker *make) { - make.bottom.leading.trailing.mas_equalTo(self.view); + make.bottom.mas_equalTo(0); + make.leading.trailing.mas_equalTo(self.view); make.height.mas_equalTo(80 + kSafeAreaBottomHeight); }]; } @@ -113,7 +119,10 @@ static NSArray *> *DressUpOptions(void) { - (void)setupContentList { NSInteger top = kNavigationHeight; NSInteger bottom = 80 + kSafeAreaBottomHeight; - ShoppingMallCategoryListView *listView = [[ShoppingMallCategoryListView alloc] initWithFrame:CGRectMake(0, top, KScreenWidth, KScreenHeight - top - bottom)]; + ShoppingMallCategoryListView *listView = [[ShoppingMallCategoryListView alloc] initWithFrame:CGRectMake(0, top, KScreenWidth, KScreenHeight - top)]; + listView.bottomSpace = bottom; + [self.view insertSubview:listView belowSubview:self.bottomControlArea]; + self.listView = listView; @kWeakify(self); listView.fetchDataForPage = ^(NSInteger pageIndex, FetchDataCompletion completion) { @kStrongify(self); @@ -129,11 +138,6 @@ static NSArray *> *DressUpOptions(void) { self.selectedModel = model; [self updateBottomControlArea]; }; - listView.didTapItemPlay = ^(NSString * _Nonnull resourcePath) { - @kStrongify(self); - [self playItemEffect:resourcePath]; - }; - [self.view addSubview:listView]; listView.items = DressUpOptions(); } @@ -152,17 +156,47 @@ static NSArray *> *DressUpOptions(void) { - (void)updateBottomControlArea { if (self.selectedModel) { - self.bottomControlPriceLabel.attributedText = self.selectedModel.pricePerDay; + if (self.selectedModel.obtainWay > 1) { + self.bottomControlPriceLabel.text = @""; + } else { + self.bottomControlPriceLabel.attributedText = [self.selectedModel generateAttributedStringWithIncludeOriginalPrice:YES]; + } } else { self.bottomControlPriceLabel.text = @""; } + + if ([NSString isEmpty:self.bottomControlPriceLabel.text]) { + [self hideBottomControlArea]; + } else { + [self showBottomControlArea]; + } +} + +- (void)showBottomControlArea { + [UIView animateWithDuration:0.25 animations:^{ + [self.bottomControlArea mas_updateConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(0); + }]; + } completion:^(BOOL finished) { + [self.view layoutIfNeeded]; + }]; +} + +- (void)hideBottomControlArea { + [UIView animateWithDuration:0.25 animations:^{ + [self.bottomControlArea mas_updateConstraints:^(MASConstraintMaker *make) { + make.bottom.mas_equalTo(80 + kSafeAreaBottomHeight); + }]; + } completion:^(BOOL finished) { + [self.view layoutIfNeeded]; + }]; } - (void)didTapBuy:(id)sender { if (!self.selectedModel) { return; } - ShoppingMallItemPreview *preview = [[ShoppingMallItemPreview alloc] initWith:self.selectedModel]; + ShoppingMallItemPreview *preview = [[ShoppingMallItemPreview alloc] initWith:self.selectedModel isForGive:NO]; preview.frame = CGRectMake(0, 0, 284, 353); [TTPopup popupView:preview style:TTPopupStyleAlert]; @kWeakify(self); @@ -185,6 +219,9 @@ static NSArray *> *DressUpOptions(void) { if (!self.selectedModel) { return; } + XPDressSearchViewController *vc = [[XPDressSearchViewController alloc] init]; + vc.selectedModel = self.selectedModel; + [self.navigationController pushViewController:vc animated:YES]; } - (void)didTapBack { @@ -218,10 +255,12 @@ static NSArray *> *DressUpOptions(void) { [p parseWithURL:[NSURL URLWithString:path] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) { @kStrongify(self); - [self.loading stopAnimating]; - self.svgaEffect.hidden = NO; - self.svgaEffect.videoItem = videoItem; - [self.svgaEffect startAnimation]; + if (!self.playEffectMask.isHidden) { + [self.loading stopAnimating]; + self.svgaEffect.hidden = NO; + self.svgaEffect.videoItem = videoItem; + [self.svgaEffect startAnimation]; + } } failureBlock:^(NSError * _Nullable error) { @kStrongify(self); [self stopItemSVGAEffect]; @@ -247,6 +286,9 @@ static NSArray *> *DressUpOptions(void) { [self.loading mas_makeConstraints:^(MASConstraintMaker *make) { make.center.mas_equalTo(_playEffectMask); }]; + + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stopItemSVGAEffect)]; + [_playEffectMask addGestureRecognizer:tap]; } return _playEffectMask; } @@ -259,9 +301,8 @@ static NSArray *> *DressUpOptions(void) { _svgaEffect.loops = 0; _svgaEffect.clearsAfterStop = YES; _svgaEffect.hidden = YES; - - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stopItemSVGAEffect)]; - [_svgaEffect addGestureRecognizer:tap]; + _svgaEffect.userInteractionEnabled = YES; + } return _svgaEffect; } diff --git a/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.h b/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.h index 39c1722a..bd626524 100644 --- a/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.h +++ b/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.h @@ -96,6 +96,15 @@ NS_ASSUME_NONNULL_BEGIN /// @param targetUid 目标用户UID + (void)requestSendDress:(HttpRequestHelperCompletion)completion id:(NSString *)dressId targetUid:(NSString *)targetUid; +/// 获取我的装扮内容 +/// @param completion 完成回掉 +/// @param page 分页 +/// @param pageSize 分页大小 +/// @param dressType 装扮类型,目前只支持 0 & 5 ++ (void)mineDressItems:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize dressType:(NSString *)dressType; + ++ (void)optDress:(HttpRequestHelperCompletion)completion dressType:(NSString *)dressType dressId:(NSString *)dressId; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.m b/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.m index 709421eb..c2733234 100644 --- a/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.m +++ b/YuMi/Modules/YMMine/View/DressUp/Api/Api+DressUp.m @@ -143,4 +143,12 @@ [self makeRequest:fang method:HttpRequestHelperMethodPOST completion:completion, __FUNCTION__, dressId, targetUid, nil]; } ++ (void)mineDressItems:(HttpRequestHelperCompletion)completion page:(NSString *)page pageSize:(NSString *)pageSize dressType:(NSString *)dressType { + [self makeRequest:@"dress/shop/mine" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, page, pageSize, dressType, nil]; +} + ++ (void)optDress:(HttpRequestHelperCompletion)completion dressType:(NSString *)dressType dressId:(NSString *)dressId { + [self makeRequest:@"dress/shop/optDress" method:HttpRequestHelperMethodGET completion:completion, __FUNCTION__, dressType, dressId, nil]; +} + @end diff --git a/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.h b/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.h index 49fb548a..76b7b9d1 100644 --- a/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.h +++ b/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.h @@ -46,9 +46,14 @@ NS_ASSUME_NONNULL_BEGIN // "获得方式,1-普通,2-活动" @property (nonatomic, assign) NSInteger obtainWay; +// 个人页背景 +@property(nonatomic, copy) NSString *usingPersonalBackground; + - (NSMutableAttributedString *)pricePerDay; - (NSMutableAttributedString *)pricePerDayForVIP; +- (NSMutableAttributedString *)generateAttributedStringWithIncludeOriginalPrice:(BOOL)includeOriginalPrice; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.m b/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.m index 5816d675..67a7aa16 100644 --- a/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.m +++ b/YuMi/Modules/YMMine/View/DressUp/Model/DressUpShopModel.m @@ -37,7 +37,7 @@ //TODO: 修改为支持 0-1-2 位小数 - if (fmod(self.discountPrice, 1.0) == 0.0) { + if (fmod(self.dressPrice, 1.0) == 0.0) { formattedPriceString = [NSString stringWithFormat:@"%ld", (long)self.dressPrice]; } else { formattedPriceString = [NSString stringWithFormat:@"%.2ld", (long)self.dressPrice]; @@ -118,4 +118,67 @@ return attributedString; } +- (NSMutableAttributedString *)generateAttributedStringWithIncludeOriginalPrice:(BOOL)includeOriginalPrice { + // 创建一个 NSMutableAttributedString 来存放最终的结果 + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init]; + + // 1. 添加金币图片 + NSTextAttachment *coinAttachment = [[NSTextAttachment alloc] init]; + coinAttachment.image = kImage(@"moli_money_icon"); // 替换为你的金币图片名称 + coinAttachment.bounds = CGRectMake(0, -2, 18, 18); // 设置图片大小和位置,偏移量适当调整 + NSAttributedString *coinString = [NSAttributedString attributedStringWithAttachment:coinAttachment]; + [attributedString appendAttributedString:coinString]; + + // 2. 添加空格 + NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:@" "]; + [attributedString appendAttributedString:spaceString]; + + // 3. 添加 price 文本,字体加粗,颜色 #F8CE1F,字体大小 25 + NSDictionary *priceAttributes = @{ + NSFontAttributeName: kFontSemibold(15), + NSForegroundColorAttributeName: UIColorFromRGB(0xF8CE1F) + }; + NSString *formattedPriceString = [self formatPrice: self.vipLevel>0 ? self.discountPrice : self.dressPrice]; + NSAttributedString *priceString = [[NSAttributedString alloc] initWithString:formattedPriceString attributes:priceAttributes]; + [attributedString appendAttributedString:priceString]; + + // 4. 添加 day 文本,字体常规,颜色 #F8CE1F,字体大小 12 + NSDictionary *dayAttributes = @{ + NSFontAttributeName: kFontRegular(12), + NSForegroundColorAttributeName: UIColorFromRGB(0xF8CE1F) + }; + NSString *formattedDayString = [NSString stringWithFormat:@"/%ldD ", (long)self.dressDay]; + NSAttributedString *dayString = [[NSAttributedString alloc] initWithString:formattedDayString attributes:dayAttributes]; + [attributedString appendAttributedString:dayString]; + + // 如果需要添加原始价格 + if (includeOriginalPrice && self.vipLevel > 0) { + NSDictionary *originalPriceAttributes = @{ + NSFontAttributeName: kFontRegular(12), + NSForegroundColorAttributeName: UIColorRGBAlpha(0xD9E7F7, 0.5f), + NSStrikethroughStyleAttributeName: @(NSUnderlineStyleSingle), // 单条删除线 + NSStrikethroughColorAttributeName: UIColorRGBAlpha(0xD9E7F7, 0.5f) // 删除线颜色 + }; + NSString *originalPriceString = [NSString stringWithFormat:@"%@", [self formatPrice:self.dressPrice]]; + NSAttributedString *originalPriceAttributedString = [[NSAttributedString alloc] initWithString:originalPriceString attributes:originalPriceAttributes]; + [attributedString appendAttributedString:originalPriceAttributedString]; + } + + return attributedString; +} + +// 辅助方法:格式化价格,支持 0-2 位小数 +- (NSString *)formatPrice:(CGFloat)price { + if (fmod(price, 1.0) == 0.0) { + // 整数,移除小数部分 + return [NSString stringWithFormat:@"%.0f", price]; + } else if (fmod(price * 10, 1.0) == 0.0) { + // 保留 1 位小数 + return [NSString stringWithFormat:@"%.1f", price]; + } else { + // 保留 2 位小数 + return [NSString stringWithFormat:@"%.2f", price]; + } +} + @end diff --git a/YuMi/Modules/YMMine/View/DressUp/Model/NameplateModel.h b/YuMi/Modules/YMMine/View/DressUp/Model/NameplateModel.h index c2d05641..872a00cf 100644 --- a/YuMi/Modules/YMMine/View/DressUp/Model/NameplateModel.h +++ b/YuMi/Modules/YMMine/View/DressUp/Model/NameplateModel.h @@ -31,7 +31,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, assign) NSTimeInterval createTime; @property (nonatomic, assign) BOOL isCustomWord; @property (nonatomic, copy) NSString *remark; -@property (nonatomic, copy) NSString *iconPic; +//@property (nonatomic, copy) NSString *iconPic; @property (nonatomic, assign) NSInteger expireDays; @property (nonatomic, assign) NSTimeInterval updateTime; @property (nonatomic, copy) NSString *nameplateName; diff --git a/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.h b/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.h index 7b977cd9..b3607a06 100644 --- a/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.h +++ b/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.h @@ -7,12 +7,12 @@ #import "MvpViewController.h" +@class DressUpShopModel; NS_ASSUME_NONNULL_BEGIN @interface XPDressSearchViewController : MvpViewController -@property (nonatomic, assign) NSInteger dressType; -@property (nonatomic, copy) NSString *dressId; +@property(nonatomic, strong) DressUpShopModel *selectedModel; @end diff --git a/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.m b/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.m index 06fef0b0..9a61f1cf 100644 --- a/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.m +++ b/YuMi/Modules/YMMine/View/DressUp/View/XPDressSearchViewController.m @@ -14,6 +14,7 @@ #import "Api+DressUp.h" #import "NSArray+Safe.h" ///Model +#import "DressUpShopModel.h" #import "HomeSearchResultModel.h" ///View #import "XPDressShopSearchTableViewCell.h" @@ -24,7 +25,10 @@ ///VC #import "XPRoomViewController.h" #import "XPMineUserInfoViewController.h" -@interface XPDressSearchViewController () + +#import "ShoppingMallItemPreview.h" + +@interface XPDressSearchViewController () ///搜索 @property (nonatomic,strong) XPHomeSearchNavView *searchView; @@ -47,14 +51,55 @@ - (void)viewDidLoad { [super viewDidLoad]; + + self.view.backgroundColor = UIColorFromRGB(0x02061D); + + [self setupNavigationBar]; [self initSubViews]; [self initSubViewConstraints]; + + @kWeakify(self); + [self.presenter getFriends:^(NSArray * _Nonnull users) { + @kStrongify(self); + NSMutableArray *tempArray = @[].mutableCopy; + for (UserInfoModel *model in users) { + HomeSearchResultModel *resultModel = [[HomeSearchResultModel alloc] initFromUserInfo:model]; + [tempArray addObject:resultModel]; + } + self.datasource = tempArray.copy; + [self.tableView reloadData]; + } failure:^(NSError * _Nonnull error) { + + }]; +} + +- (void)setupNavigationBar { + UILabel *titleLabel = [self titleLabel]; + UIButton *backButton = [self backButton]; + [self.view addSubview:titleLabel]; + [self.view addSubview:backButton]; + + [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerX.mas_equalTo(self.view); + make.top.mas_equalTo(self.view).offset(44 + 11); + make.height.mas_equalTo(22); + }]; + + [backButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.leading.mas_equalTo(self.view).offset(16); + make.centerY.mas_equalTo(titleLabel); + make.size.mas_equalTo(CGSizeMake(22, 22)); + }]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } +- (void)didTapBack { + [self.navigationController popViewControllerAnimated:YES]; +} + #pragma mark - Public Method - (void)searchText:(NSString *)text { NSString * type = @"2"; @@ -69,7 +114,8 @@ - (void)initSubViewConstraints { [self.searchView mas_makeConstraints:^(MASConstraintMaker *make) { - make.leading.trailing.top.mas_equalTo(self.view); + make.top.mas_equalTo(self.view).offset(kNavigationHeight); + make.leading.trailing.mas_equalTo(self.view); make.height.mas_equalTo(kNavigationHeight); }]; [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) { @@ -105,17 +151,29 @@ #pragma mark - XPDressShopSearchTableViewCellDelegate - (void)xPDressShopSearchTableViewCellSendButtonClick:(XPDressShopSearchTableViewCell *)cell { - NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; - HomeSearchResultModel * resultModel = [self.datasource xpSafeObjectAtIndex:indexPath.row]; - [self showLoading]; - [Api requestSendDress:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { - [self hideHUD]; - if (code == 200) { - [self showSuccessToast:YMLocalizedString(@"XPDressSearchViewController0")]; - } else { - [self showErrorToast:msg]; - } - } id:self.dressId targetUid:resultModel.uid]; + + ShoppingMallItemPreview *preview = [[ShoppingMallItemPreview alloc] initWith:self.selectedModel + isForGive:YES]; + preview.frame = CGRectMake(0, 0, 284, 353); + [TTPopup popupView:preview style:TTPopupStyleAlert]; + @kWeakify(self); + [preview setGiveWith:^(DressUpShopModel * _Nonnull model) { + @kStrongify(self); + @kWeakify(self); + NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; + HomeSearchResultModel * resultModel = [self.datasource xpSafeObjectAtIndex:indexPath.row]; + [self showLoading]; + [Api requestSendDress:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + @kStrongify(self); + [self hideHUD]; + if (code == 200) { + [TTPopup dismiss]; + [self showSuccessToast:YMLocalizedString(@"XPDressSearchViewController0")]; + } else { + [self showErrorToast:msg]; + } + } id:self.selectedModel.dressUpId targetUid:resultModel.uid]; + }]; } #pragma mark - XPHomeSearchProtocol @@ -181,4 +239,25 @@ } return _searchView; } + +- (UIButton *)backButton { + UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom]; + [b setImage:[kImage(@"vip_center_back_button") ms_SetImageForRTL] + forState:UIControlStateNormal]; + [b addTarget:self + action:@selector(didTapBack) + forControlEvents:UIControlEventTouchUpInside]; + return b; +} + +- (UILabel *)titleLabel { + UILabel *label = [[UILabel alloc] init]; + label.textAlignment = NSTextAlignmentCenter; + label.font = kFontMedium(17); + label.text = YMLocalizedString(@"1.0.30_text_11"); + label.textColor = UIColorFromRGB(0xD9E7F7); + return label; +} + + @end diff --git a/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopCardViewController.m b/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopCardViewController.m index a5d6a3fe..82fc57c2 100644 --- a/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopCardViewController.m +++ b/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopCardViewController.m @@ -55,8 +55,8 @@ ///赠送装扮 - (void)xPDressUpShopCardTableViewCellSendDress:(XPDressUpShopCardTableViewCell *)view dressId:(NSString *)dressId { XPDressSearchViewController *vc = [[XPDressSearchViewController alloc] init]; - vc.dressType = self.type; - vc.dressId = dressId; +// vc.dressType = self.type; +// vc.dressId = dressId; [self.navigationController pushViewController:vc animated:YES]; } diff --git a/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopListViewController.m b/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopListViewController.m index 8dd58113..0fa6f1ba 100644 --- a/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopListViewController.m +++ b/YuMi/Modules/YMMine/View/DressUp/View/XPDressUpShopListViewController.m @@ -53,10 +53,11 @@ } #pragma mark - XPDressUpShopCollectionViewCellDelegate -- (void)xPDressUpShopCollectionViewCellSendDress:(XPDressUpShopCollectionViewCell *)view dressId:(NSString *)dressId { +- (void)xPDressUpShopCollectionViewCellSendDress:(XPDressUpShopCollectionViewCell *)view + dressId:(NSString *)dressId { XPDressSearchViewController *vc = [[XPDressSearchViewController alloc] init]; - vc.dressType = self.type; - vc.dressId = dressId; +// vc.dressType = self.type; +// vc.dressId = dressId; [self.navigationController pushViewController:vc animated:YES]; } diff --git a/YuMi/Modules/YMMine/View/DressUp/View/XPMineDressUpListViewController.m b/YuMi/Modules/YMMine/View/DressUp/View/XPMineDressUpListViewController.m index cd891173..9a89c57e 100644 --- a/YuMi/Modules/YMMine/View/DressUp/View/XPMineDressUpListViewController.m +++ b/YuMi/Modules/YMMine/View/DressUp/View/XPMineDressUpListViewController.m @@ -94,7 +94,6 @@ - (void)useHeadwearSuccess:(NSString *)headWearId { [self.presenter getUserHeadwearList]; [self showSuccessToast:headWearId.integerValue == 0 ? YMLocalizedString(@"XPMineDressUpViewController6") : YMLocalizedString(@"XPMineDressUpListViewController1")]; - } - (void)useCarSuccess:(NSString *)carId { diff --git a/YuMi/Modules/YMMine/View/XPMineViewController.m b/YuMi/Modules/YMMine/View/XPMineViewController.m index b295fc6e..edfe7324 100644 --- a/YuMi/Modules/YMMine/View/XPMineViewController.m +++ b/YuMi/Modules/YMMine/View/XPMineViewController.m @@ -47,8 +47,8 @@ #import "XPWebViewController.h" #import "XPRoomViewController.h" -#import "XPMineDressUpViewController.h" -#import "XPDressUpShopViewController.h" +#import "MyDressingViewController.h" +#import "ShoppingMallViewController.h" #import "XPMineFansViewController.h" #import "XPMineAttentionViewController.h" #import "XPMineVisitorViewController.h" @@ -70,6 +70,8 @@ #import "VIPCenterViewController.h" #import "VipSettingViewController.h" +#import "XPSkillCardPlayerManager.h" + UIKIT_EXTERN NSString *kRequestTicket; @@ -276,13 +278,13 @@ UIKIT_EXTERN NSString *kRequestTicket; break; case XPMineItemType_My_DressUp: { - XPMineDressUpViewController * dressUpVC = [[XPMineDressUpViewController alloc] init]; + MyDressingViewController * dressUpVC = [[MyDressingViewController alloc] init]; [self.navigationController pushViewController:dressUpVC animated:YES]; } break; case XPMineItemType_DressUp_Market: { - XPDressUpShopViewController *dressUpShopVc = [[XPDressUpShopViewController alloc] init]; + ShoppingMallViewController *dressUpShopVc = [[ShoppingMallViewController alloc] init]; [self.navigationController pushViewController:dressUpShopVc animated:YES]; } break; @@ -346,7 +348,7 @@ UIKIT_EXTERN NSString *kRequestTicket; } - (void)toMineItems { - XPMineDressUpViewController *vc = [[XPMineDressUpViewController alloc] init]; + MyDressingViewController *vc = [[MyDressingViewController alloc] init]; [self.navigationController pushViewController:vc animated:YES]; } @@ -641,6 +643,9 @@ UIKIT_EXTERN NSString *kRequestTicket; } - (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo { + + [XPSkillCardPlayerManager shareInstance].userInfoModel = userInfo; + ///防止重新注册时,获取到用户信息不全,调用接口时401 [self hideHUD]; if (!userInfo.isBindPhone && [ClientConfig shareConfig].iOSPhoneBind) { diff --git a/YuMi/Modules/YMNewHome/Presenter/XPHomeContainerPresenter.m b/YuMi/Modules/YMNewHome/Presenter/XPHomeContainerPresenter.m index 1c0fa092..ffde9283 100644 --- a/YuMi/Modules/YMNewHome/Presenter/XPHomeContainerPresenter.m +++ b/YuMi/Modules/YMNewHome/Presenter/XPHomeContainerPresenter.m @@ -133,7 +133,6 @@ @kWeakify(self); [Api getHomeTabsCompletion:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { @kStrongify(self); - // TODO: 不能在 API call 的地方返回 UI 元素 NSArray * array = [PIHomeCategoryTitleModel modelsWithArray:data.data]; for (PIHomeCategoryTitleModel *model in array) { model.checkedWidth = [UILabel getWidthWithText:model.name height:kGetScaleWidth(44) font:kFontSemibold(16)]; diff --git a/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.h b/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.h index 6e3d06f9..a04b30dd 100644 --- a/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.h +++ b/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.h @@ -8,6 +8,7 @@ #import #import "YUMINNNN.h" #import "UserLevelVo.h" +#import "UserInfoModel.h" NS_ASSUME_NONNULL_BEGIN @@ -33,6 +34,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,assign) GenderType gender; ///搜索用户的时候 如果用户在房间中的话 就有roomUid @property (nonatomic,copy) NSString *roomUid; + +- (instancetype)initFromUserInfo:(UserInfoModel *)model; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.m b/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.m index 3ccfe9e4..bc28832f 100644 --- a/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.m +++ b/YuMi/Modules/YMNewHome/View/Search/Model/HomeSearchResultModel.m @@ -9,4 +9,15 @@ @implementation HomeSearchResultModel +- (instancetype)initFromUserInfo:(UserInfoModel *)model { + if (self = [super init]) { + self.userLevelVo = model.userLevelVo; + self.avatar = model.avatar; + self.uid = @(model.uid).stringValue; + self.nick = model.nick; + self.erbanNo = @(model.erbanNo).stringValue; + } + return self; +} + @end diff --git a/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.h b/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.h index 75d4d620..d3d17260 100644 --- a/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.h +++ b/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.h @@ -7,6 +7,8 @@ #import "BaseMvpPresenter.h" +@class UserInfoModel; + NS_ASSUME_NONNULL_BEGIN @interface XPHomeSearchPresenter : BaseMvpPresenter @@ -19,9 +21,8 @@ NS_ASSUME_NONNULL_BEGIN /// 获取首页推荐列表 - (void)getHomeRecommendRoomList; -/// 获取大家都在搜的房间列表 -/// @param sid keyID -- (void)getEveryOneSearchRoomList:(NSString *)sid; +- (void)getFriends:(void(^)(NSArray *users))success + failure:(void(^)(NSError *error))failure; @end diff --git a/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.m b/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.m index eef5c128..989deb22 100644 --- a/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.m +++ b/YuMi/Modules/YMNewHome/View/Search/Presenter/XPHomeSearchPresenter.m @@ -7,6 +7,9 @@ #import "XPHomeSearchPresenter.h" #import "Api+Home.h" +#import "Api+Mine.h" +#import "UserInfoModel.h" +#import #import "XPHomeSearchProtocol.h" #import "AccountInfoStorage.h" #import "HomeSearchResultModel.h" @@ -36,13 +39,31 @@ }] uid:uid]; } -/// 获取大家都在搜的房间列表 -/// @param sid keyID -- (void)getEveryOneSearchRoomList:(NSString *)sid { -// [Api requestEveryOneSearchRoomList:[self createHttpCompletion:^(BaseModel * _Nonnull data) { -// NSArray * array = [HomeRecommendRoomModel modelsWithArray:data.data]; -// [[self getView] everyoneSearchListSuccess:array]; -// }] wordId:sid]; +- (void)getFriends:(void(^)(NSArray *users))success + failure:(void(^)(NSError *error))failure { + NSArray * array = [[NIMSDK sharedSDK].userManager myFriends]; + if (array.count > 0) { + NSMutableArray * uidsArray = [NSMutableArray array]; + for (int i = 0; i< array.count; i++) { + NIMUser * user = [array xpSafeObjectAtIndex:i]; + [uidsArray addObject:user.userId]; + } + NSString *uids = [uidsArray componentsJoinedByString:@","]; + [Api getUsersListInfo:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + NSArray *users= [UserInfoModel modelsWithArray:data.data]; + if (success) { + success(users); + } + } fail:^(NSInteger code, NSString * _Nullable msg) { + if (failure) { + failure([NSError errorWithDomain:msg code:code userInfo:nil]); + } + } showLoading:YES errorToast:YES] uids:uids]; + } else { + if (success) { + success(@[]); + } + } } diff --git a/YuMi/Modules/YMNewHome/View/Search/Protocol/XPHomeSearchProtocol.h b/YuMi/Modules/YMNewHome/View/Search/Protocol/XPHomeSearchProtocol.h index 013c283b..837f0c35 100644 --- a/YuMi/Modules/YMNewHome/View/Search/Protocol/XPHomeSearchProtocol.h +++ b/YuMi/Modules/YMNewHome/View/Search/Protocol/XPHomeSearchProtocol.h @@ -10,14 +10,19 @@ NS_ASSUME_NONNULL_BEGIN @protocol XPHomeSearchProtocol + ///搜索成功 - (void)searchRoomSuccess:(NSArray *)data type:(NSString *)type; +@optional ///搜索页获取推荐房间成功 - (void)searchRoomGetRecommendSuccess:(NSArray *)data; + +@optional ///搜索页获取推荐房间失败 - (void)searchRoomGetRecommendFail; +@optional /// 大家都在搜房间列表成功 - (void)everyoneSearchListSuccess:(NSArray *)list; diff --git a/YuMi/Modules/YMNewHome/View/Search/View/SubView/XPHomeSearchNavView.h b/YuMi/Modules/YMNewHome/View/Search/View/SubView/XPHomeSearchNavView.h index ca8aeb96..fc5bd451 100644 --- a/YuMi/Modules/YMNewHome/View/Search/View/SubView/XPHomeSearchNavView.h +++ b/YuMi/Modules/YMNewHome/View/Search/View/SubView/XPHomeSearchNavView.h @@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN @class XPHomeSearchNavView; @protocol XPHomeSearchNavViewDelegate + +@optional //点击了返回 - (void)xPHomeSearchNavView:(XPHomeSearchNavView *)view didClickBack:(UIButton *)sender; ///点击了搜索 diff --git a/YuMi/Modules/YMNewHome/View/XPHomePagingViewController.m b/YuMi/Modules/YMNewHome/View/XPHomePagingViewController.m index adaab3a4..f1e561ea 100644 --- a/YuMi/Modules/YMNewHome/View/XPHomePagingViewController.m +++ b/YuMi/Modules/YMNewHome/View/XPHomePagingViewController.m @@ -14,8 +14,6 @@ #import "Api+Gift.h" #import "XPGiftStorage.h" -#import "ShoppingMallViewController.h" - @interface XPHomePagingViewController () @property (nonatomic, strong) UIView *topControlView; @@ -166,12 +164,6 @@ #pragma mark - - (void)didTapMineButton { -#if DEBUG - ShoppingMallViewController *vc = [[ShoppingMallViewController alloc] init]; - [self.navigationController pushViewController:vc animated:YES]; - return; -#endif - [self.pageContainer setViewControllers:@[self.viewControllers[1]] direction:UIPageViewControllerNavigationDirectionReverse animated:NO diff --git a/YuMi/Tools/CardManager/XPSkillCardPlayerManager.h b/YuMi/Tools/CardManager/XPSkillCardPlayerManager.h index 3679de07..f47c2247 100644 --- a/YuMi/Tools/CardManager/XPSkillCardPlayerManager.h +++ b/YuMi/Tools/CardManager/XPSkillCardPlayerManager.h @@ -7,6 +7,7 @@ #import #import +#import "UserInfoModel.h" typedef enum : NSUInteger { MICState_None = 0, @@ -38,8 +39,10 @@ typedef enum : NSUInteger { // 用户在 mic 的状态 @property (nonatomic, assign) MICState micState; +// 作为全局获取当前用户数据的 model,需要在相关 user/get 调用处更新,目前只在 mine tab 更新 +@property(nonatomic, strong) UserInfoModel *userInfoModel; -+ (instancetype)shareInstance ; ++ (instancetype)shareInstance; /** 播放一次音频 diff --git a/YuMi/ar.lproj/Localizable.strings b/YuMi/ar.lproj/Localizable.strings index 3493882d..ad1d2b0a 100644 --- a/YuMi/ar.lproj/Localizable.strings +++ b/YuMi/ar.lproj/Localizable.strings @@ -4009,3 +4009,7 @@ ineHeadView12" = "الحمل"; "1.0.30_text_7" = "Mall"; "1.0.30_text_8" = "My Dress"; "1.0.30_text_9" = "Homepage"; +"1.0.30_text_10" = "VIP%@-%@%"; +"1.0.30_text_11" = "Select Friend"; +"1.0.30_text_12" = "Not used"; +"1.0.30_text_13" = "<1Day"; diff --git a/YuMi/en.lproj/Localizable.strings b/YuMi/en.lproj/Localizable.strings index a00cb5cc..eb295ce2 100644 --- a/YuMi/en.lproj/Localizable.strings +++ b/YuMi/en.lproj/Localizable.strings @@ -3802,3 +3802,7 @@ "1.0.30_text_7" = "Mall"; "1.0.30_text_8" = "My Dress"; "1.0.30_text_9" = "Homepage"; +"1.0.30_text_10" = "VIP%@-%@%"; +"1.0.30_text_11" = "Select Friend"; +"1.0.30_text_12" = "Not used"; +"1.0.30_text_13" = "<1Day"; diff --git a/YuMi/tr.lproj/Localizable.strings b/YuMi/tr.lproj/Localizable.strings index 3295c489..13237696 100644 --- a/YuMi/tr.lproj/Localizable.strings +++ b/YuMi/tr.lproj/Localizable.strings @@ -3588,3 +3588,8 @@ "1.0.30_text_7" = "Mall"; "1.0.30_text_8" = "My Dress"; "1.0.30_text_9" = "Homepage"; +"1.0.30_text_10" = "VIP%@-%@%"; +"1.0.30_text_11" = "Select Friend"; +"1.0.30_text_12" = "Not used"; +"1.0.30_text_13" = "<1Day"; +"1.0.30_text_14" = "%@Day"; diff --git a/YuMi/zh-Hant.lproj/Localizable.strings b/YuMi/zh-Hant.lproj/Localizable.strings index a27fc807..44577eb9 100644 --- a/YuMi/zh-Hant.lproj/Localizable.strings +++ b/YuMi/zh-Hant.lproj/Localizable.strings @@ -3460,3 +3460,7 @@ "1.0.30_text_7" = "Mall"; "1.0.30_text_8" = "My Dress"; "1.0.30_text_9" = "Homepage"; +"1.0.30_text_10" = "VIP%@-%@%%"; +"1.0.30_text_11" = "Select Friend"; +"1.0.30_text_12" = "Not used"; +"1.0.30_text_13" = "<1Day";