新增 next-chat.mdc 文件以定义对话上下文的规则;在 Assets.xcassets 中添加多个图像资源及其对应的 Contents.json 文件;更新 AttachmentModel.h 中的枚举值以修正飘屏消息类型;在 SessionViewController.h 和 SessionViewController.m 中添加 userInfo 属性并调整相关逻辑;在 SessionListViewController.h 和 SessionListViewController.m 中优化会话列表的展示逻辑;在多个模型和视图文件中进行小幅调整以提升代码可读性和一致性。

This commit is contained in:
edwinQQQ
2025-07-02 15:52:48 +08:00
parent f0dad8886f
commit 8a096239da
55 changed files with 1708 additions and 432 deletions

View File

@@ -0,0 +1,7 @@
---
description:
globs:
alwaysApply: false
---
本次对话的上下文已经太长了,我打算关掉并重新开一个新的会话。
你有什么想对你的继任者说的,以便它能更好的理解你当前的工作并顺利继续?

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "切图 31@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "切图 70@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "容器 8456@3x (1).png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "容器 8456@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -723,7 +723,7 @@ typedef NS_ENUM(NSUInteger, CustomMessageTypeSuperGift) {
Custom_Message_Sub_Super_Gift_Banner = 1066, // 飘屏
};
///通用飘屏
//CustomMessageType_General_Floating_Screen = 105,
//CustomMessageType_General_Floating_Screen = 107,
typedef NS_ENUM(NSUInteger, CustomMessageTypeGeneralFloatingScreen) {
///所有房间
Custom_Message_Sub_General_Floating_Screen_One_Room = 1071,//单房间

View File

@@ -8,7 +8,7 @@
#import "MvpViewController.h"
#import "SessionListViewController.h"
#import <NIMSDK/NIMSDK.h>
@class UserInfoModel;
NS_ASSUME_NONNULL_BEGIN
@interface SessionViewController : MvpViewController
@@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
///置顶回话
@property (nonatomic,strong) NSMutableDictionary<NIMSession *, NIMStickTopSessionInfo *> *stickTopMessages;
@property (nonatomic, strong) UserInfoModel *userInfo;
@end
NS_ASSUME_NONNULL_END

View File

@@ -104,7 +104,7 @@
///
@property (nonatomic,strong) SessionNavView *sessionNavView;
@property (nonatomic, strong) UITableView * sessionTableView;
@property (nonatomic, strong) UserInfoModel *userInfo;
@property (nonatomic, strong) UserInfoModel *detailUserInfo;
///
@property (nonatomic,strong) NIMMessage *lastMessage;
@@ -159,7 +159,9 @@
[super viewWillAppear:animated];
if (![[[ClientConfig shareConfig].configInfo officialAccountUids] containsObject:self.session.sessionId]) {
[self.presenter getFansLike:self.session.sessionId];
[self.presenter getUserInfoWithUid:self.session.sessionId];
if (!self.userInfo) {
[self.presenter getUserInfoWithUid:self.session.sessionId];
}
}
}
@@ -258,7 +260,6 @@
default:
model = [[MessageUnSupportModel alloc] initWithMessage:message];
break;
}
return model;
}
@@ -595,8 +596,8 @@
[XPSkillCardPlayerManager shareInstance].userInfoModel = userInfo;
} else {
self.userInfo = userInfo;
[self.sessionTableView reloadData];
}
[self.sessionTableView reloadData];
}
#pragma mark - MessageCellDelegate

View File

@@ -7,7 +7,7 @@
// 请注意,这是一次冒险。😱
//
#import "BaseViewController.h"
#import "MvpViewController.h"
#import <JXCategoryView/JXCategoryListContainerView.h>
#import <NIMSDK/NIMSDK.h>
#import <JXPagingView/JXPagerView.h>
@@ -19,7 +19,7 @@ typedef NS_ENUM(NSUInteger, SessionListOpenType) {
SessionListOpenTypeRoom = 2,
};
@interface SessionListViewController : BaseViewController<JXPagerViewListViewDelegate,JXCategoryListContentViewDelegate>
@interface SessionListViewController : MvpViewController<JXPagerViewListViewDelegate,JXCategoryListContentViewDelegate>
- (instancetype)initWithType:(SessionListOpenType)type;
/** 控制器 因为房间内聊天没有控制器去push 或者做其他的操作*/

View File

@@ -20,13 +20,14 @@
#import "XPSessionFindNewViewController.h"
#import "TTPopUp.h"
#import "XPSkillCardPlayerManager.h"
#import "MessagePresenter.h"
#import "MessageProtocol.h"
NSString * const kMessageShowReadDotKey = @"kMessageShowReadDotKey";
#import <Masonry/Masonry.h>
@interface SessionListViewController ()<UITableViewDataSource, UITableViewDelegate, NIMLoginManagerDelegate, NIMConversationManagerDelegate>
@interface SessionListViewController ()<UITableViewDataSource, UITableViewDelegate, NIMLoginManagerDelegate, NIMConversationManagerDelegate, MessageProtocol>
/**
*
@@ -42,6 +43,9 @@ NSString * const kMessageShowReadDotKey = @"kMessageShowReadDotKey";
///
@property (nonatomic,strong) UserInfoModel *userInfo;
@property (nonatomic, copy) void(^scrollCallback)(UIScrollView *scrollView);
@property (nonatomic, strong) NIMRecentSession *recentSession;
@end
@implementation SessionListViewController
@@ -56,6 +60,10 @@ NSString * const kMessageShowReadDotKey = @"kMessageShowReadDotKey";
return YES;
}
- (MessagePresenter *)createPresenter {
return [[MessagePresenter alloc] init];
}
- (instancetype)initWithType:(SessionListOpenType)type {
self = [self init];
if (self) {
@@ -137,6 +145,15 @@ NSString * const kMessageShowReadDotKey = @"kMessageShowReadDotKey";
}];
}
- (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo {
if (userInfo) {
SessionViewController *vc = [[SessionViewController alloc] initWithSession:self.recentSession.session];
vc.openType = self.openType;
vc.userInfo = userInfo;
[self.navigationController pushViewController:vc animated:YES];
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (self.recentSessions.count == 0) {
@@ -157,9 +174,14 @@ NSString * const kMessageShowReadDotKey = @"kMessageShowReadDotKey";
[self.mainController addChildViewController:sessionVC];
} else {
NIMRecentSession *recentSession = self.recentSessions[indexPath.row];
SessionViewController *vc = [[SessionViewController alloc] initWithSession:recentSession.session];
vc.openType = self.openType;
[self.navigationController pushViewController:vc animated:YES];
self.recentSession = recentSession;
if ([[[ClientConfig shareConfig].configInfo officialAccountUids] containsObject:self.recentSession.session.sessionId]) {
SessionViewController *vc = [[SessionViewController alloc] initWithSession:self.recentSession.session];
vc.openType = self.openType;
[self.navigationController pushViewController:vc animated:YES];
} else {
[self.presenter getUserInfoWithUid:recentSession.session.sessionId];
}
}
}

View File

@@ -15,8 +15,8 @@
return YMLocalizedString(@"20.20.61_text_9");
}
// NSDate
NSDate *expireDate = [NSDate dateWithTimeIntervalSince1970:self.expireSeconds];
// + expireSeconds
NSDate *expireDate = [NSDate dateWithTimeIntervalSinceNow:self.expireSeconds];
//
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

View File

@@ -20,6 +20,7 @@ NS_ASSUME_NONNULL_BEGIN
//充值banner位数据
@property(nonatomic,copy) NSString *bannerUrl;
@property(nonatomic,copy) NSString *linkUrl;
@property (nonatomic, assign) NSInteger chargeGoldNum;
@end

View File

@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, copy)NSString *diamonds;
//金币数量
@property(nonatomic, assign) double golds;
@property(nonatomic, copy)NSString *chargeGoldNum;
@property(nonatomic, copy) NSString *chargeGoldNum;
@property(nonatomic, assign)NSInteger amount;
/// 钻石数量

View File

@@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)userMedalsSuccess:(UserMedalsModel *)userMedalsModel;
- (void)userMedalsFailure;
- (void)squareMedalsSuccess:(NSArray <MedalSeriesVo *> *)squareMedalsModel;
- (void)squareMedalsSuccess:(NSArray <MedalSeriesItemVo *> *)squareMedalsModel;
- (void)squareMedalsFailure;
- (void)mineAllMedalsSuccess:(MineAllMedalModel *)model;

View File

@@ -156,6 +156,7 @@
}
- (void)setUserMedalModel:(UserMedalModel *)userMedalModel {
_userMedalModel = userMedalModel;
self.icon.hidden = YES;
self.vapView.hidden = NO;
@@ -168,21 +169,99 @@
}];
self.nameLabel.text = userMedalModel.medalName;
if (self.videoUrl.length > 0) {
[self.vapView playHWDMP4:self.videoUrl repeatCount:-1 delegate:nil];
} else {
NSString *resourcePath = [userMedalModel.picUrl pureURLString];
if (resourcePath.length > 0) {
@kWeakify(self);
[self.vapParser parseWithURL:resourcePath completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (videoUrl.length) {
[self.vapView playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
}
} failureBlock:^(NSError * _Nullable error) {
}];
}
//
[self.vapView stopHWDMP4];
//
NSString *mp4Url = userMedalModel.mp4Url;
NSString *picUrl = userMedalModel.picUrl;
// 1. 使 mp4Url vapView mp4
if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) {
[self playMP4WithUrl:mp4Url];
return;
}
// 2. mp4Url picUrl
if (![NSString isEmpty:picUrl] && [NSString isValidImageURL:picUrl]) {
//
[self showImageWithUrl:picUrl];
return;
}
// 3. picUrl 使 picUrl vapView
if (![NSString isEmpty:picUrl]) {
[self playMP4WithUrl:picUrl];
return;
}
//
[self showDefaultState];
}
#pragma mark -
/// MP4 URL
- (BOOL)isValidMP4URL:(NSString *)url {
if ([NSString isEmpty:url]) {
return NO;
}
NSString *lowercaseUrl = [url lowercaseString];
return [lowercaseUrl hasSuffix:@".mp4"] ||
[lowercaseUrl containsString:@"mp4"] ||
[lowercaseUrl containsString:@"video"];
}
/// URL
- (BOOL)isValidImageURL:(NSString *)url {
if ([NSString isEmpty:url]) {
return NO;
}
NSString *lowercaseUrl = [url lowercaseString];
return [lowercaseUrl hasSuffix:@".jpg"] ||
[lowercaseUrl hasSuffix:@".jpeg"] ||
[lowercaseUrl hasSuffix:@".png"] ||
[lowercaseUrl hasSuffix:@".gif"] ||
[lowercaseUrl hasSuffix:@".webp"] ||
[lowercaseUrl containsString:@"image"];
}
/// MP4
- (void)playMP4WithUrl:(NSString *)url {
self.vapView.hidden = NO;
self.icon.hidden = YES;
NSString *resourcePath = [url pureURLString];
if (resourcePath.length > 0) {
@kWeakify(self);
[self.vapParser parseWithURL:resourcePath completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (videoUrl.length) {
[self.vapView playHWDMP4:videoUrl repeatCount:-1 delegate:nil];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
// MP4
[self showDefaultState];
}];
}
}
///
- (void)showImageWithUrl:(NSString *)url {
self.vapView.hidden = YES;
self.icon.hidden = NO;
self.icon.imageUrl = url;
}
///
- (void)showDefaultState {
self.vapView.hidden = YES;
self.icon.hidden = NO;
self.icon.imageUrl = @""; //
}
- (NetImageView *)icon {

View File

@@ -76,6 +76,7 @@
- (void)handleTapFirstCharge {
XPWebViewController *webVC = [[XPWebViewController alloc] initWithRoomUID:@""];
webVC.url = URLWithType(kFirstChargeBanner);
webVC.isPush = YES;
[self.navigationController pushViewController:webVC animated:YES];
}

View File

@@ -6,7 +6,7 @@
//
#import <UIKit/UIKit.h>
@class MedalSeriesVo;
@class MedalSeriesItemVo;
NS_ASSUME_NONNULL_BEGIN
@interface MedalsCollectionViewCell : UICollectionViewCell
@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void)registerTo:(UICollectionView *)collectionView;
+ (instancetype)cellFor:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)index;
- (void)updateCell:(MedalSeriesVo *)model;
- (void)updateCell:(MedalSeriesItemVo *)model isForSquare:(BOOL)isSquare;
/**
* 当 cell 将要显示时调用

View File

@@ -146,9 +146,12 @@
//
[self stopMP4Playback];
// mp4
// mp4View
[self resetMP4View];
//
self.mp4View.hidden = YES;
self.imageView.hidden = NO;
self.imageView.hidden = YES;
//
self.mp4Path = nil;
@@ -157,6 +160,7 @@
self.displayModel = nil; //
self.currentItemVo = nil; //
//
self.titleLabel.text = @"";
self.subLabel.text = @"";
@@ -169,27 +173,26 @@
self.imageView.imageUrl = @"";
}
- (void)updateCell:(MedalSeriesVo *)model {
MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0];
self.currentItemVo = itemVos;
self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:0];
- (void)updateCell:(MedalSeriesItemVo *)model isForSquare:(BOOL)isSquare {
// MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0];
self.currentItemVo = model;
//
[self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel];
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
//
//
self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeNormal;
// 使 URL
for (NSInteger i = 0; i < itemVos.medalVos.count; i++) {
MedalVo *medalVo = [itemVos.medalVos xpSafeObjectAtIndex:i];
if (medalVo) {
NSString *imageUrl = [self getImageUrlForMedal:medalVo];
[self.levelIndicatorView setImageUrl:imageUrl forLevel:i + 1];
}
//
[self.levelIndicatorView setupWithMaxLevel:model.medalLevel];
if (isSquare) {
self.displayModel = [model.medalVos xpSafeObjectAtIndex:model.medalVos.count - 1];
[self.levelIndicatorView setSelectedLevel:model.medalLevel animated:NO];
} else {
self.displayModel = [model.medalVos xpSafeObjectAtIndex:0];
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
}
self.levelIndicatorView.userInteractionEnabled = !isSquare;
[self updateDisplayWithCurrentModel];
}
@@ -199,11 +202,9 @@
return;
}
// TODO: fix mp4
// MP4 URL
NSString *mp4Url = self.currentItemVo.mp4Url;
NSString *picUrl = self.currentItemVo.picUrl;
NSString *mp4Url = self.displayModel.mp4Url;
NSString *picUrl = self.displayModel.picUrl;
// MP4 URL
if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) {
@@ -229,8 +230,7 @@
[self showDefaultPlaceholder];
//
self.titleLabel.text = self.displayModel.name;
self.subLabel.text = [self.displayModel expireDateString];
[self updateTextLabels];
}
#pragma mark -
@@ -296,6 +296,10 @@
}
- (void)setImagePath:(NSString *)imagePath {
if ([NSString isEmpty:imagePath]) {
self.imageView.hidden = YES;
return;
}
// mp4
[self stopMP4Playback];
@@ -306,8 +310,8 @@
}
- (void)setMp4Path:(NSString *)mp4Path {
// mp4
if ([_mp4Path isEqualToString:mp4Path]) {
if ([NSString isEmpty:mp4Path]) {
self.mp4View.hidden = YES;
return;
}
@@ -366,6 +370,35 @@
#pragma mark - MP4
/// MP4
- (void)resetMP4View {
if (self.mp4View) {
// 1:
[self.mp4View stopHWDMP4];
self.mp4View.tag = 0;
self.mp4View.hidden = YES;
// 2:
if (YES) { // NO
[self.mp4View removeFromSuperview];
_mp4View = nil;
// mp4View
[self.contentView addSubview:self.mp4View];
[self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.imageView);
}];
}
// 3:
// frame
if (NO) { //
CGRect currentFrame = self.mp4View.frame;
self.mp4View.frame = CGRectZero;
self.mp4View.frame = currentFrame;
}
}
}
- (void)stopMP4Playback {
if (self.mp4View) {
[self.mp4View stopHWDMP4];
@@ -375,7 +408,7 @@
- (void)pauseMP4Playback {
if (self.mp4View && !self.mp4View.hidden) {
[self.mp4View pauseHWDMP4];
[self.mp4View stopHWDMP4];
}
}
@@ -404,6 +437,7 @@
NSLog(@"%@", error);
}
#pragma mark - HWDMP4PlayDelegate
- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config {
@@ -428,6 +462,7 @@
- (void)willDisplay {
self.isVisible = YES;
// return;
// MP4
if (self.mp4View.tag == 1 && !self.mp4View.hidden && self.mp4Path) {
@@ -482,7 +517,8 @@
- (VAPView *)mp4View {
if (!_mp4View) {
_mp4View = [[VAPView alloc] init];
_mp4View.contentMode = UIViewContentModeScaleAspectFill;
_mp4View.contentMode = UIViewContentModeScaleAspectFit;
// [_mp4View enableOldVersion:YES];
}
return _mp4View;
}

View File

@@ -0,0 +1,214 @@
//
// MedalsCollectionViewCell_Refactored.m
// YuMi
//
// 使 MedalMediaDisplayManager
//
#import "MedalsCollectionViewCell.h"
#import "MedalsModel.h"
#import "MedalMediaDisplayManager.h"
#import "MedalsLevelIndicatorView.h"
@interface MedalsCollectionViewCell () <MedalMediaDisplayDelegate>
// -
@property (nonatomic, strong) MedalMediaDisplayManager *mediaManager;
// UI
@property (nonatomic, strong) NetImageView *imageView;
@property (nonatomic, strong) VAPView *mp4View;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *subLabel;
@property (nonatomic, strong) MedalsLevelIndicatorView *levelIndicatorView;
//
@property (nonatomic, strong) MedalVo *displayModel;
@property (nonatomic, strong) MedalSeriesItemVo *currentItemVo;
@end
@implementation MedalsCollectionViewCell
+ (NSString *)cellID {
return NSStringFromClass([MedalsCollectionViewCell class]);
}
+ (void)registerTo:(UICollectionView *)collectionView {
[collectionView registerClass:[self class] forCellWithReuseIdentifier:[self cellID]];
}
+ (instancetype)cellFor:(UICollectionView *)collectionView atIndexPath:(NSIndexPath *)index {
MedalsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[self cellID]
forIndexPath:index];
return cell;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setupUI];
[self setupMediaManager];
}
return self;
}
- (void)setupUI {
// UI
[self.contentView addGradientBackgroundWithColors:@[
UIColorFromRGB(0x41007b),
UIColorFromRGB(0x290858)
] startPoint:CGPointMake(0.5, 0) endPoint:CGPointMake(0.5, 1) cornerRadius:8];
[self.contentView setAllCornerRadius:8
borderWidth:1
borderColor:UIColorFromRGB(0xa166bf)];
self.imageView = [[NetImageView alloc] init];
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview:self.imageView];
[self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.top.mas_equalTo(13);
make.leading.trailing.mas_equalTo(self.contentView).inset(13);
make.height.mas_equalTo(self.imageView.mas_width);
}];
self.mp4View = [[VAPView alloc] init];
self.mp4View.contentMode = UIViewContentModeScaleAspectFit;
[self.contentView addSubview:self.mp4View];
[self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.imageView);
}];
// UI...
self.titleLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
self.subLabel = [UILabel labelInitWithText:@"" font:kFontRegular(11) textColor:[UIColor colorWithWhite:1 alpha:0.6]];
// ...
}
- (void)setupMediaManager {
//
self.mediaManager = [[MedalMediaDisplayManager alloc] initWithDelegate:self];
}
- (void)prepareForReuse {
[super prepareForReuse];
// 使 -
[self.mediaManager cleanupResources];
// UI
self.displayModel = nil;
self.currentItemVo = nil;
self.titleLabel.text = @"";
self.subLabel.text = @"";
[self.levelIndicatorView resetToLevel:0];
}
- (void)updateCell:(MedalSeriesVo *)model isForSquare:(BOOL)isSquare {
MedalSeriesItemVo *itemVos = [model.medalSeries xpSafeObjectAtIndex:0];
self.currentItemVo = itemVos;
//
self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeNormal;
[self.levelIndicatorView setupWithMaxLevel:itemVos.medalLevel];
if (isSquare) {
self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:itemVos.medalVos.count - 1];
[self.levelIndicatorView setSelectedLevel:itemVos.medalLevel animated:NO];
} else {
self.displayModel = [itemVos.medalVos xpSafeObjectAtIndex:0];
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
}
self.levelIndicatorView.userInteractionEnabled = !isSquare;
// 使 -
[self.mediaManager updateDisplayWithModel:self.displayModel];
//
[self updateTextLabels];
}
- (void)updateTextLabels {
self.titleLabel.text = self.displayModel.name;
self.subLabel.text = [self.displayModel expireDateString];
}
#pragma mark - -
- (void)willDisplay {
[self.mediaManager willDisplay];
}
- (void)didEndDisplaying {
[self.mediaManager didEndDisplaying];
}
#pragma mark - MedalMediaDisplayDelegate -
- (NSString *)getMP4UrlFromModel:(id)model {
MedalVo *medalVo = (MedalVo *)model;
return medalVo.mp4Url;
}
- (NSString *)getPicUrlFromModel:(id)model {
MedalVo *medalVo = (MedalVo *)model;
return medalVo.picUrl;
}
- (NetImageView *)getImageView {
return self.imageView;
}
- (VAPView *)getMP4View {
return self.mp4View;
}
- (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success {
//
NSLog(@"Media display updated: %@ - %@", isMP4 ? @"MP4" : @"Image", success ? @"Success" : @"Failed");
}
- (UIImage *)getDefaultPlaceholderImage {
return [UIImageConstant defaultEmptyPlaceholder];
}
#pragma mark -
- (void)dealloc {
//
NSLog(@"MedalsCollectionViewCell dealloc");
}
@end
/*
~528
~15070%+
-
- MP4
-
-
- MP4
-
-
- UI
-
-
- UI
1.
2.
3. Bug
4.
5.
*/

