diff --git a/YuMi/Modules/YMMine/Model/Medals/MedalsModel.h b/YuMi/Modules/YMMine/Model/Medals/MedalsModel.h index c9ae5a9b..3f3f4166 100644 --- a/YuMi/Modules/YMMine/Model/Medals/MedalsModel.h +++ b/YuMi/Modules/YMMine/Model/Medals/MedalsModel.h @@ -58,7 +58,7 @@ NS_ASSUME_NONNULL_BEGIN @interface MineAllMedalModel : PIBaseModel @property (nonatomic, copy) NSArray *allMedals; @property (nonatomic, copy) NSDictionary *vipMedalSeatVos; -@property (nonatomic, copy) NSArray *useMedals; +@property (nonatomic, copy) NSArray *useMedals; @property (nonatomic, assign) NSInteger vipLevel; @property (nonatomic, assign) NSInteger medalNum; @end diff --git a/YuMi/Modules/YMMine/Model/Medals/MedalsModel.m b/YuMi/Modules/YMMine/Model/Medals/MedalsModel.m index 6641752e..290106c2 100644 --- a/YuMi/Modules/YMMine/Model/Medals/MedalsModel.m +++ b/YuMi/Modules/YMMine/Model/Medals/MedalsModel.m @@ -44,6 +44,7 @@ + (NSDictionary *)mj_objectClassInArray { return @{ @"allMedals" : [MedalVo class], + @"useMedals" : [MedalVo class], // @"vipMedalSeatVos" : [VipMedalSeatVo class], // @"allMedals" : [MedalVo class], }; diff --git a/YuMi/Modules/YMMine/Presenter/MedalsPresenter.h b/YuMi/Modules/YMMine/Presenter/MedalsPresenter.h index 440d5818..e8a785d6 100644 --- a/YuMi/Modules/YMMine/Presenter/MedalsPresenter.h +++ b/YuMi/Modules/YMMine/Presenter/MedalsPresenter.h @@ -25,6 +25,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)rankListSuccess:(MedalsRankModel *)model; - (void)rankListFailure; +- (void)useMedalSuccess; +- (void)userMedalsFailure; + @end @interface MedalsPresenter : BaseMvpPresenter diff --git a/YuMi/Modules/YMMine/Presenter/MedalsPresenter.m b/YuMi/Modules/YMMine/Presenter/MedalsPresenter.m index 0b6f86ad..b3f5b72a 100644 --- a/YuMi/Modules/YMMine/Presenter/MedalsPresenter.m +++ b/YuMi/Modules/YMMine/Presenter/MedalsPresenter.m @@ -70,10 +70,17 @@ - (void)updateMedalUseStatus:(NSString *)medalId isUse:(BOOL)isUse { + @kWeakify(self); [Api medalUseMedal:[self createHttpCompletion:^(BaseModel * _Nonnull data) { - + @kStrongify(self); + if ([[self getView] respondsToSelector:@selector(useMedalSuccess)]) { + [[self getView] useMedalSuccess]; + } } fail:^(NSInteger code, NSString * _Nullable msg) { - + @kStrongify(self); + if ([[self getView] respondsToSelector:@selector(userMedalsFailure)]) { + [[self getView] userMedalsFailure]; + } } showLoading:YES errorToast:YES] id:medalId useStatus:@(isUse == YES ? 1 : 0)]; } diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsViewController.m b/YuMi/Modules/YMMine/View/Medals/MedalsViewController.m index 747f9885..b6fb563a 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsViewController.m +++ b/YuMi/Modules/YMMine/View/Medals/MedalsViewController.m @@ -243,12 +243,25 @@ typedef enum : NSInteger { } - (void)setupWearingButton { + UIView *wearingBg = [[UIView alloc] init]; + [wearingBg addGradientBackgroundWithColors:@[ + UIColorFromRGB(0xf2e7ff), + UIColorFromRGB(0xb497f6) + ] startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) cornerRadius:25/2]; + [wearingBg setAllCornerRadius:25/2 borderWidth:1 borderColor:[UIColor whiteColor]]; + [self.view addSubview:wearingBg]; + + UIButton *wearingButton = [self wearingButton]; [self.view addSubview:wearingButton]; [wearingButton mas_makeConstraints:^(MASConstraintMaker *make) { make.top.mas_equalTo(90); make.trailing.mas_equalTo(-12); }]; + + [wearingBg mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(wearingButton).insets(UIEdgeInsetsMake(0, -15, 0, -25)); + }]; } - (void)setupEmptyUserMedals { @@ -449,6 +462,12 @@ typedef enum : NSInteger { } } +- (void)_updateWearingInfo { + if (self.displayType != MedalsCenterDisplayType_Other) { + + } +} + - (void)_updateOtherInfo:(UserMedalsModel *)userModel { if (self.displayType == MedalsCenterDisplayType_Other) { self.otherAvatar.imageUrl = userModel.avatar; @@ -612,6 +631,8 @@ typedef enum : NSInteger { UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button addTarget:self action:@selector(didTapWearingButton:) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:YMLocalizedString(@"20.20.61_text_2") forState:UIControlStateNormal]; + [button setTitleColor:UIColorFromRGB(0x201440) forState:UIControlStateNormal]; + button.titleLabel.font = kFontMedium(12); return button; } diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.h b/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.h index becfa8e7..b7a67770 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.h +++ b/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.h @@ -7,6 +7,8 @@ #import +@class MedalVo; + NS_ASSUME_NONNULL_BEGIN @interface MedalsWearingControlCollectionViewCell : UICollectionViewCell @@ -15,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)cellFor:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)index; - (void)updateVIPLevel:(NSInteger)level; +- (void)updateMedal:(MedalVo *)medalVo; @end diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.m b/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.m index eb729606..b4e089d0 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.m +++ b/YuMi/Modules/YMMine/View/Medals/MedalsWearingControlCollectionViewCell.m @@ -6,11 +6,48 @@ // #import "MedalsWearingControlCollectionViewCell.h" +#import "MedalsModel.h" + +@interface VipPill : UIView + +- (void)updateLevel:(NSInteger)level; + +@end + +@implementation VipPill { + UILabel *contentLabel; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + [self addGradientBackgroundWithColors:@[ + UIColorFromRGB(0xf2e7ff), + UIColorFromRGB(0xb497f6) + ] startPoint:CGPointMake(0, 0.5) endPoint:CGPointMake(1, 0.5) cornerRadius:6.5]; + [self setAllCornerRadius:6.5 borderWidth:1 borderColor:[UIColor whiteColor]]; + + contentLabel = [UILabel labelInitWithText:@"VIP" font:kFontHeavy(10) textColor:UIColorFromRGB(0x1b0043)]; + [self addSubview:contentLabel]; + [contentLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self); + }]; + } + return self; +} + +- (void)updateLevel:(NSInteger)level { + contentLabel.text = [NSString stringWithFormat:@"VIP%@", @(level)]; +} + +@end @interface MedalsWearingControlCollectionViewCell () @property (nonatomic, strong) NetImageView *medalImageView; @property (nonatomic, strong) UIImageView *vipImageView; +@property (nonatomic, strong) VipPill *pill; @end @@ -31,10 +68,36 @@ } - (void)updateVIPLevel:(NSInteger)level { - self.vipImageView.hidden = level < 1; + if (level <= 0) { + self.pill.hidden = YES; + self.vipImageView.hidden = YES; + return; + } + + self.vipImageView.hidden = NO; NSString *imagePath = [NSString stringWithFormat:@"medals_control_vip%@", @(level)]; self.vipImageView.image = kImage(imagePath); + + self.pill.hidden = self.vipImageView.hidden; + [self.pill updateLevel:level]; +} + +- (void)updateMedal:(MedalVo *)medalVo { + if (!medalVo) { + self.medalImageView.imageUrl = @""; +#if DEBUG + self.medalImageView.backgroundColor = [UIColor clearColor]; +#endif + return; + } + if (![medalVo.picUrl hasSuffix:@"mp4"]) { + self.medalImageView.imageUrl = medalVo.picUrl; + } + +#if DEBUG + self.medalImageView.backgroundColor = [UIColor redColor]; +#endif } - (instancetype)initWithFrame:(CGRect)frame @@ -43,6 +106,7 @@ if (self) { [self.contentView addSubview:self.medalImageView]; [self.contentView addSubview:self.vipImageView]; + [self.contentView addSubview:self.pill]; [self.medalImageView mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.contentView); @@ -52,6 +116,9 @@ make.centerY.mas_equalTo(self.contentView.mas_bottom); make.size.mas_equalTo(CGSizeMake(32, 13)); }]; + [self.pill mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.vipImageView); + }]; } return self; } @@ -73,4 +140,11 @@ return _vipImageView; } +- (VipPill *)pill { + if (!_pill) { + _pill = [[VipPill alloc] initWithFrame:CGRectZero]; + } + return _pill; +} + @end diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.h b/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.h index 46fc06c1..aaea6eeb 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.h +++ b/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.h @@ -16,6 +16,10 @@ NS_ASSUME_NONNULL_BEGIN - (void)updateCell:(MedalVo *)medalModel; +// 可见性管理 +- (void)willDisplay; +- (void)didEndDisplaying; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.m b/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.m index ef84850f..592420d6 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.m +++ b/YuMi/Modules/YMMine/View/Medals/MedalsWearingListCollectionViewCell.m @@ -55,6 +55,7 @@ self = [super initWithFrame:frame]; if (self) { [self setupUI]; + [self setupNotifications]; } return self; } @@ -168,6 +169,51 @@ } } +#pragma mark - 可见性管理 + +- (void)willDisplay { + self.isVisible = YES; + [self resumeMP4Playback]; +} + +- (void)didEndDisplaying { + self.isVisible = NO; + [self pauseMP4Playback]; +} + +#pragma mark - 通知处理 + +- (void)appDidEnterBackground { + [self pauseMP4Playback]; +} + +- (void)appWillEnterForeground { + if (self.isVisible) { + [self resumeMP4Playback]; + } +} + +- (void)didReceiveMemoryWarning { + // 内存警告时停止播放 + if (!self.isVisible) { + [self stopMP4Playback]; + } +} + +#pragma mark - 生命周期 + +- (void)dealloc { + // 停止播放 + [self stopMP4Playback]; + + // 移除通知观察者 + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + // 清理资源 + self.mp4Parser = nil; + NSLog(@"MedalsWearingListCollectionViewCell dealloc"); +} + #pragma mark - - (VAPView *)mp4View { if (!_mp4View) { @@ -188,4 +234,39 @@ return _selectedImageView; } +- (void)setupNotifications { + // 监听应用进入后台和恢复前台的通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appDidEnterBackground) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(appWillEnterForeground) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + + // 监听内存警告通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didReceiveMemoryWarning) + name:UIApplicationDidReceiveMemoryWarningNotification + object:nil]; +} + +- (void)prepareForReuse { + [super prepareForReuse]; + + // 停止播放 + [self stopMP4Playback]; + + // 隐藏 mp4 视图 + self.mp4View.hidden = YES; + self.imageView.hidden = NO; + + // 重置状态 + self.mp4Path = nil; + self.imagePath = nil; + self.isVisible = NO; +} + @end diff --git a/YuMi/Modules/YMMine/View/Medals/MedalsWearingViewController.m b/YuMi/Modules/YMMine/View/Medals/MedalsWearingViewController.m index 2a8dc277..22ed9152 100644 --- a/YuMi/Modules/YMMine/View/Medals/MedalsWearingViewController.m +++ b/YuMi/Modules/YMMine/View/Medals/MedalsWearingViewController.m @@ -11,7 +11,7 @@ #import "MedalsWearingControlCollectionViewCell.h" #import "MJRefresh.h" -@interface MedalsWearingViewController () +@interface MedalsWearingViewController () @property (nonatomic, strong) UIView *dismissArea; @property (nonatomic, strong) UIView *contentArea; @@ -21,8 +21,8 @@ @property (nonatomic, assign) NSInteger medalsAreaPage; +@property (nonatomic, copy) NSArray *useMedalsVo; @property (nonatomic, copy) NSArray *allMedalsVo; -//@property (nonatomic, copy) NSArray *vipSeatVo; @property (nonatomic, copy) NSDictionary *vipSeatDic; @property (nonatomic, assign) NSInteger minVipLevelForSeats; @@ -61,7 +61,7 @@ make.height.mas_equalTo(kGetScaleWidth(147)); }]; [self.controlAreaCollectionView mas_makeConstraints:^(MASConstraintMaker *make) { - make.edges.mas_equalTo(self.controlAreaBG).insets(UIEdgeInsetsMake(15, 15, 15, 15)); + make.edges.mas_equalTo(self.controlAreaBG).insets(UIEdgeInsetsMake(15, 15, 0, 15)); }]; [self.contentArea addSubview:self.medalsAreaCollectionView]; @@ -107,6 +107,7 @@ self.vipSeatDic = model.vipMedalSeatVos; self.allMedalsVo = model.allMedals; + self.useMedalsVo = model.useMedals; [self.controlAreaCollectionView reloadData]; [self.medalsAreaCollectionView reloadData]; @@ -121,6 +122,14 @@ } } +- (void)useMedalSuccess { + [self headerRefresh]; +} + +- (void)userMedalsFailure { + +} + - (void)endRefresh { [self.medalsAreaCollectionView.mj_header endRefreshing]; [self.medalsAreaCollectionView.mj_footer endRefreshing]; @@ -140,32 +149,53 @@ if (collectionView == self.controlAreaCollectionView) { MedalsWearingControlCollectionViewCell *cell = [MedalsWearingControlCollectionViewCell cellFor:collectionView atIndexPath:indexPath]; - // 根据 vipSeatDic 数据判断是否调用 updateVIPLevel - NSString *seatKey = [NSString stringWithFormat:@"%ld", (long)(indexPath.row + 1)]; - NSArray *vipLevels = self.vipSeatDic[seatKey]; - - if (vipLevels && vipLevels.count > 0) { - // 找到最低的 VIP level - NSInteger currentMinVipLevel = NSIntegerMax; - for (NSNumber *levelNum in vipLevels) { - NSInteger level = [levelNum integerValue]; - if (level < currentMinVipLevel) { - currentMinVipLevel = level; - } + // 找到 vipSeatDic 的最小 key,判断当前 index 是否适用显示 VIP level + NSInteger minSeatIndex = NSIntegerMax; + for (NSString *key in self.vipSeatDic.allKeys) { + NSInteger seatIndex = [key integerValue]; + if (seatIndex < minSeatIndex) { + minSeatIndex = seatIndex; } - - if (currentMinVipLevel != NSIntegerMax) { - // 更新全局最低VIP level - if (self.minVipLevelForSeats == 0 || currentMinVipLevel < self.minVipLevelForSeats) { - self.minVipLevelForSeats = currentMinVipLevel; - } - [cell updateVIPLevel:currentMinVipLevel]; - } - } else if (self.minVipLevelForSeats > 0) { - // 当前座位没有对应的vip seat vo,但之前已经有最低VIP level,则沿用 - [cell updateVIPLevel:self.minVipLevelForSeats]; } + // 当前 cell 的座位索引(从1开始) + NSInteger currentSeatIndex = indexPath.row + 1; + + // 只有当前座位索引大于等于最小座位索引时,才处理 VIP level 逻辑 + if (minSeatIndex != NSIntegerMax && currentSeatIndex >= minSeatIndex) { + // 根据 vipSeatDic 数据判断是否调用 updateVIPLevel + NSString *seatKey = [NSString stringWithFormat:@"%ld", (long)currentSeatIndex]; + NSArray *vipLevels = self.vipSeatDic[seatKey]; + + if (vipLevels && vipLevels.count > 0) { + // 找到最低的 VIP level + NSInteger currentMinVipLevel = NSIntegerMax; + for (NSNumber *levelNum in vipLevels) { + NSInteger level = [levelNum integerValue]; + if (level < currentMinVipLevel) { + currentMinVipLevel = level; + } + } + + if (currentMinVipLevel != NSIntegerMax) { + // 更新全局最低VIP level + if (self.minVipLevelForSeats == 0 || currentMinVipLevel < self.minVipLevelForSeats) { + self.minVipLevelForSeats = currentMinVipLevel; + } + [cell updateVIPLevel:currentMinVipLevel]; + } + } else if (self.minVipLevelForSeats > 0) { + // 当前座位没有对应的vip seat vo,但之前已经有最低VIP level,则沿用 + [cell updateVIPLevel:self.minVipLevelForSeats]; + } + } else { + // 如果当前座位索引小于最小座位索引,则不显示 VIP level + [cell updateVIPLevel:-1]; + } + + MedalVo *medalVo = [self.useMedalsVo xpSafeObjectAtIndex:indexPath.row]; + [cell updateMedal:medalVo]; + return cell; } else if (collectionView == self.medalsAreaCollectionView) { MedalsWearingListCollectionViewCell *cell = [MedalsWearingListCollectionViewCell cellFor:collectionView atIndexPath:indexPath]; @@ -182,6 +212,19 @@ } } +// 处理 cell 的可见性 +- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if ([cell isKindOfClass:[MedalsWearingListCollectionViewCell class]]) { + [(MedalsWearingListCollectionViewCell *)cell willDisplay]; + } +} + +- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { + if ([cell isKindOfClass:[MedalsWearingListCollectionViewCell class]]) { + [(MedalsWearingListCollectionViewCell *)cell didEndDisplaying]; + } +} + #pragma mark - Refresh Actions - (void)headerRefresh { self.medalsAreaPage = 1; @@ -239,6 +282,7 @@ _controlAreaCollectionView.backgroundColor = [UIColor clearColor]; _controlAreaCollectionView.delegate = self; _controlAreaCollectionView.dataSource = self; + _controlAreaCollectionView.clipsToBounds = NO; [MedalsWearingControlCollectionViewCell registerTo:_controlAreaCollectionView]; }