View File

@@ -91,9 +91,12 @@
//
[self stopMP4Playback];
// mp4
// mp4View
[self resetMP4View];
//
self.mp4View.hidden = YES;
self.imageView.hidden = NO;
self.imageView.hidden = YES;
//
self.mp4Path = nil;
@@ -179,10 +182,15 @@
}
- (void)setMp4Path:(NSString *)mp4Path {
// mp4
if ([_mp4Path isEqualToString:mp4Path]) {
if ([NSString isEmpty:mp4Path]) {
self.mp4View.hidden = YES;
[self handleMP4FailureWithFallback];
return;
}
// mp4
// if ([_mp4Path isEqualToString:mp4Path]) {
// return;
// }
// mp4
[self stopMP4Playback];
@@ -239,6 +247,35 @@
#pragma mark - MP4
/// MP4
- (void)resetMP4View {
if (self.mp4View) {
// 1:
[self.mp4View stopHWDMP4];
self.mp4View.tag = 0;
self.mp4View.hidden = YES;
// 2:
if (NO) { // NO
[self.mp4View removeFromSuperview];
_mp4View = nil;
// mp4View
[self.contentView addSubview:self.mp4View];
[self.mp4View mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.imageView);
}];
}
// 3:
// frame
if (NO) { //
CGRect currentFrame = self.mp4View.frame;
self.mp4View.frame = CGRectZero;
self.mp4View.frame = currentFrame;
}
}
}
- (void)stopMP4Playback {
if (self.mp4View) {
[self.mp4View stopHWDMP4];
@@ -246,44 +283,33 @@
}
}
- (void)pauseMP4Playback {
if (self.mp4View && !self.mp4View.hidden) {
[self.mp4View pauseHWDMP4];
}
}
- (void)resumeMP4Playback {
if (self.mp4View && !self.mp4View.hidden && self.mp4Path) {
if (self.mp4View.tag == 1) { //
@kWeakify(self);
[self.mp4Parser parseWithURL:self.mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl] && self.isVisible) {
[self startMP4PlaybackWithURL:videoUrl];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
// MP4 使 picURL
[self handleMP4FailureWithFallback];
}];
} else {
[self.mp4View resumeHWDMP4];
}
}
}
#pragma mark -
- (void)willDisplay {
self.isVisible = YES;
// MP4
if (self.mp4View.tag == 1 && !self.mp4View.hidden && self.mp4Path) {
[self resumeMP4Playback];
} else if (!self.mp4View.hidden) {
//
[self resumeMP4Playback];
//
if (!self.mp4View.hidden && self.mp4Path) {
//
[self stopMP4Playback];
//
if (!_mp4Parser) {
self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init];
}
@kWeakify(self);
[self.mp4Parser parseWithURL:self.mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl] && self.isVisible) {
[self startMP4PlaybackWithURL:videoUrl];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
NSLog(@"[MedalsCyclePagerCell] Failed to restart mp4 in willDisplay: %@", error);
[self handleMP4FailureWithFallback];
}];
}
NSLog(@"[MedalsCyclePagerCell] willDisplay - isVisible: %@, mp4Path: %@",
@@ -292,18 +318,34 @@
- (void)didEndDisplaying {
self.isVisible = NO;
[self pauseMP4Playback];
//
[self stopMP4Playback];
}
#pragma mark -
- (void)appDidEnterBackground {
[self pauseMP4Playback];
[self stopMP4Playback];
}
- (void)appWillEnterForeground {
if (self.isVisible) {
[self resumeMP4Playback];
if (self.isVisible && !self.mp4View.hidden && self.mp4Path) {
//
if (!_mp4Parser) {
self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init];
}
@kWeakify(self);
[self.mp4Parser parseWithURL:self.mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl] && self.isVisible) {
[self startMP4PlaybackWithURL:videoUrl];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self handleMP4FailureWithFallback];
}];
}
}
@@ -334,9 +376,7 @@
if (!_mp4View) {
_mp4View = [[VAPView alloc] init];
_mp4View.contentMode = UIViewContentModeScaleAspectFit;
#if DEBUG
_mp4View.backgroundColor = [UIColor redColor];
#endif
// [_mp4View enableOldVersion:YES];
}
return _mp4View;
}

View File

@@ -6,12 +6,12 @@
//
#import <UIKit/UIKit.h>
@class MedalSeriesVo;
@class MedalSeriesItemVo;
NS_ASSUME_NONNULL_BEGIN
@interface MedalsDetailView : UIView
@property (nonatomic, strong) MedalSeriesVo *detailItemVo;
@property (nonatomic, strong) MedalSeriesItemVo *detailItemVo;
@end

View File

@@ -72,6 +72,7 @@
make.centerX.mas_equalTo(self);
make.top.mas_equalTo(self.imageView.mas_bottom).offset(8);
make.leading.trailing.mas_equalTo(self).inset(13);
make.height.mas_equalTo(28);
}];
[self addSubview:self.subLabel];
[self.subLabel mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -85,7 +86,7 @@
[self addSubview:self.levelIndicatorView];
[self.levelIndicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self);
make.top.mas_equalTo(self.subLabel).offset(24);
make.top.mas_equalTo(self.subLabel.mas_bottom).offset(33);
make.leading.trailing.mas_greaterThanOrEqualTo(self).inset(8);
make.height.mas_equalTo(66);
}];
@@ -116,27 +117,34 @@
//
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBackgroundTap:)];
[closeButtonView addGestureRecognizer:tapGesture];
UIButton *back = [UIButton buttonWithType:UIButtonTypeCustom];
[back setBackgroundImage:kImage(@"common_nav_back_white") forState:UIControlStateNormal];
[back addTarget:selfWeak action:@selector(handleBackgroundTap:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:back];
[back mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(16);
make.top.mas_equalTo(kStatusBarHeight);
make.size.mas_equalTo(CGSizeMake(22, 22));
}];
}
- (void)setDetailItemVo:(MedalSeriesVo *)detailItemVo {
_detailItemVo = detailItemVo;
self.currentSeriesItemVO = [detailItemVo.medalSeries xpSafeObjectAtIndex:0];
self.displayModel = [self.currentSeriesItemVO.medalVos xpSafeObjectAtIndex:0];
- (void)setDetailItemVo:(MedalSeriesItemVo *)detailItemVo {
// _detailItemVo = detailItemVo;
self.currentSeriesItemVO = detailItemVo;
self.displayModel = [detailItemVo.medalVos xpSafeObjectAtIndex:0];
[self.levelIndicatorView setupWithMaxLevel:self.currentSeriesItemVO.medalLevel];
[self.levelIndicatorView setSelectedLevel:1 animated:NO];
[self.levelIndicatorView setSeriesItems:detailItemVo.medalSeries];
[self.levelIndicatorView setSeriesItems:detailItemVo.medalVos];
//
self.levelIndicatorView.indicatorType = MedalsLevelIndicatorTypeWithImage;
// 使 URL
for (NSInteger i = 0; i < self.currentSeriesItemVO.medalVos.count; i++) {
MedalVo *medalVo = [self.currentSeriesItemVO.medalVos xpSafeObjectAtIndex:i];
if (medalVo) {
NSString *imageUrl = [self getImageUrlForMedal:medalVo];
[self.levelIndicatorView setImageUrl:imageUrl forLevel:i + 1];
}
for (MedalVo *medalVo in detailItemVo.medalVos) {
NSString *imageUrl = [self getImageUrlForMedal:medalVo];
[self.levelIndicatorView setImageUrl:imageUrl forLevel:medalVo.level];
}
[self updateDisplayWithCurrentModel];

View File

@@ -6,7 +6,7 @@
//
#import <UIKit/UIKit.h>
@class MedalSeriesItemVo;
@class MedalSeriesItemVo, MedalVo;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, MedalsLevelIndicatorType) {
@@ -18,7 +18,7 @@ typedef NS_ENUM(NSInteger, MedalsLevelIndicatorType) {
@property (nonatomic, copy) void (^levelSelectedBlock)(NSInteger level);
@property (nonatomic, assign) MedalsLevelIndicatorType indicatorType;
@property (nonatomic, copy) NSArray <MedalSeriesItemVo *> *seriesItems;
@property (nonatomic, copy) NSArray <MedalVo *> *seriesItems;
- (void)setupWithMaxLevel:(NSInteger)maxLevel;
- (void)setSelectedLevel:(NSInteger)level animated:(BOOL)animated;
@@ -40,7 +40,7 @@ typedef NS_ENUM(NSInteger, MedalsLevelIndicatorType) {
* 设置系列数据,用于处理 MP4 和 PNG 资源
* @param seriesItems MedalSeriesItemVo 数组
*/
- (void)setSeriesItems:(NSArray <MedalSeriesItemVo *> *)seriesItems;
- (void)setSeriesItems:(NSArray <MedalVo *> *)seriesItems;
@end

View File

@@ -610,25 +610,17 @@
}
}
- (void)setSeriesItems:(NSArray <MedalSeriesItemVo *> *)seriesItems {
- (void)setSeriesItems:(NSArray <MedalVo *> *)seriesItems {
_seriesItems = seriesItems;
//
if (!seriesItems || seriesItems.count == 0 || _levelItems.count == 0) {
return;
}
//
MedalSeriesItemVo *firstSeriesItem = [seriesItems xpSafeObjectAtIndex:0];
if (!firstSeriesItem || !firstSeriesItem.medalVos) {
return;
}
// /MP4
for (NSInteger i = 0; i < firstSeriesItem.medalVos.count && i < _levelItems.count; i++) {
MedalVo *medalVo = [firstSeriesItem.medalVos xpSafeObjectAtIndex:i];
for (MedalVo *medalVo in seriesItems) {
if (medalVo && medalVo.picUrl) {
[self setImageUrl:medalVo.picUrl forLevel:i + 1];
[self setImageUrl:medalVo.picUrl forLevel:medalVo.level];
}
}
}

View File

@@ -17,7 +17,7 @@
@property (nonatomic, strong) NetImageView *avatarImageView;
@property (nonatomic, strong) UILabel *nameLabel;
@property (nonatomic, strong) UILabel *countLabel;
@property (nonatomic, strong) UILabel *detailLabel;
+ (void)registerTo:(UITableView *)tableView;
+ (instancetype)cellFor:(UITableView *)tableView atIndexPath:(NSIndexPath *)index;
@@ -46,6 +46,7 @@
self.nameLabel.text = userModel.nick;
self.indexLabel.text = @(userModel.rank).stringValue;
self.countLabel.text = @(userModel.medalCount).stringValue;
// self.detailLabel.hidden = userModel.uid == 0;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
@@ -80,12 +81,12 @@
make.top.mas_equalTo(self.avatarImageView);
}];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:[kImage(@"medals_icon_rank") ms_SetImageForRTL]];
[self.contentView addSubview:rankIcon];
[rankIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(6);
make.bottom.mas_equalTo(self.avatarImageView);
make.size.mas_equalTo(CGSizeMake(10, 14));
make.size.mas_equalTo(CGSizeMake(15, 15));
}];
self.countLabel = [UILabel labelInitWithText:@"" font:kFontMedium(14) textColor:[UIColor whiteColor]];
@@ -95,11 +96,11 @@
make.centerY.mas_equalTo(rankIcon);
}];
UILabel *detailLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_13")
self.detailLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_13")
font:kFontRegular(12)
textColor:[UIColor colorWithWhite:1 alpha:0.6]];
[self.contentView addSubview:detailLabel];
[detailLabel mas_makeConstraints:^(MASConstraintMaker *make) {
[self.contentView addSubview:self.detailLabel];
[self.detailLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.trailing.mas_equalTo(self.contentView).offset(-28);
make.centerY.mas_equalTo(self.contentView);
}];
@@ -175,13 +176,16 @@
nameLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(15) textColor:UIColorFromRGB(0xffffff)];
[self addSubview:nameLabel];
medalIconImageView = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
medalIconImageView = [[UIImageView alloc] initWithImage:kImage(@"medals_icon_rank")];
medalCountLabel = [UILabel labelInitWithText:@"0" font:kFontMedium(14) textColor:UIColorFromRGB(0xffffff)];
medalCountStack = [[UIStackView alloc] initWithArrangedSubviews:@[
medalIconImageView,
medalCountLabel
]];
[self addSubview:medalCountStack];
[medalIconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(15, 15));
}];
honorLabel.hidden = YES;
honorImageView.hidden = YES;
@@ -349,7 +353,7 @@
- (void)setupRankList {
[self.view addSubview:self.rankTableView];
CGFloat height = 84 + kSafeAreaBottomHeight;
CGFloat height = 84;
[self.rankTableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.topTwo.mas_bottom).offset(40);
make.bottom.mas_equalTo(self.view).offset(-height);
@@ -421,6 +425,8 @@
self.countLabel.text = @(self.mineRankModel.medalCount).stringValue;
self.rankList = [NSMutableArray array];
NSInteger currentRank = 4; // 4
for (MedalsRankUserModel *user in model.rankList) {
if (user.rank == 1) {
self.topOne.userModel = user;
@@ -430,8 +436,23 @@
self.topThree.userModel = user;
} else {
[self.rankList addObject:user];
currentRank = MAX(currentRank, user.rank + 1);
}
}
// 10 rankList 7 top
NSInteger targetCount = 7; // 103
while (self.rankList.count < targetCount) {
MedalsRankUserModel *emptyUser = [[MedalsRankUserModel alloc] init];
emptyUser.rank = currentRank;
emptyUser.uid = 0;
emptyUser.avatar = @"";
emptyUser.nick = @"--";
emptyUser.medalCount = 0;
[self.rankList addObject:emptyUser];
currentRank++;
}
[self.rankTableView reloadData];
}
}
@@ -461,11 +482,15 @@
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MedalsRankUserModel *model = [self.rankList xpSafeObjectAtIndex:indexPath.row];
[self handleTopViewTap:model];
//
if (model && model.uid != 0) {
[self handleTopViewTap:model];
}
}
- (void)handleTopViewTap:(MedalsRankUserModel *)model {
if (model) {
if (model && model.uid != 0) {
UserInfoModel *userInfo = [[UserInfoModel alloc] init];
userInfo.uid = model.uid;
userInfo.avatar = model.avatar;

View File

@@ -38,10 +38,11 @@ typedef enum : NSInteger {
@property (nonatomic, strong) TYCyclePagerView *medalsCyclePagerView;
@property (nonatomic, strong) UIView *emptyView;
@property (nonatomic, copy) UICollectionView *medalsCollectionView;
@property (nonatomic, strong) UIStackView *centerTabsStackView;
@property (nonatomic, strong) NSMutableArray <MedalSeriesVo *>*datasourceTaskMedals;
@property (nonatomic, strong) NSMutableArray <MedalSeriesVo *>*datasourceActivityMedals;
@property (nonatomic, strong) NSMutableArray <MedalSeriesVo *>*datasourceGloryMedals;
@property (nonatomic, strong) NSMutableArray <MedalSeriesItemVo *>*datasourceTaskMedals;
@property (nonatomic, strong) NSMutableArray <MedalSeriesItemVo *>*datasourceActivityMedals;
@property (nonatomic, strong) NSMutableArray <MedalSeriesItemVo *>*datasourceGloryMedals;
@property (nonatomic, copy) NSArray <MedalVo *> *useMedals;
@property (nonatomic, assign) NSInteger currentPageTaskMedals;
@@ -52,7 +53,9 @@ typedef enum : NSInteger {
@property (nonatomic, assign) MedalsCenterDisplayType displayType;
@property (nonatomic, strong) UserMedalsModel *userMedalsModel;
@property (nonatomic, copy) NSMutableArray <MedalSeriesVo *>*squareMedalVo;
@property (nonatomic, copy) NSMutableArray <MedalSeriesVo *>*taskSquareMedalVo;
@property (nonatomic, copy) NSMutableArray <MedalSeriesVo *>*activitySquareMedalVo;
@property (nonatomic, copy) NSMutableArray <MedalSeriesVo *>*glorySquareMedalVo;
@property (nonatomic, strong) UIImageView *otherBG;
@property (nonatomic, strong) NetImageView *otherAvatar;
@@ -238,7 +241,7 @@ typedef enum : NSInteger {
[self setupNavigationBar];
if (self.displayType != MedalsCenterDisplayType_Other) {
if (self.displayType == MedalsCenterDisplayType_Mine) {
[self setupWearingButton];
}
}
@@ -322,12 +325,12 @@ typedef enum : NSInteger {
make.top.mas_equalTo(self.otherAvatar);
}];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:kImage(@"medals_rank")];
UIImageView *rankIcon = [[UIImageView alloc] initWithImage:kImage(@"medals_icon_other")];
[self.view addSubview:rankIcon];
[rankIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(self.otherAvatar.mas_trailing).offset(10);
make.bottom.mas_equalTo(self.otherAvatar);
make.size.mas_equalTo(CGSizeMake(14, 18));
make.size.mas_equalTo(CGSizeMake(22, 22));
}];
self.otherCountLabel = [UILabel labelInitWithText:@""
@@ -339,12 +342,12 @@ typedef enum : NSInteger {
make.centerY.mas_equalTo(rankIcon);
}];
self.otherMedal = [[NetImageView alloc] initWithImage:kImage(@"medals_empty")];
self.otherMedal = [[NetImageView alloc] initWithImage:kImage(@"medals_empty_other")];
[self.view addSubview:self.otherMedal];
[self.otherMedal mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(bg);
make.trailing.mas_equalTo(bg).offset(-15);
make.size.mas_equalTo(CGSizeMake(80, 80));
make.size.mas_equalTo(CGSizeMake(81, 81));
}];
[self.view addSubview:self.otherMP4View];
@@ -356,9 +359,9 @@ typedef enum : NSInteger {
}
- (void)setupCenterTabs {
UIStackView *centerTabsStackView = [self centerTabStack];
[self.view addSubview:centerTabsStackView];
[centerTabsStackView mas_makeConstraints:^(MASConstraintMaker *make) {
self.centerTabsStackView = [self centerTabStack];
[self.view addSubview:self.centerTabsStackView];
[self.centerTabsStackView mas_makeConstraints:^(MASConstraintMaker *make) {
if (self.displayType == MedalsCenterDisplayType_Other) {
make.top.mas_equalTo(self.otherBG.mas_bottom).offset(18);
} else {
@@ -384,10 +387,11 @@ typedef enum : NSInteger {
[wearingButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(90);
make.trailing.mas_equalTo(-12);
make.height.mas_equalTo(25);
}];
[wearingBg mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(wearingButton).insets(UIEdgeInsetsMake(0, -15, 0, -25));
make.edges.mas_equalTo(wearingButton).insets(UIEdgeInsetsMake(0, -25, 0, -25));
}];
}
@@ -445,11 +449,7 @@ typedef enum : NSInteger {
[self.medalsCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.mas_equalTo(self.view);
make.trailing.leading.mas_equalTo(self.view).inset(26);
if (self.displayType == MedalsCenterDisplayType_Other) {
make.height.mas_equalTo(kGetScaleWidth(500));
} else {
make.height.mas_equalTo(kGetScaleWidth(380));
}
make.top.mas_equalTo(self.centerTabsStackView.mas_bottom).offset(68);
}];
//
@@ -583,6 +583,32 @@ typedef enum : NSInteger {
}
- (void)squareMedalsSuccess:(NSArray <MedalSeriesVo *>*)squareMedalsModel {
switch (self.currentTabType) {
case MedalsCenterTab_TaskMedals:
if (self.currentPageTaskMedals == 1) {
self.taskSquareMedalVo = squareMedalsModel.mutableCopy;
} else {
[self.taskSquareMedalVo addObjectsFromArray:squareMedalsModel];
}
break;
case MedalsCenterTab_ActivityMedals:
if (self.currentPageActivityMedals == 1) {
self.activitySquareMedalVo = squareMedalsModel.mutableCopy;
} else {
[self.activitySquareMedalVo addObjectsFromArray:squareMedalsModel];
}
break;
case MedalsCenterTab_GloryMedals:
if (self.currentPageGloryMedals == 1) {
self.glorySquareMedalVo = squareMedalsModel.mutableCopy;
} else {
[self.glorySquareMedalVo addObjectsFromArray:squareMedalsModel];
}
break;
default:
break;
}
[self endReresh];
[self _updateDataSource:squareMedalsModel];
[self _updateWearingInfo];
@@ -622,24 +648,25 @@ typedef enum : NSInteger {
NSMutableArray *editArr = [NSMutableArray array];
switch (self.currentTabType) {
case MedalsCenterTab_TaskMedals:
arr = self.datasourceTaskMedals.copy;
arr = self.taskSquareMedalVo.copy;
break;
case MedalsCenterTab_ActivityMedals:
arr = self.datasourceActivityMedals.copy;
arr = self.activitySquareMedalVo.copy;
break;
case MedalsCenterTab_GloryMedals:
arr = self.datasourceGloryMedals.copy;
arr = self.glorySquareMedalVo.copy;
break;
default:
break;
}
for (MedalSeriesVo *seriesVO in arr) {
MedalSeriesItemVo *item = [seriesVO.medalSeries xpSafeObjectAtIndex:0];
if (item) {
MedalVo *medal = [item.medalVos xpSafeObjectAtIndex:0];
if (medal) {
[editArr addObject:medal];
for (MedalSeriesItemVo *item in seriesVO.medalSeries) {
// medalSeries
for (MedalVo *medalVo in item.medalVos) {
if (medalVo.level == item.medalLevel) {
[editArr addObject:medalVo];
}
}
}
}
@@ -651,7 +678,7 @@ typedef enum : NSInteger {
self.emptyUserMedalButton.hidden = YES;
self.medalsCyclePagerView.hidden = NO;
[self.medalsCyclePagerView reloadData];
if (self.useMedals.count > 1 && self.displayType == MedalsCenterDisplayType_Square) {
if (self.useMedals.count > 1 && self.displayType == MedalsCenterDisplayType_Square) {
//
[self startAutoScroll:0];
@@ -722,7 +749,7 @@ typedef enum : NSInteger {
self.otherMedal.imageUrl = imageUrl;
} else {
//
self.otherMedal.image = kImage(@"medals_empty");
self.otherMedal.image = kImage(@"medals_empty_other");
}
}
@@ -782,29 +809,34 @@ typedef enum : NSInteger {
[self.medalsCollectionView.mj_footer resetNoMoreData];
}
NSMutableArray *itemDataSources = [NSMutableArray array];
for (MedalSeriesVo *vo in models) {
[itemDataSources addObjectsFromArray:vo.medalSeries];
}
switch (self.currentTabType) {
case MedalsCenterTab_TaskMedals:
if (self.currentPageTaskMedals == 1) {
self.emptyView.hidden = (models.count != 0);
self.datasourceTaskMedals = models.mutableCopy;
self.datasourceTaskMedals = itemDataSources;
} else {
[self.datasourceTaskMedals addObjectsFromArray:models];
[self.datasourceTaskMedals addObjectsFromArray:itemDataSources];
}
break;
case MedalsCenterTab_ActivityMedals:
if (self.currentPageActivityMedals == 1) {
self.emptyView.hidden = (models.count != 0);
self.datasourceActivityMedals = models.mutableCopy;
self.datasourceActivityMedals = itemDataSources;
} else {
[self.datasourceActivityMedals addObjectsFromArray:models];
[self.datasourceActivityMedals addObjectsFromArray:itemDataSources];
}
break;
case MedalsCenterTab_GloryMedals:
if (self.currentPageGloryMedals == 1) {
self.emptyView.hidden = (models.count != 0);
self.datasourceGloryMedals = models.mutableCopy;
self.datasourceGloryMedals = itemDataSources;
} else {
[self.datasourceGloryMedals addObjectsFromArray:models];
[self.datasourceGloryMedals addObjectsFromArray:itemDataSources];
}
break;
@@ -837,6 +869,7 @@ typedef enum : NSInteger {
- (void)didTapWearingButton:(UIButton *)sender {
MedalsWearingViewController *vc = [[MedalsWearingViewController alloc] init];
vc.userInfo = self.userInfo;
//
@kWeakify(self);
@@ -852,6 +885,7 @@ typedef enum : NSInteger {
- (void)didTapEmptyMedalButton:(UIButton *)sender {
MedalsWearingViewController *vc = [[MedalsWearingViewController alloc] init];
vc.userInfo = self.userInfo;
//
@kWeakify(self);
@@ -900,7 +934,7 @@ typedef enum : NSInteger {
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
MedalsCollectionViewCell *cell = [MedalsCollectionViewCell cellFor:collectionView atIndexPath:indexPath];
[cell updateCell:[self loadModel:indexPath.item]];
[cell updateCell:[self loadModel:indexPath.item] isForSquare:self.displayType == MedalsCenterDisplayType_Square];
return cell;
}
@@ -930,8 +964,8 @@ typedef enum : NSInteger {
[self.view addSubview:view];
}
- (MedalSeriesVo *)loadModel:(NSInteger)row {
MedalSeriesVo *model = nil;
- (MedalSeriesItemVo *)loadModel:(NSInteger)row {
MedalSeriesItemVo *model = nil;
switch (self.currentTabType) {
case MedalsCenterTab_TaskMedals:
model = [self.datasourceTaskMedals xpSafeObjectAtIndex:row];
@@ -948,6 +982,25 @@ typedef enum : NSInteger {
return model;
}
- (MedalSeriesVo *)loadDetailModel:(NSInteger)row {
MedalSeriesVo *model = nil;
switch (self.currentTabType) {
case MedalsCenterTab_TaskMedals:
model = [self.taskSquareMedalVo xpSafeObjectAtIndex:row];
break;
case MedalsCenterTab_ActivityMedals:
model = [self.activitySquareMedalVo xpSafeObjectAtIndex:row];
break;
case MedalsCenterTab_GloryMedals:
model = [self.glorySquareMedalVo xpSafeObjectAtIndex:row];
break;
default:
break;
}
return model;
}
#pragma mark - TYCyclePagerView DataSource & Delegate
- (NSInteger)numberOfItemsInPagerView:(TYCyclePagerView *)pageView {
@@ -980,8 +1033,12 @@ typedef enum : NSInteger {
[self startAutoScroll:toIndex];
}
MedalVo *vo = [self.useMedals xpSafeObjectAtIndex:toIndex];
self.medalDescLabel.text = [vo expireDateString];
if (self.displayType == MedalsCenterDisplayType_Mine) {
MedalVo *vo = [self.useMedals xpSafeObjectAtIndex:toIndex];
self.medalDescLabel.text = [vo expireDateString];
} else {
self.medalDescLabel.text = @"";
}
}
#pragma mark - Lazy load
@@ -1115,7 +1172,12 @@ typedef enum : NSInteger {
_emptyView = [[UIView alloc] init];
_emptyView.backgroundColor = [UIColor clearColor];
UILabel *titleLabel = [UILabel labelInitWithText:YMLocalizedString(@"20.20.61_text_7")
NSString *content = YMLocalizedString(@"20.20.61_text_7.1");
if (self.displayType == MedalsCenterDisplayType_Mine) {
content = YMLocalizedString(@"20.20.61_text_7.2");
}
UILabel *titleLabel = [UILabel labelInitWithText:content
font:kFontRegular(14)
textColor:UIColorFromRGB(0xafb1b3)];
titleLabel.numberOfLines = 2;

View File

@@ -186,9 +186,9 @@
- (void)setMp4Path:(NSString *)mp4Path {
// mp4
if ([_mp4Path isEqualToString:mp4Path]) {
return;
}
// if ([_mp4Path isEqualToString:mp4Path]) {
// return;
// }
// mp4
[self stopMP4Playback];

View File

@@ -6,13 +6,14 @@
//
#import "MvpViewController.h"
@class UserInfoModel;
NS_ASSUME_NONNULL_BEGIN
@interface MedalsWearingViewController : MvpViewController
/// 数据变化回调,当佩戴数据发生改变时触发
@property (nonatomic, copy) void (^dataChangedCallback)(void);
@property (nonatomic, strong) UserInfoModel *userInfo;
@end

View File

@@ -10,6 +10,8 @@
#import "MedalsWearingListCollectionViewCell.h"
#import "MedalsWearingControlCollectionViewCell.h"
#import "MJRefresh.h"
#import "UserInfoModel.h"
#import "XPWebViewController.h"
@interface MedalsWearingViewController () <UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, MedalsPresenterProtocol>
@@ -221,9 +223,87 @@
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
MedalVo *vo = [self.allMedalsVo xpSafeObjectAtIndex:indexPath.row];
if (vo) {
[self.presenter updateMedalUseStatus:vo.id isUse:!vo.useStatus];
if (collectionView == self.controlAreaCollectionView) {
// cell 1
NSInteger currentSeatIndex = indexPath.row + 1;
NSString *seatKey = [NSString stringWithFormat:@"%ld", (long)currentSeatIndex];
NSArray *vipLevels = self.vipSeatDic[seatKey];
// VIP level
NSInteger displayedVipLevel = -1;
// vipSeatDic key
NSInteger minSeatIndex = NSIntegerMax;
for (NSString *key in self.vipSeatDic.allKeys) {
NSInteger seatIndex = [key integerValue];
if (seatIndex < minSeatIndex) {
minSeatIndex = seatIndex;
}
}
// VIP level
if (minSeatIndex != NSIntegerMax && currentSeatIndex >= minSeatIndex) {
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) {
displayedVipLevel = currentMinVipLevel;
}
} else if (self.minVipLevelForSeats > 0) {
displayedVipLevel = self.minVipLevelForSeats;
}
}
UserVipInfoVo *vipVo = self.userInfo.userVipInfoVO;
if (vipVo) {
if (vipVo.vipLevel < displayedVipLevel) {
TTAlertConfig * config = [[TTAlertConfig alloc] init];
// config.actionStyle = 0;
config.title = YMLocalizedString(@"20.20.61_text_17");
config.message = YMLocalizedString(@"20.20.61_text_15");
TTAlertButtonConfig *confirmCongif = config.confirmButtonConfig;
confirmCongif.title = YMLocalizedString(@"20.20.61_text_18");
config.confirmButtonConfig = confirmCongif;
@kWeakify(self);
[TTPopup alertWithConfig:config confirmHandler:^{
@kStrongify(self);
XPWebViewController * webVC =[[XPWebViewController alloc] initWithRoomUID:nil];
webVC.url = URLWithType(kVIP);
[self.navigationController pushViewController:webVC animated:YES];
} cancelHandler:^{
}];
}
}
NSLog(@"[MedalsWearing] 点击位置: %ld, 座位索引: %ld, 显示VIP等级: %ld, VIP数据: %@, 最小座位索引: %ld, 全局最低VIP: %ld",
(long)indexPath.row,
(long)currentSeatIndex,
(long)displayedVipLevel,
vipLevels ?: @"无",
(long)minSeatIndex,
(long)self.minVipLevelForSeats);
} else if (collectionView == self.medalsAreaCollectionView) {
if (self.useMedalsVo.count >= 10) {
TTAlertConfig * config = [[TTAlertConfig alloc] init];
config.actionStyle = 0;
config.title = YMLocalizedString(@"UserDetail_CP_Toast_0");
config.message = YMLocalizedString(@"20.20.61_text_16");
[TTPopup alertWithConfig:config confirmHandler:^{
} cancelHandler:^{
}];
} else {
MedalVo *vo = [self.allMedalsVo xpSafeObjectAtIndex:indexPath.row];
if (vo) {
[self.presenter updateMedalUseStatus:vo.id isUse:!vo.useStatus];
}
}
}
}

View File

@@ -388,7 +388,10 @@ HWDMP4PlayDelegate>
self.userInfo.relationUserVO = userInfo.relationUserVO;
self.headView.relationUser = userInfo.relationUserVO;
userInfo.medalsPic = self.userInfo.medalsPic;
self.headerHeight = [XPMineUserInfoHeaderView headerHeight:userInfo cps:0];
[self.pagingView reloadData];
///访

View File

@@ -86,16 +86,14 @@
- (void)setRechargeModel:(RechargeListModel *)rechargeModel {
_rechargeModel = rechargeModel;
NSMutableAttributedString *priceStr = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"$%.2f",rechargeModel.money.floatValue]];
// [priceStr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:8] range:NSMakeRange(0, 1)];
self.priceLabel.attributedText = priceStr;
NSCharacterSet* nonDigits =[[NSCharacterSet decimalDigitCharacterSet] invertedSet];
int remainSecond = [[rechargeModel.prodName stringByTrimmingCharactersInSet:nonDigits] intValue];
self.numLabel.text = [NSString stringWithFormat:@"%d",remainSecond];
self.numLabel.text = [NSString stringWithFormat:@"%ld",
(long)rechargeModel.chargeGoldNum];
FirstRechargeModel *model = [FirstRechargeManager.sharedManager loadCurrentModel];
if (model && model.chargeStatus == NO) {
for (FirstRechargeLevelModel *levelModel in model.levelCharge) {
if (levelModel.exp == remainSecond) {
if (levelModel.exp == rechargeModel.chargeGoldNum) {
[self.moneyLabel updateContent: [NSString stringWithFormat:@"+ %@", @(levelModel.awardNum)]];
break;
}

View File

@@ -450,32 +450,12 @@ HWDMP4PlayDelegate>
self.stack.alignment = UIStackViewAlignmentLeading;
self.stack.spacing = 4;
// if (self.userInfo.guildNameplateIcon.length > 0) {
// scrollView.translatesAutoresizingMaskIntoConstraints = NO;
// [self.userInfoView addSubview:scrollView];
// [scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
// make.leading.mas_equalTo(kGetScaleWidth(15));
// make.trailing.mas_equalTo(kGetScaleWidth(-15));
// make.top.mas_equalTo(self.nickStackView.mas_bottom).offset(5);
// make.height.mas_equalTo(24);
// }];
// [scrollView addSubview:self.stack];
// [self.stack mas_makeConstraints:^(MASConstraintMaker *make) {
// make.edges.equalTo(scrollView); //
// make.height.equalTo(scrollView); //
// }];
//
//// if (isMSRTL()) {
//// _idEmptyView = [[UIView alloc] init];
//// }
// } else {
[self.userInfoView addSubview:self.stack];
[self.stack mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(kGetScaleWidth(15));
make.top.mas_equalTo(self.nickStackView.mas_bottom).offset(5);
make.height.mas_equalTo(24);
}];
// }
[self.userInfoView addSubview:self.stack];
[self.stack mas_makeConstraints:^(MASConstraintMaker *make) {
make.leading.mas_equalTo(kGetScaleWidth(15));
make.top.mas_equalTo(self.nickStackView.mas_bottom).offset(5);
make.height.mas_equalTo(24);
}];
[self.stack addArrangedSubview:self.beautIDView];
[self.stack addArrangedSubview:self.idLabel];
@@ -543,14 +523,21 @@ HWDMP4PlayDelegate>
make.top.mas_equalTo(self.nameplateCollectionView.mas_bottom).offset(6);
make.leading.mas_equalTo(self.userInfoView).offset(kGetScaleWidth(15));
make.trailing.mas_equalTo(self.userInfoView).offset(kGetScaleWidth(-15));
make.height.mas_equalTo(kGetScaleWidth(30));
make.height.mas_equalTo(0);
}];
UIView *container = [[UIView alloc] init];
container.backgroundColor = [UIColor clearColor];
[self.medalsScrollView addSubview:container];
[container mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.medalsScrollView);
}];
// ScrollView StackView
[self.medalsScrollView addSubview:self.medalsStackView];
[container addSubview:self.medalsStackView];
[self.medalsStackView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(self.medalsScrollView);
make.height.mas_equalTo(self.medalsScrollView);
make.edges.mas_equalTo(container);
make.height.mas_equalTo(kGetScaleWidth(30));
}];
//
@@ -1648,8 +1635,8 @@ HWDMP4PlayDelegate>
_medalsStackView = [[UIStackView alloc] init];
_medalsStackView.backgroundColor = [UIColor clearColor];
_medalsStackView.axis = UILayoutConstraintAxisHorizontal;
_medalsStackView.distribution = UIStackViewDistributionEqualSpacing;
_medalsStackView.alignment = UIStackViewAlignmentCenter;
_medalsStackView.distribution = UIStackViewDistributionFill;//UIStackViewDistributionEqualSpacing;
_medalsStackView.alignment = UIStackViewAlignmentLeading;
_medalsStackView.spacing = 5;
}
return _medalsStackView;
@@ -1679,6 +1666,10 @@ HWDMP4PlayDelegate>
return;
}
[self.medalsScrollView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(kGetScaleWidth(30));
}];
self.medalsScrollView.hidden = NO;
NSMutableArray<VAPView *> *mp4Views = [NSMutableArray array];
@@ -1731,17 +1722,17 @@ HWDMP4PlayDelegate>
[self.medalsStackView addArrangedSubview:medalContainer];
[medalContainer mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height
.mas_equalTo(kGetScaleWidth(30))
.priority(UILayoutPriorityRequired);
.mas_equalTo(kGetScaleWidth(30));
// .priority(UILayoutPriorityRequired);
}];
//
[medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
//
[medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
// //
// [medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
// [medalContainer setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
//
// //
// [medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
// [medalContainer setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}
// ScrollView contentSize
@@ -1752,6 +1743,19 @@ HWDMP4PlayDelegate>
CGFloat expectedWidth = count * kGetScaleWidth(30) + (count - 1) * 5;
stackViewWidth = expectedWidth;
}
CGFloat targetWidth = KScreenWidth - kGetScaleWidth(40);
if (stackViewWidth < targetWidth) {
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, targetWidth, kGetScaleWidth(30))];
v.backgroundColor = [UIColor clearColor];
[self.medalsStackView addArrangedSubview:v];
[v mas_remakeConstraints:^(MASConstraintMaker *make) {
make.size
.mas_equalTo(CGSizeMake(targetWidth-stackViewWidth, kGetScaleWidth(30)));
}];
stackViewWidth = targetWidth;
}
[self.medalsStackView layoutIfNeeded];
self.medalsScrollView.contentSize = CGSizeMake(stackViewWidth, kGetScaleWidth(30));
self.medalMP4Views = [mp4Views copy];

View File

@@ -518,11 +518,11 @@ UIKIT_EXTERN NSString *kRequestTicket;
}
///
-(void)pushGiveDiamondVC{
// XPWebViewController * webVC =[[XPWebViewController alloc] initWithRoomUID:nil];
// webVC.url = URLWithType(kTransfer);
// [self.navigationController pushViewController:webVC animated:YES];
XPMineGiveDiamondVC *giveDiamondVC = [[XPMineGiveDiamondVC alloc] initWithUserModel:self.userInfo];
[self.navigationController pushViewController:giveDiamondVC animated:YES];
XPWebViewController * webVC =[[XPWebViewController alloc] initWithRoomUID:nil];
webVC.url = URLWithType(kTransfer);
[self.navigationController pushViewController:webVC animated:YES];
// XPMineGiveDiamondVC *giveDiamondVC = [[XPMineGiveDiamondVC alloc] initWithUserModel:self.userInfo];
// [self.navigationController pushViewController:giveDiamondVC animated:YES];
}
///
-(void)pushThirdPartyPayVC{

View File

@@ -10,11 +10,16 @@
#import "XPNewHomeViewController.h"
#import "XPHomeMineViewController.h"
#import "XPRoomSearchContainerViewController.h"
#import "XPWebViewController.h"
#import "Api+Gift.h"
#import "XPGiftStorage.h"
#import "FirstRechargeManager.h"
#import "FirstRechargeModel.h"
#import "YUMIHtmlUrl.h"
#import "YUMIMacroUitls.h"
@interface XPHomePagingViewController () <UIPageViewControllerDelegate, UIPageViewControllerDataSource>
@interface XPHomePagingViewController () <UIPageViewControllerDelegate, UIPageViewControllerDataSource, FirstRechargeManagerDelegate>
@property (nonatomic, strong) UIView *topControlView;
@property (nonatomic, strong) UIButton *mineButton;
@@ -27,10 +32,20 @@
@property (nonatomic, strong) XPNewHomeViewController *recommendVC;
@property (nonatomic, strong) XPHomeMineViewController *mineVC;
//
@property (nonatomic, strong) XPWebViewController *firstChargeWebVC;
//
@property (nonatomic, strong) UIView *firstChargeBackgroundView;
@end
@implementation XPHomePagingViewController
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[FirstRechargeManager sharedManager].delegate = nil;
}
- (BOOL)isHiddenNavBar {
return YES;
}
@@ -38,6 +53,18 @@
- (void)viewDidLoad {
[super viewDidLoad];
[self setup];
//
[FirstRechargeManager sharedManager].delegate = self;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[FirstRechargeManager sharedManager] startMonitoring];
});
}
- (void)setup {
@@ -193,4 +220,113 @@
[self displayRecommendTab];
}
}
- (void)tokenInvalid {
//
[[FirstRechargeManager sharedManager] stopMonitoring];
// [super tokenInvalid];
}
#pragma mark - FirstRechargeManagerDelegate
- (void)firstRechargeManager:(FirstRechargeManager *)manager didCheckFirstRecharge:(FirstRechargeModel *)model shouldShow:(BOOL)shouldShow {
if (shouldShow && model.chargeStatus == NO) {
//
[self showFirstRechargePopup:model];
//
[[FirstRechargeManager sharedManager] markTodayShown];
}
}
- (void)showFirstRechargePopup:(FirstRechargeModel *)model {
if (model.chargeStatus) {
return;
}
//
[self removeFirstChargePopup];
//
self.firstChargeBackgroundView = [[UIView alloc] initWithFrame:self.view.bounds];
self.firstChargeBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
self.firstChargeBackgroundView.alpha = 0;
//
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBackgroundTap:)];
[self.firstChargeBackgroundView addGestureRecognizer:tapGesture];
//
[self.view addSubview:self.firstChargeBackgroundView];
// web
self.firstChargeWebVC = [[XPWebViewController alloc] initWithRoomUID:@""];
self.firstChargeWebVC.isPush = NO;
self.firstChargeWebVC.url = URLWithType(kFirstChargeHomeIndex);
[self addChildViewController:self.firstChargeWebVC];
[self.firstChargeBackgroundView addSubview:self.firstChargeWebVC.view];
[self.firstChargeWebVC didMoveToParentViewController:self];
self.firstChargeWebVC.view.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.webview.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.webview.opaque = NO;
self.firstChargeWebVC.webview.scrollView.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.view.frame = CGRectMake(0,
0,
kGetScaleWidth(305),
kGetScaleWidth(403));
self.firstChargeWebVC.view.center = self.firstChargeBackgroundView.center;
@kWeakify(self);
[self.firstChargeWebVC setUrlLoadCompleted:^(BOOL result, NSError * _Nullable error) {
@kStrongify(self);
[UIView animateWithDuration:0.5 animations:^{
self.firstChargeBackgroundView.alpha = 1;
}];
}];
[self.firstChargeWebVC setDidTapCharge:^{
@kStrongify(self);
[self removeFirstChargePopup];
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self removeFirstChargePopup];
});
}
//
- (void)handleBackgroundTap:(UITapGestureRecognizer *)gesture {
//
CGPoint location = [gesture locationInView:self.firstChargeBackgroundView];
// webView
if (self.firstChargeWebVC && self.firstChargeWebVC.view) {
CGRect webViewFrame = self.firstChargeWebVC.view.frame;
if (!CGRectContainsPoint(webViewFrame, location)) {
// webView
[self removeFirstChargePopup];
}
} else {
// webView
[self removeFirstChargePopup];
}
}
//
- (void)removeFirstChargePopup {
if (self.firstChargeWebVC) {
[self.firstChargeWebVC willMoveToParentViewController:nil];
[self.firstChargeWebVC.view removeFromSuperview];
[self.firstChargeWebVC removeFromParentViewController];
self.firstChargeWebVC = nil;
}
if (self.firstChargeBackgroundView) {
[self.firstChargeBackgroundView removeFromSuperview];
self.firstChargeBackgroundView = nil;
}
}
@end

View File

@@ -13,7 +13,6 @@
#import <JXCategoryView/JXCategoryView.h>
#import <MJRefresh/MJRefresh.h>
#import "SDWebImageManager.h"
#import "FirstRechargeManager.h"
///Tool
#import "Api+Home.h"
#import "YUMIMacroUitls.h"
@@ -330,8 +329,7 @@ JXCategoryViewDelegate,
XPHomeContainerProtocol,
XPNewHomeNavViewDelegate,
XPNewHomeHeadViewDelegate,
XPHomeRecommendOtherRoomViewDelegate,
FirstRechargeManagerDelegate>
XPHomeRecommendOtherRoomViewDelegate>
///
@property(nonatomic,strong) XPNewHomeHeadView *headView;
@@ -359,11 +357,6 @@ FirstRechargeManagerDelegate>
@property (nonatomic, assign) bool hasLoadAPIs;
//
@property (nonatomic, strong) XPWebViewController *firstChargeWebVC;
//
@property (nonatomic, strong) UIView *firstChargeBackgroundView;
@end
@implementation XPNewHomeViewController
@@ -377,7 +370,6 @@ FirstRechargeManagerDelegate>
-(void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self];
[FirstRechargeManager sharedManager].delegate = nil;
}
- (BOOL)isHiddenNavBar {
@@ -398,12 +390,6 @@ FirstRechargeManagerDelegate>
[self initSubViewConstraints];
[self requestCheckIp];
//
[FirstRechargeManager sharedManager].delegate = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[FirstRechargeManager sharedManager] startMonitoring];
});
}
}
@@ -416,13 +402,10 @@ FirstRechargeManagerDelegate>
});
self.hasLoadAPIs = YES;
}
}
- (void)tokenInvalid {
//
[[FirstRechargeManager sharedManager] stopMonitoring];
[[AccountInfoStorage instance] saveAccountInfo:nil];
[[AccountInfoStorage instance] saveTicket:nil];
if ([NIMSDK sharedSDK].loginManager.isLogined) {
@@ -786,135 +769,7 @@ FirstRechargeManagerDelegate>
self.type = index;
}
- (void)getFirstChargeSuccess:(FirstRechargeModel *)model {
if (model.chargeStatus == NO) {
// TODO: web view
XPWebViewController *web = [[XPWebViewController alloc] initWithRoomUID:@""];
[self addChildViewController:web];
[self.view addSubview:web.view];
web.view.frame = CGRectMake(0, 0, KScreenWidth/2, KScreenHeight/2);
web.view.center = self.view.center;
}
}
#pragma mark - FirstRechargeManagerDelegate
- (void)firstRechargeManager:(FirstRechargeManager *)manager didCheckFirstRecharge:(FirstRechargeModel *)model shouldShow:(BOOL)shouldShow {
if (shouldShow && model.chargeStatus == NO) {
//
[self showFirstRechargePopup:model];
//
[[FirstRechargeManager sharedManager] markTodayShown];
}
}
- (void)showFirstRechargePopup:(FirstRechargeModel *)model {
if (model.chargeStatus) {
return;
}
//
[self removeFirstChargePopup];
// keyWindow tabbar
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
if (!keyWindow) {
keyWindow = [UIApplication sharedApplication].windows.firstObject;
}
// 使 keyWindow bounds
self.firstChargeBackgroundView = [[UIView alloc] initWithFrame:keyWindow.bounds];
self.firstChargeBackgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
//
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleBackgroundTap:)];
[self.firstChargeBackgroundView addGestureRecognizer:tapGesture];
// keyWindow tabbar
[keyWindow addSubview:self.firstChargeBackgroundView];
// web
self.firstChargeWebVC = [[XPWebViewController alloc] initWithRoomUID:@""];
self.firstChargeWebVC.isPush = NO;
self.firstChargeWebVC.url = URLWithType(kFirstChargeHomeIndex);
//
UIViewController *rootViewController = keyWindow.rootViewController;
if ([rootViewController isKindOfClass:[UINavigationController class]]) {
rootViewController = [(UINavigationController *)rootViewController topViewController];
} else if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tabBarController = (UITabBarController *)rootViewController;
rootViewController = tabBarController.selectedViewController;
if ([rootViewController isKindOfClass:[UINavigationController class]]) {
rootViewController = [(UINavigationController *)rootViewController topViewController];
}
}
[rootViewController addChildViewController:self.firstChargeWebVC];
[self.firstChargeBackgroundView addSubview:self.firstChargeWebVC.view];
[self.firstChargeWebVC didMoveToParentViewController:rootViewController];
self.firstChargeWebVC.view.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.webview.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.webview.opaque = NO;
self.firstChargeWebVC.webview.scrollView.backgroundColor = [UIColor clearColor];
self.firstChargeWebVC.view.frame = CGRectMake(0, 0, KScreenWidth - 40, KScreenHeight*2/3);
self.firstChargeWebVC.view.center = self.firstChargeBackgroundView.center;
//
// UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
// [closeButton setTitle:@"✕" forState:UIControlStateNormal];
// [closeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
// closeButton.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightBold];
// [closeButton addTarget:self action:@selector(removeFirstChargePopup) forControlEvents:UIControlEventTouchUpInside];
// closeButton.frame = CGRectMake(0, 0, 30, 30);
// closeButton.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
// closeButton.layer.cornerRadius = 15;
// [self.firstChargeBackgroundView addSubview:closeButton];
//
// // webView
// CGRect webViewFrame = self.firstChargeWebVC.view.frame;
// closeButton.center = CGPointMake(CGRectGetMaxX(webViewFrame) - 15, CGRectGetMinY(webViewFrame) + 15);
// 3
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// [self removeFirstChargePopup];
// });
}
//
- (void)handleBackgroundTap:(UITapGestureRecognizer *)gesture {
//
CGPoint location = [gesture locationInView:self.firstChargeBackgroundView];
// webView
if (self.firstChargeWebVC && self.firstChargeWebVC.view) {
CGRect webViewFrame = self.firstChargeWebVC.view.frame;
if (!CGRectContainsPoint(webViewFrame, location)) {
// webView
[self removeFirstChargePopup];
}
} else {
// webView
[self removeFirstChargePopup];
}
}
//
- (void)removeFirstChargePopup {
if (self.firstChargeWebVC) {
[self.firstChargeWebVC willMoveToParentViewController:nil];
[self.firstChargeWebVC.view removeFromSuperview];
[self.firstChargeWebVC removeFromParentViewController];
self.firstChargeWebVC = nil;
}
if (self.firstChargeBackgroundView) {
[self.firstChargeBackgroundView removeFromSuperview];
self.firstChargeBackgroundView = nil;
}
}
#pragma mark - XPNewHomeHeadViewDelegate
///

View File

@@ -106,9 +106,7 @@
[[NIMSDK sharedSDK].chatroomManager enterChatroom:request completion:^(NSError * _Nullable error, NIMChatroom * _Nullable chatroom, NIMChatroomMember * _Nullable me) {
@kStrongify(self);
if (error) {
#ifdef DEBUG
NSLog(@"\n云信进房异常:\n %@", error);
#endif
NSLog(@"\n云信进房异常:\n %@", error);
[[self getView] enterRoomFail:error.code];
} else {
[[self getView] enterRoomSuccess:chatroom];

View File

@@ -36,6 +36,11 @@
CGSize size = [content boundingRectWithSize:CGSizeMake(width, 0)
options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin
context:nil].size;
if (self.first == 9 && self.second == 91) {
self.rowHeight = 100;
return;
}
YYTextContainer *container = [YYTextContainer containerWithSize:CGSizeMake(size.width, CGFLOAT_MAX)];
container.maximumNumberOfRows = 0;
@@ -45,6 +50,7 @@
CGSize textSize = textLayout.textBoundingRect.size;
self.textWidth = textSize.width;
if ([NSString isEmpty:self.bubbleImageUrl]) {
self.rowHeight =
ceil(textSize.height) +
@@ -61,5 +67,19 @@
self.rowHeight += 10;
// }
self.rowHeight += (self.isBoom ? 20 : 0);
if ([self isStringContainArabic:content.string]) {
self.rowHeight += 20;
}
}
- (BOOL)isStringContainArabic:(NSString *)string {
for (NSUInteger i = 0; i < string.length; i++) {
unichar c = [string characterAtIndex:i];
if (c >= 0x0600 && c <= 0x06FF) {
return YES;
}
}
return NO;
}
@end

View File

@@ -1012,6 +1012,9 @@
- (XPMessageInfoModel*)createRoomFaceAttribute:(AttachmentModel *)attachment
messageInfo:(XPMessageInfoModel *)messageInfo
remoteExtModel:(XPMessageRemoteExtModel *)model {
messageInfo.first = attachment.first;
messageInfo.second = attachment.second;
NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init];
///
[attribute appendAttributedString:[self createOfficalAndNewuserAttribute:model.defUser newUser:model.newUser fromSayHelloChannel:model.fromSayHelloChannel]];
@@ -1094,7 +1097,6 @@
}
}
messageInfo.content = attribute;
messageInfo.first = attachment.first;
return messageInfo;
}

View File

@@ -141,7 +141,7 @@
FirstRechargeModel *model = [[FirstRechargeManager sharedManager] loadCurrentModel];
if (model && model.chargeStatus == NO) {
self.firstChargeView.hidden = NO;
[self.moneyLabel updateContent:@"Bonus >"];
[self.moneyLabel updateContent:YMLocalizedString(@"20.20.61_text_19")];
} else {
self.firstChargeView.hidden = YES;
}
@@ -164,9 +164,18 @@
}];
[self.firstChargeView mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(68, 23));
make.height.mas_equalTo(23);
make.leading.mas_equalTo(self.rechargeStackView.mas_leading);
make.centerY.mas_equalTo(self.rechargeStackView);
if (isMSZH()) {
make.width.mas_equalTo(80);
} else if (isMSRTL()) {
make.width.mas_equalTo(76);
} else if (isMSTR()) {
make.width.mas_equalTo(70);
} else {
make.width.mas_equalTo(70);
}
}];
[self.sendOperationView mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -546,7 +555,19 @@
[_firstChargeView addSubview:self.moneyLabel];
[self.moneyLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(_firstChargeView).insets(UIEdgeInsetsMake(5, 5, 5, 5));
make.edges.mas_equalTo(_firstChargeView).insets(UIEdgeInsetsMake(5, 5, 5, 10));
}];
UIImageView *arrow = [[UIImageView alloc] initWithImage:[kImage(@"brown_arrow") ms_SetImageForRTL]];
[_firstChargeView addSubview:arrow];
[arrow mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.mas_equalTo(_firstChargeView);
if (isMSRTL()) {
make.leading.mas_equalTo(self.moneyLabel.mas_trailing).offset(-10);
}else {
make.leading.mas_equalTo(self.moneyLabel.mas_trailing).offset(-5);
}
make.size.mas_equalTo(CGSizeMake(12, 12));
}];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTagRecharge:)];
@@ -557,7 +578,7 @@
- (MoliMoneyLabel *)moneyLabel {
if (!_moneyLabel) {
_moneyLabel = [MoliMoneyLabel moneyLabelWithTextColot:UIColorFromRGB(0x582B00) font:kFontSemibold(10) moneyPostion:1 moneySize:CGSizeMake(15, 15)];
_moneyLabel = [MoliMoneyLabel moneyLabelWithTextColot:UIColorFromRGB(0x582B00) font:kFontSemibold(12) moneyPostion:1 moneySize:CGSizeMake(15, 15)];
}
return _moneyLabel;
}

View File

@@ -461,7 +461,7 @@
[self.medalsScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.contentView);
make.centerY.mas_equalTo(self.contentView);
make.top.mas_equalTo(self.contentView);
make.height.mas_equalTo(kGetScaleWidth(30));
//
self.scrollViewWidthConstraint = make.width.mas_equalTo(maxMedalsWidth);

View File

@@ -43,6 +43,8 @@ NS_ASSUME_NONNULL_BEGIN
@property(nonatomic, copy) void (^verifyCaptcha)(BOOL result);
@property (nonatomic, copy) void(^didTapCharge)(void);
- (instancetype)initWithCustomizeNav:(BOOL)isCustom;
///强制使用 roomUID 初始化,尽量传入,防止 web 在需要时取不到数据

View File

@@ -373,9 +373,10 @@ NSString * const kJSShowShareCallBack = @"showShareAction";
NSString *currentUrl = [NSString stringWithFormat:@"%@", response];
///host,便h5
BOOL condition = currentUrl != nil && [currentUrl containsString:API_HOST_URL];
#ifdef DEBUG
NSLog(@"-- -- - -- - - -- -- - -- - -%@", response);
NSLog(@"-- -- - -- - -%@: %@", message.name, message.body);
#ifdef DEBUG
condition = currentUrl != nil;
#endif
if(condition) {
@@ -450,6 +451,11 @@ NSString * const kJSShowShareCallBack = @"showShareAction";
webVC.type = @"4";
[[XCCurrentVCStackManager shareManager].getCurrentVC.navigationController pushViewController:webVC animated:YES];
}
if (self.didTapCharge) {
self.didTapCharge();
}
} else if ([message.name isEqualToString:kOpenPersonPage]) {
NSString *uid = [NSString stringWithFormat:@"%@",message.body];
if (uid.integerValue > 0) {

View File

@@ -71,6 +71,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign) NSInteger busType;
@property (nonatomic,copy) NSString *mp4Url;
@end
@interface MedalModel : PIBaseModel

View File

@@ -125,12 +125,18 @@
- (void)accountCanceled:(NSDictionary *)data {
NSString *date = [NSString stringWithFormat:@"%.0f",[[data objectForKey:@"cancelDate"] doubleValue]];
NSString *dateDes = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController0"), [PLTimeUtil getDateWithYYMMDD:date]];
NSString *msg = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController1"), dateDes];
NSString *msg = [NSString stringWithFormat:YMLocalizedString(@"MvpViewController1.1"), dateDes];
if ([[data objectForKey:@"cancelDate"] doubleValue] == 0) {
dateDes = @"";
msg = YMLocalizedString(@"MvpViewController1.2");
}
TTAlertMessageAttributedConfig *dateAttrConfig = [[TTAlertMessageAttributedConfig alloc] init];
dateAttrConfig.text = dateDes;
dateAttrConfig.color = DJDKMIMOMColor.appMainColor;
TTAlertConfig *config = [[TTAlertConfig alloc] init];
config.actionStyle = 0;
config.title = YMLocalizedString(@"MvpViewController2");
config.message = msg;
config.messageAttributedConfig = @[dateAttrConfig];

View File

@@ -15,14 +15,14 @@
static NSString * const kFirstRechargeModelKey = @"FirstRechargeModel";
static NSString * const kLastCheckDateKey = @"FirstRechargeLastCheckDate";
static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
static NSString * const kCurrentUserIdKey = @"FirstRechargeCurrentUserId";
@interface FirstRechargeManager ()
@property (nonatomic, strong) FirstRechargeModel *currentFirstRechargeData;
@property (nonatomic, strong) NSTimer *dailyTimer;
@property (nonatomic, assign) BOOL isMonitoring;
@property (nonatomic, copy) NSString *currentUserId;
@end
@@ -42,6 +42,7 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
if (self) {
_isMonitoring = NO;
[self loadCachedModel];
[self updateCurrentUserId];
}
return self;
}
@@ -63,6 +64,9 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
self.isMonitoring = YES;
//
[self checkUserSwitch];
//
[self checkFirstRechargeStatus];
@@ -99,8 +103,7 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
- (void)markTodayShown {
NSString *today = [self getTodayString];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:kTodayShownKey];
[[NSUserDefaults standardUserDefaults] synchronize];
[self setTodayShownForCurrentUser:today];
}
#pragma mark - Private Methods
@@ -140,6 +143,9 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
}
- (void)applicationDidBecomeActive {
//
[self checkUserSwitch];
//
if ([self shouldCheckToday]) {
[self checkFirstRechargeStatus];
@@ -147,7 +153,8 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
}
- (BOOL)shouldCheckToday {
NSString *lastCheckDate = [[NSUserDefaults standardUserDefaults] objectForKey:kLastCheckDateKey];
NSString *userSpecificKey = [self getUserSpecificKey:kLastCheckDateKey];
NSString *lastCheckDate = [[NSUserDefaults standardUserDefaults] objectForKey:userSpecificKey];
NSString *today = [self getTodayString];
return ![today isEqualToString:lastCheckDate];
@@ -160,6 +167,9 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
return;
}
// ID
[self updateCurrentUserId];
// API
@kWeakify(self);
[Api firstchargeInfo:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) {
@@ -180,9 +190,10 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
self.currentFirstRechargeData = model;
[self saveCachedModel:model];
//
//
NSString *today = [self getTodayString];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:kLastCheckDateKey];
NSString *userSpecificKey = [self getUserSpecificKey:kLastCheckDateKey];
[[NSUserDefaults standardUserDefaults] setObject:today forKey:userSpecificKey];
[[NSUserDefaults standardUserDefaults] synchronize];
//
@@ -193,16 +204,13 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
}
- (BOOL)shouldShowFirstRecharge:(FirstRechargeModel *)model {
#if DEBUG
return YES;
#endif
//
if (model.chargeStatus) {
return NO;
}
//
NSString *shownDate = [[NSUserDefaults standardUserDefaults] objectForKey:kTodayShownKey];
//
NSString *shownDate = [self getTodayShownForCurrentUser];
NSString *today = [self getTodayString];
return ![today isEqualToString:shownDate];
@@ -224,16 +232,73 @@ static NSString * const kTodayShownKey = @"FirstRechargeTodayShown";
return [formatter stringFromDate:[NSDate date]];
}
#pragma mark - User Switch Detection
- (void)updateCurrentUserId {
NSString *newUserId = [AccountInfoStorage instance].getUid;
if (newUserId.length > 0) {
self.currentUserId = newUserId;
// ID
[[NSUserDefaults standardUserDefaults] setObject:newUserId forKey:kCurrentUserIdKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
- (void)checkUserSwitch {
NSString *savedUserId = [[NSUserDefaults standardUserDefaults] objectForKey:kCurrentUserIdKey];
NSString *currentUserId = [AccountInfoStorage instance].getUid;
// ID
if (currentUserId.length > 0 &&
savedUserId.length > 0 &&
![currentUserId isEqualToString:savedUserId]) {
// ID
[self updateCurrentUserId];
//
self.currentFirstRechargeData = nil;
//
[self checkFirstRechargeStatus];
} else if (currentUserId.length > 0 && savedUserId.length == 0) {
//
[self updateCurrentUserId];
}
}
#pragma mark - User-specific Storage
- (NSString *)getUserSpecificKey:(NSString *)baseKey {
if (self.currentUserId.length == 0) {
return baseKey;
}
return [NSString stringWithFormat:@"%@_%@", baseKey, self.currentUserId];
}
- (NSString *)getTodayShownForCurrentUser {
NSString *userSpecificKey = [self getUserSpecificKey:kTodayShownKey];
return [[NSUserDefaults standardUserDefaults] objectForKey:userSpecificKey];
}
- (void)setTodayShownForCurrentUser:(NSString *)date {
NSString *userSpecificKey = [self getUserSpecificKey:kTodayShownKey];
[[NSUserDefaults standardUserDefaults] setObject:date forKey:userSpecificKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)saveCachedModel:(FirstRechargeModel *)model {
if (model) {
NSString *userSpecificKey = [self getUserSpecificKey:kFirstRechargeModelKey];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:model.toJSONObject requiringSecureCoding:NO error:nil];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:kFirstRechargeModelKey];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:userSpecificKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
- (void)loadCachedModel {
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:kFirstRechargeModelKey];
NSString *userSpecificKey = [self getUserSpecificKey:kFirstRechargeModelKey];
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:userSpecificKey];
if (data) {
NSDictionary *dict = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSDictionary class] fromData:data error:nil];
if (dict) {

View File

@@ -0,0 +1,101 @@
//
// MedalMediaDisplayManager.h
// YuMi
//
// Created by AI on 2025/1/20.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@class VAPView, NetImageView, XPRoomGiftAnimationParser;
NS_ASSUME_NONNULL_BEGIN
/**
* 媒体显示代理协议
* 需要使用媒体显示功能的类实现此协议
*/
@protocol MedalMediaDisplayDelegate <NSObject>
@required
/// 从数据模型中获取MP4 URL
- (NSString * _Nullable)getMP4UrlFromModel:(id _Nullable)model;
/// 从数据模型中获取图片 URL
- (NSString * _Nullable)getPicUrlFromModel:(id _Nullable)model;
/// 获取图片显示视图
- (NetImageView *)getImageView;
/// 获取MP4播放视图
- (VAPView *)getMP4View;
@optional
/// 媒体显示状态更新回调
- (void)onMediaDisplayUpdated:(BOOL)isMP4 success:(BOOL)success;
/// 获取默认占位图
- (UIImage * _Nullable)getDefaultPlaceholderImage;
@end
/**
* 勋章媒体显示管理器
* 统一处理MP4和PNG的显示逻辑
*/
@interface MedalMediaDisplayManager : NSObject
/// 代理对象
@property (nonatomic, weak) id<MedalMediaDisplayDelegate> delegate;
/// 当前显示的数据模型
@property (nonatomic, strong, nullable) id currentModel;
/// 可见性状态
@property (nonatomic, assign) BOOL isVisible;
/// 当前媒体路径
@property (nonatomic, copy, readonly, nullable) NSString *currentImagePath;
@property (nonatomic, copy, readonly, nullable) NSString *currentMP4Path;
/**
* 初始化方法
* @param delegate 实现MedalMediaDisplayDelegate协议的对象
*/
- (instancetype)initWithDelegate:(id<MedalMediaDisplayDelegate>)delegate;
/**
* 更新显示内容
* @param model 数据模型
*/
- (void)updateDisplayWithModel:(id _Nullable)model;
/**
* 可见性管理
*/
- (void)willDisplay;
- (void)didEndDisplaying;
/**
* 播放控制
*/
- (void)stopMP4Playback;
- (void)pauseMP4Playback;
- (void)resumeMP4Playback;
/**
* 资源清理
*/
- (void)cleanupResources;
/**
* 应用生命周期通知处理
*/
- (void)handleAppDidEnterBackground;
- (void)handleAppWillEnterForeground;
- (void)handleMemoryWarning;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,328 @@
//
// MedalMediaDisplayManager.m
// YuMi
//
// Created by AI on 2025/1/20.
//
#import "MedalMediaDisplayManager.h"
#import <QGVAPWrapView.h>
#import "XPRoomGiftAnimationParser.h"
#import "NSString+XPExtension.h"
#import "UIImageConstant.h"
@interface MedalMediaDisplayManager () <HWDMP4PlayDelegate>
@property (nonatomic, copy, readwrite, nullable) NSString *currentImagePath;
@property (nonatomic, copy, readwrite, nullable) NSString *currentMP4Path;
@property (nonatomic, strong) XPRoomGiftAnimationParser *mp4Parser;
@property (nonatomic, assign) NSInteger mp4PlaybackTag; //
@end
@implementation MedalMediaDisplayManager
#pragma mark -
- (instancetype)initWithDelegate:(id<MedalMediaDisplayDelegate>)delegate {
self = [super init];
if (self) {
_delegate = delegate;
_isVisible = YES;
_mp4PlaybackTag = 0;
[self setupNotifications];
}
return self;
}
- (void)dealloc {
[self cleanupResources];
[[NSNotificationCenter defaultCenter] removeObserver:self];
NSLog(@"MedalMediaDisplayManager dealloc");
}
#pragma mark -
- (void)updateDisplayWithModel:(id)model {
self.currentModel = model;
[self handleMediaDisplayWithModel:model];
}
- (void)willDisplay {
self.isVisible = YES;
[self resumeMP4PlaybackIfNeeded];
}
- (void)didEndDisplaying {
self.isVisible = NO;
[self pauseMP4Playback];
}
- (void)stopMP4Playback {
VAPView *mp4View = [self.delegate getMP4View];
if (mp4View) {
[mp4View stopHWDMP4];
self.mp4PlaybackTag = 0;
}
}
- (void)pauseMP4Playback {
VAPView *mp4View = [self.delegate getMP4View];
if (mp4View && !mp4View.hidden) {
[mp4View pauseHWDMP4];
}
}
- (void)resumeMP4Playback {
[self resumeMP4PlaybackIfNeeded];
}
- (void)cleanupResources {
[self stopMP4Playback];
self.mp4Parser = nil;
self.currentImagePath = nil;
self.currentMP4Path = nil;
self.currentModel = nil;
}
#pragma mark -
- (void)handleMediaDisplayWithModel:(id)model {
if (!model || !self.delegate) {
[self showDefaultPlaceholder];
return;
}
NSString *mp4Url = [self.delegate getMP4UrlFromModel:model];
NSString *picUrl = [self.delegate getPicUrlFromModel:model];
// MP4 URL
if (![NSString isEmpty:mp4Url] && [self isValidMP4URL:mp4Url]) {
[self setMp4Path:mp4Url];
return;
}
// MP4 URL URL
if (![NSString isEmpty:picUrl]) {
if ([self isValidMP4URL:picUrl]) {
// picUrl MP4
[self setMp4Path:picUrl];
return;
} else if ([NSString isValidImageURL:picUrl]) {
// URL
[self setImagePath:picUrl];
return;
}
}
//
[self showDefaultPlaceholder];
}
- (void)setImagePath:(NSString *)imagePath {
[self stopMP4Playback];
self.currentImagePath = imagePath;
self.currentMP4Path = nil;
VAPView *mp4View = [self.delegate getMP4View];
NetImageView *imageView = [self.delegate getImageView];
mp4View.hidden = YES;
imageView.hidden = NO;
imageView.imageUrl = imagePath ?: @"";
[self notifyDisplayUpdated:NO success:![NSString isEmpty:imagePath]];
}
- (void)setMp4Path:(NSString *)mp4Path {
if ([NSString isEmpty:mp4Path]) {
[self showDefaultPlaceholder];
return;
}
[self stopMP4Playback];
self.currentMP4Path = mp4Path;
self.currentImagePath = nil;
VAPView *mp4View = [self.delegate getMP4View];
NetImageView *imageView = [self.delegate getImageView];
mp4View.hidden = NO;
imageView.hidden = YES;
if (!self.mp4Parser) {
self.mp4Parser = [[XPRoomGiftAnimationParser alloc] init];
}
@kWeakify(self);
[self.mp4Parser parseWithURL:mp4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl]) {
self.mp4PlaybackTag = 1; //
if (self.isVisible) {
[self startMP4PlaybackWithURL:videoUrl];
}
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
NSLog(@"[MedalMediaDisplayManager] Failed to parse mp4: %@", error);
[self handleMP4FailureWithFallback];
}];
}
- (void)startMP4PlaybackWithURL:(NSString *)videoUrl {
if ([NSString isEmpty:videoUrl] || !self.delegate) {
return;
}
VAPView *mp4View = [self.delegate getMP4View];
if (mp4View && !mp4View.hidden) {
[mp4View playHWDMP4:videoUrl repeatCount:-1 delegate:self];
[self notifyDisplayUpdated:YES success:YES];
NSLog(@"[MedalMediaDisplayManager] Started MP4 playback: %@", videoUrl);
}
}
- (void)handleMP4FailureWithFallback {
if (!self.delegate || !self.currentModel) {
[self showDefaultPlaceholder];
return;
}
// MP4
NSString *picUrl = [self.delegate getPicUrlFromModel:self.currentModel];
if (![NSString isEmpty:picUrl] && [NSString isValidImageURL:picUrl]) {
[self setImagePath:picUrl];
} else {
[self showDefaultPlaceholder];
}
}
- (void)showDefaultPlaceholder {
[self stopMP4Playback];
VAPView *mp4View = [self.delegate getMP4View];
NetImageView *imageView = [self.delegate getImageView];
mp4View.hidden = YES;
imageView.hidden = NO;
imageView.imageUrl = @"";
//
UIImage *placeholderImage = nil;
if ([self.delegate respondsToSelector:@selector(getDefaultPlaceholderImage)]) {
placeholderImage = [self.delegate getDefaultPlaceholderImage];
}
if (!placeholderImage) {
placeholderImage = [UIImageConstant defaultEmptyPlaceholder];
}
imageView.image = placeholderImage;
[self notifyDisplayUpdated:NO success:NO];
}
- (void)resumeMP4PlaybackIfNeeded {
if (!self.isVisible || [NSString isEmpty:self.currentMP4Path]) {
return;
}
VAPView *mp4View = [self.delegate getMP4View];
if (mp4View && !mp4View.hidden) {
if (self.mp4PlaybackTag == 1) {
//
@kWeakify(self);
[self.mp4Parser parseWithURL:self.currentMP4Path
completionBlock:^(NSString * _Nullable videoUrl) {
@kStrongify(self);
if (![NSString isEmpty:videoUrl] && self.isVisible) {
[self startMP4PlaybackWithURL:videoUrl];
}
} failureBlock:^(NSError * _Nullable error) {
@kStrongify(self);
[self handleMP4FailureWithFallback];
}];
} else {
//
[mp4View resumeHWDMP4];
}
}
}
#pragma mark -
- (BOOL)isValidMP4URL:(NSString *)url {
if ([NSString isEmpty:url]) {
return NO;
}
NSString *lowercaseUrl = [url lowercaseString];
return [lowercaseUrl hasSuffix:@".mp4"] ||
[lowercaseUrl containsString:@"mp4"] ||
[lowercaseUrl containsString:@"video"];
}
- (void)notifyDisplayUpdated:(BOOL)isMP4 success:(BOOL)success {
if ([self.delegate respondsToSelector:@selector(onMediaDisplayUpdated:success:)]) {
[self.delegate onMediaDisplayUpdated:isMP4 success:success];
}
}
#pragma mark -
- (void)setupNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleAppDidEnterBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleAppWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMemoryWarning)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
}
- (void)handleAppDidEnterBackground {
[self pauseMP4Playback];
}
- (void)handleAppWillEnterForeground {
if (self.isVisible) {
[self resumeMP4PlaybackIfNeeded];
}
}
- (void)handleMemoryWarning {
if (!self.isVisible) {
[self stopMP4Playback];
}
}
#pragma mark - HWDMP4PlayDelegate
- (BOOL)shouldStartPlayMP4:(VAPView *)container config:(QGVAPConfigModel *)config {
return YES;
}
- (void)viewDidFinishPlayMP4:(NSInteger)totalFrameCount view:(VAPView *)container {
// MP4
}
- (void)viewDidStopPlayMP4:(NSInteger)lastFrameIndex view:(VAPView *)container {
// MP4
}
- (void)viewDidFailPlayMP4:(NSError *)error {
NSLog(@"[MedalMediaDisplayManager] MP4 播放失败: %@", error);
[self handleMP4FailureWithFallback];
}
@end

View File

@@ -2941,8 +2941,8 @@ ineHeadView12" = "الحمل";
"LoginBindPhoneViewController2" = "ربط رقم الهاتف المحمول";
"MvpViewController0" = "وقت الإلغاء: %@";
"MvpViewController1" = "%@\n\nيرجى الاتصال بخدمة العملاء (WeChat: mxyz2050) للحصول على استفسارات";
"MvpViewController2" = "تم إلغاء تسجيل الحساب";
"MvpViewController1.1" = "@%\n\nيرجى الاتصال بخدمة العملاء (WeChat: mxyz2050) للحصول على استفسارات";
"MvpViewController1.2" = "يرجى الاتصال بخدمة العملاء (WeChat: mxyz2050) للحصول على استفسارات";
"MvpViewController3" = "من أجل خلق بيئة إنترنت آمنة أكثر\nحماية ممتلكاتك وممتلكات الآخرين\nيرجى تقديم التحقق الهوية أولا";
"MvpViewController5" = "التحقق من الهوية";
@@ -4206,3 +4206,24 @@ ineHeadView12" = "الحمل";
"20.20.59_text_34" = "تم التقديم بنجاح";
"20.20.59_text_35" = "تم الاشتراك بنجاح";
"20.20.59_text_36" = "تم الإلغاء بنجاح";
"20.20.61_text_1" = "ميدالياتي";
"20.20.61_text_2" = "حامل الميدالية";
"20.20.61_text_3" = "ميداليات المهام";
"20.20.61_text_4" = "ميداليات الأنشطة";
"20.20.61_text_5" = "ميداليات المجد";
"20.20.61_text_6" = "لا ترتدي أي ميداليات";
"20.20.61_text_7.1" = "لم تستلم أي ميداليات";
"20.20.61_text_7.2" = "لم تستلم أي ميداليات\nاذهب إلى مربع الميداليات وتحقق!";
"20.20.61_text_8" = "تاريخ الانتهاء:%@";
"20.20.61_text_9" = "دائمًا";
"20.20.61_text_10" = "مربع الميداليات";
"20.20.61_text_11" = "قاعة مشاهير الميداليات";
"20.20.61_text_12" = "المالك القوي";
"20.20.61_text_13" = "عرض ميدالياته";
"20.20.61_text_14" = "%@ ميدالية";
"20.20.61_text_15" = "قم بترقية VIP للحصول على المزيد من فتحات عرض الميداليات!";
"20.20.61_text_16" = "ميدالياتك ممتلئة!\nاضبطها أولاً ثم أضف المزيد!";
"20.20.61_text_17" = "نصيحة مقعد الميدالية";
"20.20.61_text_18" = "قم بالترقية الآن!";
"20.20.61_text_19" = "بونص";

View File

@@ -2549,6 +2549,8 @@
"MvpViewController0" = "Logoff time: %@";
"MvpViewController1" = "%@\n\nPlease contact customer service (WeChat: mxyz2050) for inquiries.";
"MvpViewController1.1" = "%@\n\nPlease contact customer service (WeChat: mxyz2050) for inquiries.";
"MvpViewController1.2" = "Please contact customer service (WeChat: mxyz2050) for inquiries.";
"MvpViewController2" = "This account has been logged off";
"MvpViewController3" = "In order to create a safer online environment\nand protect the property safety of you and others,\nplease complete real-name authentication first";
@@ -3991,3 +3993,24 @@
"20.20.59_text_34" = "Submission Successful";
"20.20.59_text_35" = "Sub successful";
"20.20.59_text_36" = "Cancel successful";
"20.20.61_text_1" = "My Medals";
"20.20.61_text_2" = "Medal Wearing";
"20.20.61_text_3" = "Task Medals";
"20.20.61_text_4" = "Activity Medals";
"20.20.61_text_5" = "Glory Medals";
"20.20.61_text_6" = "You are not wearing any medals";
"20.20.61_text_7.1" = "You have not received any medals";
"20.20.61_text_7.2" = "You have not received any medals\nGo to the medal square and check it out!";
"20.20.61_text_8" = "Expiration time:%@";
"20.20.61_text_9" = "Forever";
"20.20.61_text_10" = "Medal Square";
"20.20.61_text_11" = "Medal Hall of Fame";
"20.20.61_text_12" = "Powerful Owner";
"20.20.61_text_13" = "View his medals";
"20.20.61_text_14" = "%@'s medal";
"20.20.61_text_15" = "Upgrade VIP to get more medal display slots!";
"20.20.61_text_16" = "Your medals are full!\nAdjust first and then add more!";
"20.20.61_text_17" = "Medal Seat Tip";
"20.20.61_text_18" = "Upgrade now!";
"20.20.61_text_19" = "Bonus";

View File

@@ -2224,6 +2224,8 @@
"MvpViewController0" = "Oturumu kapatma zamanı: %@";
"MvpViewController1" = "%@\n\nMüşteri hizmetleriyle iletişime geçin (WeChat: mxyz2050) danışın";
"MvpViewController1.1" = "%@\n\nMüşteri hizmetleriyle iletişime geçin (WeChat: mxyz2050) danışın";
"MvpViewController1.2" = "Müşteri hizmetleriyle iletişime geçin (WeChat: mxyz2050) danışın";
"MvpViewController2" = "Bu hesap kapatıldı";
"MvpViewController3" = "Daha güvenli bir ağ ortamı oluşturmak ve sizin ve diğerlerinin mülk güvenliğini korumak için\nlütfen önce kimlik doğrulaması yapın";
@@ -3784,3 +3786,24 @@
"20.20.59_text_34" = "Gönderim Başarılı";
"20.20.59_text_35" = "Alt başarılı";
"20.20.59_text_36" = "İptal başarılı";
"20.20.61_text_1" = "Madalyalarım";
"20.20.61_text_2" = "Madalya Takma";
"20.20.61_text_3" = "Görev Madalyaları";
"20.20.61_text_4" = "Etkinlik Madalyaları";
"20.20.61_text_5" = "Şan madalyaları";
"20.20.61_text_6" = "Hiçbir madalya takmıyorsunuz";
"20.20.61_text_7.1" = "Hiçbir madalya almadınız";
"20.20.61_text_7.2" = "Hiçbir madalya almadınız\nMadalya karesine gidin ve kontrol edin!";
"20.20.61_text_8" = "Son kullanma tarihi:%@";
"20.20.61_text_9" = "Sonsuza kadar";
"20.20.61_text_10" = "Madalya Karesi";
"20.20.61_text_11" = "Madalya Şeref Salonu";
"20.20.61_text_12" = "Güçlü Sahip";
"20.20.61_text_13" = "Madalyalarını görüntüle";
"20.20.61_text_14" = "%@'ın madalyası";
"20.20.61_text_15" = "Daha fazla madalya sergileme yuvası elde etmek için VIP'yi yükseltin!";
"20.20.61_text_16" = "Madalyalarınız dolu!\nÖnce ayarlayın ve sonra daha fazlasını ekleyin!";
"20.20.61_text_17" = "Madalya Koltuğu İpucu";
"20.20.61_text_18" = "Şimdi yükseltin!";
"20.20.61_text_19" = "Bonus";

View File

@@ -2263,7 +2263,8 @@
"LoginBindPhoneViewController2" = "綁定手機號";
"MvpViewController0" = "註銷時間: %@";
"MvpViewController1" = "%@\n\n請聯繫客服微信mxyz2050咨詢哦";
"MvpViewController1.1" = "%@\n\n請聯繫客服微信mxyz2050咨詢哦";
"MvpViewController1.2" = "請聯繫客服微信mxyz2050咨詢哦";
"MvpViewController2" = "該賬號已註銷";
"MvpViewController3" = "為了營造更安全的網絡環境\n保護您和他人的財產安全\n請先進行實名認證";
@@ -3657,17 +3658,23 @@
"20.20.59_text_35" = "訂閱成功";
"20.20.59_text_36" = "取消成功";
"20.20.61_text_1" = "My Medals";
"20.20.61_text_2" = "Wearing";
"20.20.61_text_3" = "Task Medals";
"20.20.61_text_4" = "Activity Medals";
"20.20.61_text_5" = "Glory Medals";
"20.20.61_text_6" = "You are not wearing any medals";
"20.20.61_text_7" = "You have not received any medals Go to the medal square and check it out!";
"20.20.61_text_8" = "Expiration time:%@";
"20.20.61_text_9" = "Forever";
"20.20.61_text_10" = "Medals Square";
"20.20.61_text_11" = "Medal Hall of Fame";
"20.20.61_text_12" = "Powerful Owner";
"20.20.61_text_13" = "View his medals";
"20.20.61_text_14" = "%@'s medal";
"20.20.61_text_1" = "我的獎牌";
"20.20.61_text_2" = "配戴獎牌";
"20.20.61_text_3" = "任務獎章";
"20.20.61_text_4" = "活動獎牌";
"20.20.61_text_5" = "榮耀勳章";
"20.20.61_text_6" = "你沒有戴任何獎牌";
"20.20.61_text_7.1" = "您尚未獲得任何勳章";
"20.20.61_text_7.2" = "您尚未獲得任何勳章\n去獎牌廣場看看吧";
"20.20.61_text_8" = "到期時間:%@";
"20.20.61_text_9" = "永遠";
"20.20.61_text_10" = "獎牌廣場";
"20.20.61_text_11" = "獎章名人堂";
"20.20.61_text_12" = "強大的拥有者";
"20.20.61_text_13" = "看他的獎牌";
"20.20.61_text_14" = "%@的勳章";
"20.20.61_text_15" = "升級VIP獲得更多勳章展示位";
"20.20.61_text_16" = "你的勳章已滿!\n先調整然後再增加更多";
"20.20.61_text_17" = "獎牌座位提示";
"20.20.61_text_18" = "立即升級!";
"20.20.61_text_19" = "額外獎勵";