diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index c33b016c..67d3afa7 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -495,6 +495,7 @@ 4C13929D2D70441500A6DFB5 /* giftgift.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 4C13929B2D70441500A6DFB5 /* giftgift.mp4 */; }; 4C1392A12D71675900A6DFB5 /* coincoin.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 4C1392A02D71675900A6DFB5 /* coincoin.mp4 */; }; 4C1892992CF84349004D4426 /* RoomCahtCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1892982CF84349004D4426 /* RoomCahtCell.m */; }; + 4C1A141B2DCB4AB700B6D0CA /* ChatFaceVo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A141A2DCB4AB700B6D0CA /* ChatFaceVo.m */; }; 4C38C2AD2D84064400CFA4A8 /* LoginInputItemView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C38C2AC2D84064300CFA4A8 /* LoginInputItemView.m */; }; 4C38C2B02D84070600CFA4A8 /* AccountBindingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C38C2AF2D84070600CFA4A8 /* AccountBindingViewController.m */; }; 4C44BD5D2D151B5C00F321FA /* RoomSideMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C44BD5C2D151B5C00F321FA /* RoomSideMenu.m */; }; @@ -2631,6 +2632,8 @@ 4C1392A02D71675900A6DFB5 /* coincoin.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = coincoin.mp4; sourceTree = ""; }; 4C1892972CF84349004D4426 /* RoomCahtCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomCahtCell.h; sourceTree = ""; }; 4C1892982CF84349004D4426 /* RoomCahtCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomCahtCell.m; sourceTree = ""; }; + 4C1A14192DCB4AB700B6D0CA /* ChatFaceVo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChatFaceVo.h; sourceTree = ""; }; + 4C1A141A2DCB4AB700B6D0CA /* ChatFaceVo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChatFaceVo.m; sourceTree = ""; }; 4C38C2AB2D84064300CFA4A8 /* LoginInputItemView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LoginInputItemView.h; sourceTree = ""; }; 4C38C2AC2D84064300CFA4A8 /* LoginInputItemView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LoginInputItemView.m; sourceTree = ""; }; 4C38C2AE2D84070600CFA4A8 /* AccountBindingViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AccountBindingViewController.h; sourceTree = ""; }; @@ -11026,6 +11029,8 @@ E8C1CD7927D8B29E00376F83 /* RoomFaceInfoModel.m */, E87C0A9E27D9DE6400CB2241 /* RoomFaceSendInfoModel.h */, E87C0A9F27D9DE6400CB2241 /* RoomFaceSendInfoModel.m */, + 4C1A14192DCB4AB700B6D0CA /* ChatFaceVo.h */, + 4C1A141A2DCB4AB700B6D0CA /* ChatFaceVo.m */, ); path = Model; sourceTree = ""; @@ -12528,6 +12533,7 @@ E85E7B292A4EB0D300B6D00A /* XPGuildTimePickView.m in Sources */, E85E7BBF2A4EE7AC00B6D00A /* XPMinePersonalCenterCell.m in Sources */, E8AC722426F47E5E007D6E91 /* XPMineFeedbackViewController.m in Sources */, + 4C1A141B2DCB4AB700B6D0CA /* ChatFaceVo.m in Sources */, E8664ED627E434D5000171BA /* XPRoomPKRecordViewController.m in Sources */, E87E914E2796678D00A7B3F2 /* XPMineDressEmptyTableViewCell.m in Sources */, 232EBBFF2BD7A25500E8CEAD /* MSParamsDecode.m in Sources */, diff --git a/YuMi/Config/ClientConfig.m b/YuMi/Config/ClientConfig.m index 91d38737..6c1fd483 100644 --- a/YuMi/Config/ClientConfig.m +++ b/YuMi/Config/ClientConfig.m @@ -16,6 +16,7 @@ #import "YYUtility.h" #import "XPWeakTimer.h" #import "Api+Main.h" +#import "ChatFaceVo.h" @interface ClientConfig () ///重试的次数 10次 如果你还是失败的话 那就算了 没办法了 @@ -103,8 +104,10 @@ model.hideNoticeVersion = [NSString versionCompareOldStr:serverVer andNewStr:shortVer]; self.configInfo = model; - + [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadAfterLoadConfig" object:nil]; + + [self requestFaceTabNewList]; } else { if (self.retryCount < 10) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ @@ -116,6 +119,26 @@ }]; } +- (void)requestFaceTabNewList { + [Api faceTabNewList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + if (code == 200) { + [[XPRoomFaceTool shareFaceTool] cacheChatFaces:data.data]; +#if DEBUG + NSArray *arr = [[XPRoomFaceTool shareFaceTool] loadFaceTabs]; + ChatFaceResponse *tab = [arr xpSafeObjectAtIndex:0]; + if (tab) { + ChatFaceVo *vo = [tab.faceNewVoList xpSafeObjectAtIndex:0]; + if (vo) { + [[XPRoomFaceTool shareFaceTool] loadFace:^(NSString * _Nonnull path) { + + } with:vo]; + } + } +#endif + } + }]; +} + - (void)clientConfig:(void(^)(void))finish { @kWeakify(self); [Api clientConfig:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { diff --git a/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m b/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m index 2f8a828c..7a423241 100644 --- a/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m +++ b/YuMi/Modules/YMMine/View/SubViews/MineInfo/XPMineUserInfoHeaderView.m @@ -490,7 +490,7 @@ HWDMP4PlayDelegate> }]; [self.copyIdImageView mas_makeConstraints:^(MASConstraintMaker *make) { - make.size.mas_equalTo(CGSizeMake(18, 18)); + make.size.mas_equalTo(CGSizeMake(20, 20)); }]; [self.experImageView mas_makeConstraints:^(MASConstraintMaker *make) { @@ -1143,8 +1143,10 @@ HWDMP4PlayDelegate> if (!_copyIdImageView) { _copyIdImageView = [[UIImageView alloc] init]; _copyIdImageView.userInteractionEnabled = YES; - _copyIdImageView.contentMode = UIViewContentModeScaleAspectFill; + _copyIdImageView.contentMode = UIViewContentModeScaleAspectFit; _copyIdImageView.image = [UIImage getLanguageImage:@"user_card_copy_id1"]; + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(copyNameAction)]; + [_copyIdImageView addGestureRecognizer:tap]; } return _copyIdImageView; } diff --git a/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m b/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m index 2110deeb..359c381f 100644 --- a/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m +++ b/YuMi/Modules/YMNewHome/View/XPNewHomeViewController.m @@ -355,6 +355,8 @@ XPHomeRecommendOtherRoomViewDelegate> @property(nonatomic, assign) NSInteger maxReloadTagsLimitCount; @property(nonatomic, assign) NSInteger reloadTagsLimitCount; +@property (nonatomic, assign) bool hasLoadAPIs; + @end @implementation XPNewHomeViewController @@ -393,6 +395,14 @@ XPHomeRecommendOtherRoomViewDelegate> - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; + + if (!self.hasLoadAPIs) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + [self.pagingView.mainTableView.mj_header beginRefreshing]; + }); + self.hasLoadAPIs = YES; + } + } - (void)tokenInvalid { @@ -465,7 +475,7 @@ XPHomeRecommendOtherRoomViewDelegate> [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(homeVCRefreshComplete) name:@"khomeVCRefreshComplete" object:nil]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(logOut) name:@"kInLoginVC" object:nil]; - [header beginRefreshing]; +// [header beginRefreshing]; } -(void)homeVCRefreshComplete{ @@ -480,7 +490,6 @@ XPHomeRecommendOtherRoomViewDelegate> } -(void)headerRefresh{ - [self.presenter getHomeTopData]; [self.presenter getHomeTagList]; [self.presenter getHomeRanks]; diff --git a/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.h b/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.h new file mode 100644 index 00000000..49c93aff --- /dev/null +++ b/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.h @@ -0,0 +1,28 @@ +// +// ChatFaceVo.h +// YuMi +// +// Created by P on 2025/5/7. +// +// 对应 http://beta.api.molistar.xyz/swagger-ui/index.html#/face-tab-new-controller/faceListUsingGET + +#import "PIBaseModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ChatFaceVo : PIBaseModel +@property (nonatomic, assign) NSInteger seqNo; +@property (nonatomic, copy) NSString *faceUrl; +@property (nonatomic, copy) NSString *faceIndex; +@property (nonatomic, assign) NSInteger showTimes; +@end + +@interface ChatFaceResponse : PIBaseModel +@property (nonatomic, assign) BOOL useVip; +@property (nonatomic, copy) NSString *tabUrl; +@property (nonatomic, assign) NSInteger tabId; +@property (nonatomic, assign) NSInteger tabSeq; +@property (nonatomic, copy) NSArray *faceNewVoList; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.m b/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.m new file mode 100644 index 00000000..6d7d8606 --- /dev/null +++ b/YuMi/Modules/YMRoom/View/FaceView/Model/ChatFaceVo.m @@ -0,0 +1,20 @@ +// +// ChatFaceVo.m +// YuMi +// +// Created by P on 2025/5/7. +// + +#import "ChatFaceVo.h" + +@implementation ChatFaceVo + +@end + +@implementation ChatFaceResponse ++ (NSDictionary *)mj_objectClassInArray { + return @{ + @"faceNewVoList" : [ChatFaceVo class] + }; +} +@end diff --git a/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceSendInfoModel.h b/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceSendInfoModel.h index f295b327..4bebecc4 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceSendInfoModel.h +++ b/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceSendInfoModel.h @@ -20,6 +20,9 @@ NS_ASSUME_NONNULL_BEGIN @property (strong, nonatomic) UIImage *resultImage; ///🎲数 @property (strong, nonatomic) NSMutableArray *resultIndexes; + +@property (nonatomic, copy) NSString *svgaURL; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceTitleItemModel.h b/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceTitleItemModel.h index 346f2082..a9ebac84 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceTitleItemModel.h +++ b/YuMi/Modules/YMRoom/View/FaceView/Model/RoomFaceTitleItemModel.h @@ -6,7 +6,7 @@ // #import - +@class ChatFaceResponse; NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger, RoomFaceTitleItemType) { ///普通的表情 @@ -22,6 +22,8 @@ typedef NS_ENUM(NSInteger, RoomFaceTitleItemType) { @property (nonatomic,assign) BOOL isSelect; ///类型 @property (nonatomic,assign) RoomFaceTitleItemType faceType; + +@property (nonatomic, strong) ChatFaceResponse *tabModel; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.h b/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.h index 8b11d053..8e8db5ce 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.h +++ b/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.h @@ -6,6 +6,7 @@ // 下载表情的工具 只是下载 不做其他的任何处理 #import +@class ChatFaceVo, ChatFaceResponse; NS_ASSUME_NONNULL_BEGIN @class RoomFaceInfoModel; @@ -31,6 +32,16 @@ NS_ASSUME_NONNULL_BEGIN /// 通过faceid 查找本地的表情信息 /// @param faceId faceId - (RoomFaceInfoModel *)findFaceInfoById:(NSInteger)faceId; + + +#pragma mark - New Face(SVGA) +- (NSArray *)loadFaceTabs; +- (void)cacheChatFaces:(NSArray *)data; +- (void)loadFace:(void(^)(NSString *path))fileBlock + with:(ChatFaceVo *)vo; +- (void)loadFace:(void(^)(NSString *path))fileBlock + withUrl:(NSString *)url; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.m b/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.m index 1afde907..35d66694 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.m +++ b/YuMi/Modules/YMRoom/View/FaceView/Presenter/XPRoomFaceTool.m @@ -12,9 +12,11 @@ #import "NSObject+MJExtension.h" #import "RoomFaceInfoModel.h" #import "NSArray+Safe.h" +#import "ChatFaceVo.h" #define FileHashDefaultChunkSizeForReadingData 1024*8 // 8K NSString * const kRoomFaceVersion = @"kRoomFaceVersion"; +NSString * const kNewFacePath = @"MoliFaceCache"; @interface XPRoomFaceTool () ///解压缩之后 表情资源所在的位置 @@ -23,6 +25,9 @@ NSString * const kRoomFaceVersion = @"kRoomFaceVersion"; @property (nonatomic,assign) NSInteger retryCount; ///表情信息 @property (nonatomic,strong) NSArray *faceInfoList; + +@property (nonatomic, copy) NSArray *chatFaceTabList; + @end @implementation XPRoomFaceTool @@ -254,4 +259,95 @@ done: } +#pragma mark - New Face(SVGA) +- (NSArray *)loadFaceTabs { + return self.chatFaceTabList; +} + +- (void)loadFace:(void(^)(NSString *path))fileBlock with:(ChatFaceVo *)vo { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self loadFace:fileBlock withUrl:vo.faceUrl]; + }); +} + +- (void)loadFace:(void(^)(NSString *path))fileBlock + withUrl:(NSString *)url { + NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject + stringByAppendingPathComponent:kNewFacePath]; + NSString *fileName = [url lastPathComponent]; + NSString *filePath = [cachePath stringByAppendingPathComponent:fileName]; + + NSString *resultPath = [[NSFileManager defaultManager] fileExistsAtPath:filePath] ? filePath : nil; + + dispatch_async(dispatch_get_main_queue(), ^{ + if (fileBlock) { + fileBlock(resultPath); + } + }); +} + +- (void)cacheChatFaces:(NSArray *)data { + self.chatFaceTabList = [ChatFaceResponse modelsWithArray:data]; + NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject + stringByAppendingPathComponent:kNewFacePath]; + + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + NSMutableDictionary *cachedUrls = [[defaults objectForKey:@"SVGACachedUrls"] mutableCopy] ?: [NSMutableDictionary dictionary]; + + for (ChatFaceResponse *response in self.chatFaceTabList) { + for (ChatFaceVo *faceVo in response.faceNewVoList) { + // 从URL中获取文件名 + NSString *fileName = [faceVo.faceUrl lastPathComponent]; + NSString *filePath = [cachePath stringByAppendingPathComponent:fileName]; + + // 检查URL是否已缓存且文件存在 + if ([cachedUrls[faceVo.faceUrl] isEqualToString:fileName] && + [[NSFileManager defaultManager] fileExistsAtPath:filePath]) { + NSLog(@"已有 SVGA文件缓存:%@", faceVo.faceUrl); + continue; + } + + [self downloadFaceFile:faceVo.faceUrl savePath:cachePath completion:^(BOOL success) { + if (success) { + // 下载成功后更新缓存记录 + cachedUrls[faceVo.faceUrl] = fileName; + [defaults setObject:cachedUrls forKey:@"SVGACachedUrls"]; + [defaults synchronize]; + NSLog(@"SVGA文件缓存成功:%@ - %@", faceVo.faceUrl, filePath); + } + }]; + } + } +} + +- (NSString *)md5HashOfString:(NSString *)string { + const char *ptr = [string UTF8String]; + unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH]; + CC_MD5(ptr, (CC_LONG)strlen(ptr), md5Buffer); + NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; + for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { + [output appendFormat:@"%02x", md5Buffer[i]]; + } + return output; +} + +- (BOOL)verifyFileMD5:(NSString *)filePath expectedMD5:(NSString *)expectedMD5 { + NSString *fileMD5 = [[self getFileMD5WithPath:filePath] lowercaseString]; + return [fileMD5 isEqualToString:[expectedMD5 lowercaseString]]; +} + +- (void)downloadFaceFile:(NSString *)urlString savePath:(NSString *)savePath completion:(void(^)(BOOL))completion { + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; + AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; + + NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]]; + + [[manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { + [[NSFileManager defaultManager] createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil]; + return [NSURL fileURLWithPath:[savePath stringByAppendingPathComponent:response.suggestedFilename]]; + } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { + completion(error == nil); + }] resume]; +} + @end diff --git a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.h b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.h index e8f3b99d..f324fc57 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.h +++ b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.h @@ -6,6 +6,7 @@ // #import +@class ChatFaceVo; NS_ASSUME_NONNULL_BEGIN @class RoomFaceInfoModel; @@ -14,6 +15,9 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,assign) NSInteger vipLevel; ///表情信息 @property (nonatomic,strong) RoomFaceInfoModel *faceInfo; + +@property (nonatomic, assign) ChatFaceVo *chatFace; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.m b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.m index 5c9921c8..566d1c39 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.m +++ b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceCollectionViewCell.m @@ -13,10 +13,11 @@ #import "DJDKMIMOMColor.h" ///Model #import "RoomFaceInfoModel.h" +#import "ChatFaceVo.h" @interface XPRoomFaceCollectionViewCell () ///表情的图片 -@property (nonatomic,strong) UIImageView *faceImageView; +@property (nonatomic,strong) NetImageView *faceImageView; ///表情的标题 @property (nonatomic,strong) UILabel *faceTitleLabel; ///VIP的类型 @@ -75,6 +76,13 @@ }]; } #pragma mark - Getters And Setters +- (void)setChatFace:(ChatFaceVo *)chatFace { + _chatFace = chatFace; + if (chatFace) { + self.faceImageView.imageUrl = chatFace.faceIndex; + } +} + - (void)setFaceInfo:(RoomFaceInfoModel *)faceInfo { _faceInfo = faceInfo; if (_faceInfo) { @@ -95,9 +103,9 @@ } } -- (UIImageView *)faceImageView { +- (NetImageView *)faceImageView { if (!_faceImageView) { - _faceImageView = [[UIImageView alloc] init]; + _faceImageView = [[NetImageView alloc] init]; _faceImageView.userInteractionEnabled = YES; } return _faceImageView; diff --git a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceTitleCollectionViewCell.m b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceTitleCollectionViewCell.m index 51f0d733..8130d4a5 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceTitleCollectionViewCell.m +++ b/YuMi/Modules/YMRoom/View/FaceView/View/Cell/XPRoomFaceTitleCollectionViewCell.m @@ -12,10 +12,12 @@ #import "DJDKMIMOMColor.h" ///Model #import "RoomFaceTitleItemModel.h" +#import "ChatFaceVo.h" @interface XPRoomFaceTitleCollectionViewCell () ///标题 @property (nonatomic,strong) UILabel *titleLabel; +@property (nonatomic, strong) NetImageView *imageView; @end @implementation XPRoomFaceTitleCollectionViewCell @@ -30,23 +32,43 @@ return self; } +- (void)prepareForReuse { + [super prepareForReuse]; + if (self.titleModel.tabModel){ + self.imageView.hidden = NO; + } else { + self.imageView.hidden = YES; + } +} + #pragma mark - Private Method - (void)initSubViews { [self.contentView addSubview:self.titleLabel]; + [self.contentView addSubview:self.imageView]; } - (void)initSubViewConstraints { [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.edges.mas_equalTo(self.contentView); }]; + + [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.mas_equalTo(self.contentView); + }]; } #pragma mark - Getters And Setters - (void)setTitleModel:(RoomFaceTitleItemModel *)titleModel { _titleModel = titleModel; - if (_titleLabel) { - self.titleLabel.text = _titleModel.title; - self.titleLabel.textColor = _titleModel.isSelect ? [DJDKMIMOMColor appMainColor] : [UIColor whiteColor]; - } + self.titleLabel.hidden = titleModel.tabModel; + self.imageView.hidden = !titleModel.tabModel; + if (titleModel.tabModel) { + [self.imageView setImageUrl:titleModel.tabModel.tabUrl]; + } else { + if (titleModel) { + self.titleLabel.text = titleModel.title; + self.titleLabel.textColor = titleModel.isSelect ? [DJDKMIMOMColor appMainColor] : [UIColor whiteColor]; + } + } } - (UILabel *)titleLabel { @@ -58,4 +80,11 @@ return _titleLabel; } +- (NetImageView *)imageView { + if (!_imageView) { + _imageView = [[NetImageView alloc] init]; + } + return _imageView; +} + @end diff --git a/YuMi/Modules/YMRoom/View/FaceView/View/XPRoomFaceViewController.m b/YuMi/Modules/YMRoom/View/FaceView/View/XPRoomFaceViewController.m index b9ce65fe..d55be5b7 100644 --- a/YuMi/Modules/YMRoom/View/FaceView/View/XPRoomFaceViewController.m +++ b/YuMi/Modules/YMRoom/View/FaceView/View/XPRoomFaceViewController.m @@ -28,6 +28,8 @@ #import "XPRoomFacePresenter.h" #import "XPRoomFaceProtocol.h" +#import "ChatFaceVo.h" + @interface XPRoomFaceViewController () ///顶部的View @property (nonatomic,strong) UIView * topView; @@ -46,7 +48,7 @@ ///分页控件 @property (nonatomic, strong) UIPageControl *pageView; ///滑块的内容 -@property (nonatomic,strong) NSArray *titleList; +@property (nonatomic,strong) NSMutableArray *titleList; ///当前选中的 @property (nonatomic,strong) RoomFaceTitleItemModel *selectTitleItem; ///表情 @@ -55,6 +57,8 @@ @property (nonatomic,strong) NSArray *nobelFaceList; ///用户信息 @property (nonatomic,strong) UserInfoModel *userInfo; + + @end @implementation XPRoomFaceViewController @@ -70,6 +74,13 @@ [self initSubViewConstraints]; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + [UIView animateWithDuration:0.5 animations:^{ + self.topView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2]; + }]; +} + #pragma mark - Private Method - (void)initData { [self.presenter getUserInfo]; @@ -102,7 +113,29 @@ [self.stackView addArrangedSubview:self.pageView]; [self.titleStackView addArrangedSubview:self.titleCollectionView]; - [self.titleStackView addArrangedSubview:self.noblePrivilButton]; +// [self.titleStackView addArrangedSubview:self.noblePrivilButton]; + + NSArray *faceTabs = [[XPRoomFaceTool shareFaceTool] loadFaceTabs]; + for (ChatFaceResponse *tab in faceTabs) { + RoomFaceTitleItemModel *item = [[RoomFaceTitleItemModel alloc] init]; + item.title= @(tab.tabId).stringValue; + item.isSelect = NO; + item.faceType = RoomFaceTitleItemType_Normal; + item.tabModel = tab; + [self.titleList addObject:item]; + +// NetImageView *tabImageView = [[NetImageView alloc] init]; +// [self.titleStackView addArrangedSubview:tabImageView]; +// [tabImageView loadImageWithUrl:tab.tabUrl +// completion:^(UIImage * _Nullable image, NSURL * _Nonnull url) { +// CGSize s = image.size; +// CGFloat scale = 28 / s.height; +// CGFloat width = s.width * scale; +// [tabImageView mas_makeConstraints:^(MASConstraintMaker *make) { +// make.size.mas_equalTo(CGSizeMake(width, 28)); +// }]; +// }]; + } self.selectTitleItem = [self.titleList firstObject]; } @@ -138,13 +171,13 @@ make.height.mas_equalTo(collectionViewHeight); }]; - - [self.noblePrivilButton mas_makeConstraints:^(MASConstraintMaker *make) { - make.size.mas_equalTo(CGSizeMake(84, 26)); - }]; +// [self.noblePrivilButton mas_makeConstraints:^(MASConstraintMaker *make) { +// make.size.mas_equalTo(CGSizeMake(84, 26)); +// }]; [self.titleCollectionView mas_makeConstraints:^(MASConstraintMaker *make) { - make.height.mas_equalTo(28); + make.width.mas_equalTo(108); + make.height.mas_equalTo(28); }]; } @@ -159,6 +192,31 @@ self.pageView.currentPage = 0; } +- (void)sendNewFaceCustomMessage:(ChatFaceVo *)vo { + NSMutableArray *faceRecieveInfos = [NSMutableArray array]; + RoomFaceSendInfoModel *sendInfo = [[RoomFaceSendInfoModel alloc]init]; + sendInfo.svgaURL = vo.faceUrl; + sendInfo.nick = self.userInfo.nick; + sendInfo.faceId = vo.seqNo; + sendInfo.uid = self.userInfo.uid; + [faceRecieveInfos addObject:sendInfo.model2dictionary]; + + AttachmentModel * attachment = [[AttachmentModel alloc] init]; + attachment.first = CustomMessageType_Face; + attachment.second = Custom_Message_Sub_Face_Send; + NSDictionary * dic = @{@"data":faceRecieveInfos, @"uid": @(self.userInfo.uid)}; + attachment.data = dic; + NSString *sessionID = self.roomId; + NIMMessage *message = [[NIMMessage alloc]init]; + NIMCustomObject *object = [[NIMCustomObject alloc] init]; + object.attachment = attachment; + message.messageObject = object; + //构造会话 + NIMSession *session = [NIMSession session:sessionID type:NIMSessionTypeChatroom]; + [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:nil]; + [self dismissViewControllerAnimated:YES completion:nil]; +} + - (void)sendFaceCustomMessage:(RoomFaceInfoModel *)faceInfo { RoomFaceSendInfoModel *sendInfo = [[RoomFaceSendInfoModel alloc]init]; NSMutableArray *resultIndexs = [NSMutableArray array]; @@ -246,19 +304,31 @@ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { if (collectionView == self.titleCollectionView) { RoomFaceTitleItemModel * itemModel = [self.titleList xpSafeObjectAtIndex:indexPath.row]; - CGSize size = [itemModel.title boundingRectWithSize:CGSizeMake(120, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine - attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size; - return CGSizeMake(size.width + 10, size.height); - } - CGFloat itemWidth = (CGFloat)(KScreenWidth - 15 * 2 - 10 * 4) / (CGFloat)5; - return CGSizeMake(itemWidth, itemWidth + 20); + if (itemModel.tabModel) { + return CGSizeMake(34, 34); + } else { + CGSize size = [itemModel.title boundingRectWithSize:CGSizeMake(120, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine + attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size; + return CGSizeMake(size.width + 10, size.height); + } + } else if (collectionView == self.faceCollectionView) { + CGFloat itemWidth = (CGFloat)(KScreenWidth - 15 * 2 - 10 * 4) / (CGFloat)5; + return CGSizeMake(itemWidth, itemWidth + 20); + } + return CGSizeZero; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { if (collectionView == self.titleCollectionView) { return self.titleList.count; - } - return self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal? self.faceList.count : self.nobelFaceList.count; + } else if (collectionView == self.faceCollectionView) { + if (self.selectTitleItem.tabModel) { + return self.selectTitleItem.tabModel.faceNewVoList.count; + } else { + return self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal? self.faceList.count : self.nobelFaceList.count; + } + } + return 0; } - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { @@ -274,16 +344,22 @@ return cell; } - XPRoomFaceCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([XPRoomFaceCollectionViewCell class]) forIndexPath:indexPath]; - RoomFaceInfoModel * faceInfo; - if (self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal) { - faceInfo = [self.faceList xpSafeObjectAtIndex:indexPath.row]; - } else { - faceInfo = [self.nobelFaceList xpSafeObjectAtIndex:indexPath.row]; - } - cell.vipLevel = self.userInfo.userVipInfoVO.vipLevel; - cell.faceInfo =faceInfo; - return cell; + if (self.selectTitleItem.tabModel) { + XPRoomFaceCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NewChatFace" forIndexPath:indexPath]; + cell.chatFace = [self.selectTitleItem.tabModel.faceNewVoList xpSafeObjectAtIndex:indexPath.row]; + return cell; + } else { + XPRoomFaceCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([XPRoomFaceCollectionViewCell class]) forIndexPath:indexPath]; + RoomFaceInfoModel * faceInfo; + if (self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal) { + faceInfo = [self.faceList xpSafeObjectAtIndex:indexPath.row]; + } else { + faceInfo = [self.nobelFaceList xpSafeObjectAtIndex:indexPath.row]; + } + cell.vipLevel = self.userInfo.userVipInfoVO.vipLevel; + cell.faceInfo =faceInfo; + return cell; + } } - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { @@ -291,30 +367,38 @@ RoomFaceTitleItemModel * titleModel = [self.titleList xpSafeObjectAtIndex:indexPath.row]; self.selectTitleItem = titleModel; [self.titleCollectionView reloadData]; + NSArray * list = titleModel.faceType == RoomFaceTitleItemType_Normal ? self.faceList : self.nobelFaceList; [self updatePageViewState:list]; [self.faceCollectionView reloadData]; } else { - if (self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal) { - RoomFaceInfoModel * faceInfo = [self.faceList xpSafeObjectAtIndex:indexPath.row]; - [self sendFaceCustomMessage:faceInfo]; - } else { - if (indexPath.row < self.nobelFaceList.count) { - RoomFaceInfoModel * faceInfo = [self.nobelFaceList xpSafeObjectAtIndex:indexPath.row]; - if (faceInfo.faceVipInfo.vipLevel > self.userInfo.userVipInfoVO.vipLevel) { - TTAlertConfig *config = [[TTAlertConfig alloc] init]; - config.message = [NSString stringWithFormat:YMLocalizedString(@"XPRoomFaceViewController1"), faceInfo.name,faceInfo.faceVipInfo.vipName]; - config.actionStyle = TTAlertActionConfirmStyle; - [TTPopup alertWithConfig:config confirmHandler:^{ - - } cancelHandler:^{ - - }]; - } else { - [self sendFaceCustomMessage:faceInfo]; - } - } - } + if (self.selectTitleItem.tabModel) { + ChatFaceVo *vo = [self.selectTitleItem.tabModel.faceNewVoList xpSafeObjectAtIndex:indexPath.row]; + if (vo) { + [self sendNewFaceCustomMessage:vo]; + } + } else { + if (self.selectTitleItem.faceType == RoomFaceTitleItemType_Normal) { + RoomFaceInfoModel * faceInfo = [self.faceList xpSafeObjectAtIndex:indexPath.row]; + [self sendFaceCustomMessage:faceInfo]; + } else { + if (indexPath.row < self.nobelFaceList.count) { + RoomFaceInfoModel * faceInfo = [self.nobelFaceList xpSafeObjectAtIndex:indexPath.row]; + if (faceInfo.faceVipInfo.vipLevel > self.userInfo.userVipInfoVO.vipLevel) { + TTAlertConfig *config = [[TTAlertConfig alloc] init]; + config.message = [NSString stringWithFormat:YMLocalizedString(@"XPRoomFaceViewController1"), faceInfo.name,faceInfo.faceVipInfo.vipName]; + config.actionStyle = TTAlertActionConfirmStyle; + [TTPopup alertWithConfig:config confirmHandler:^{ + + } cancelHandler:^{ + + }]; + } else { + [self sendFaceCustomMessage:faceInfo]; + } + } + } + } } } @@ -347,7 +431,6 @@ - (UIView *)topView { if (!_topView) { _topView = [[UIView alloc] init]; - _topView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2]; UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMissViewRecognizer)]; tap.cancelsTouchesInView = NO; tap.delegate = self; @@ -430,6 +513,7 @@ _faceCollectionView.backgroundColor = [UIColor clearColor]; _faceCollectionView.pagingEnabled = YES; [_faceCollectionView registerClass:[XPRoomFaceCollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([XPRoomFaceCollectionViewCell class])]; + [_faceCollectionView registerClass:[XPRoomFaceCollectionViewCell class] forCellWithReuseIdentifier:@"NewChatFace"]; } return _faceCollectionView; } @@ -442,7 +526,7 @@ return _pageView; } -- (NSArray *)titleList { +- (NSMutableArray *)titleList { if (!_titleList) { RoomFaceTitleItemModel * normalItem = [[RoomFaceTitleItemModel alloc] init]; normalItem.title= YMLocalizedString(@"XPRoomFaceViewController2"); @@ -453,7 +537,7 @@ nobelItem.title= YMLocalizedString(@"XPRoomFaceViewController3"); nobelItem.isSelect = NO; nobelItem.faceType = RoomFaceTitleItemType_Nobel; - _titleList = @[normalItem, nobelItem]; + _titleList = @[normalItem, nobelItem].mutableCopy; } return _titleList; } diff --git a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m index f76c3719..a8b98f23 100644 --- a/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m +++ b/YuMi/Modules/YMRoom/View/SendGiftView/GiftComboManager.m @@ -502,11 +502,15 @@ @"Price": @(receive.gift.goldPrice * receive.giftNum * array.count), @"isFromWinning":@(NO)}]; } else { - self.errorMessage = msg; + if (code > 500) { + self.errorMessage = @"Over Heat!"; + } else { + self.errorMessage = msg; + } if (self.actionCallback) { self.actionCallback(ComboAction_Error); } - [self forceRemove]; +// [self forceRemove]; } } targetUids:allUIDs diff --git a/YuMi/Modules/YMRoom/View/SendGiftView/View/XPSendGiftView.m b/YuMi/Modules/YMRoom/View/SendGiftView/View/XPSendGiftView.m index ba8e3bb9..2d8421c3 100644 --- a/YuMi/Modules/YMRoom/View/SendGiftView/View/XPSendGiftView.m +++ b/YuMi/Modules/YMRoom/View/SendGiftView/View/XPSendGiftView.m @@ -202,7 +202,11 @@ UIKIT_EXTERN NSString * kShowFirstRechargeView; } break; case ComboAction_Error: { - [self showErrorToast:[[GiftComboManager sharedManager] loadErrorMessage]]; + NSString *message = [[GiftComboManager sharedManager] loadErrorMessage]; + if (![NSString isEmpty:message]) { + [self showErrorToast:message]; + } + } break; case ComboAction_Update_After_Send_Success: { diff --git a/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m b/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m index 1d352d2d..cd138fbf 100644 --- a/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m +++ b/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m @@ -66,6 +66,7 @@ @property (nonatomic,strong) SVGAImageView *headWearSVGAImageView; ///表情 @property (nonatomic, strong) UIImageView *faceImageView; +@property (nonatomic, strong) SVGAImageView *faceSvgaImageView; ///pk类型的按钮 @property (nonatomic,strong) UIButton *groupTypeButton; ///头饰播放 @@ -119,6 +120,7 @@ [self addSubview:self.forbidKickView]; [self addSubview:self.giftValueView]; [self addSubview:self.faceImageView]; + [self addSubview:self.faceSvgaImageView]; [self addSubview:self.groupTypeButton]; [self addSubview:self.goldLabel]; @@ -182,6 +184,12 @@ make.width.mas_equalTo(kGetScaleWidth(80)); make.height.mas_equalTo(80); }]; + + [self.faceSvgaImageView mas_makeConstraints:^(MASConstraintMaker *make) { + make.center.mas_equalTo(self.avatarImageView); + make.width.mas_equalTo(kGetScaleWidth(100)); + make.height.mas_equalTo(100); + }]; [self.groupTypeButton mas_makeConstraints:^(MASConstraintMaker *make) { make.size.mas_equalTo(CGSizeMake(38, 16)); @@ -407,6 +415,23 @@ } - (void)showingFace:(RoomFaceSendInfoModel *)receiveInfo{ + if (![NSString isEmpty:receiveInfo.svgaURL]) { + @kWeakify(self); + [[XPRoomFaceTool shareFaceTool] loadFace:^(NSString * _Nonnull path) { + @kStrongify(self); + SVGAParser *p = [[SVGAParser alloc] init]; + [p parseWithURL:[NSURL fileURLWithPath:path] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) { + self.faceSvgaImageView.videoItem = videoItem; + [self.faceSvgaImageView startAnimation]; + } failureBlock:^(NSError * _Nullable error) { + [self.faceSvgaImageView stopAnimation]; + }]; + } withUrl:receiveInfo.svgaURL]; +// [self.faceSvgaImageView setImageName:]; + return; + } + + [self.faceImageView.layer removeAnimationForKey:@"face"]; UIImage * result; if (receiveInfo.resultIndexes.count > 0) { @@ -880,6 +905,23 @@ return _faceImageView; } +- (SVGAImageView *)faceSvgaImageView { + if (!_faceSvgaImageView) { + _faceSvgaImageView = [[SVGAImageView alloc]init]; + _faceSvgaImageView.backgroundColor = [UIColor clearColor]; + _faceSvgaImageView.frame = CGRectZero; + _faceSvgaImageView.userInteractionEnabled = YES; + _faceSvgaImageView.autoPlay = YES; + _faceSvgaImageView.clearsAfterStop = YES; +#if DEBUG + _faceSvgaImageView.loops = 1; +#else + _faceSvgaImageView.loops = 1; +#endif + } + return _faceSvgaImageView; +} + - (UIButton *)groupTypeButton { if (!_groupTypeButton) { _groupTypeButton = [UIButton buttonWithType:UIButtonTypeCustom]; diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.h b/YuMi/Modules/YMTabbar/Api/Api+Main.h index cbe72789..9a2cc279 100644 --- a/YuMi/Modules/YMTabbar/Api/Api+Main.h +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.h @@ -57,6 +57,8 @@ NS_ASSUME_NONNULL_BEGIN +(void)requestAuthorizationCodeInfo:(HttpRequestHelperCompletion)completion; +(void)requestMineChannel:(HttpRequestHelperCompletion)completion; +// 新增表情包列表 ++(void)faceTabNewList:(HttpRequestHelperCompletion)completion; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMTabbar/Api/Api+Main.m b/YuMi/Modules/YMTabbar/Api/Api+Main.m index d939ab62..5076a520 100644 --- a/YuMi/Modules/YMTabbar/Api/Api+Main.m +++ b/YuMi/Modules/YMTabbar/Api/Api+Main.m @@ -96,4 +96,7 @@ [self makeRequest:@"charge/guide/channel" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; } ++(void)faceTabNewList:(HttpRequestHelperCompletion)completion { + [self makeRequest:@"faceTabNew/list" method:HttpRequestHelperMethodGET completion:completion,__FUNCTION__, nil]; +} @end diff --git a/YuMi/Modules/YMTabbar/View/TabbarViewController.m b/YuMi/Modules/YMTabbar/View/TabbarViewController.m index 7bace4a4..c65d0e42 100644 --- a/YuMi/Modules/YMTabbar/View/TabbarViewController.m +++ b/YuMi/Modules/YMTabbar/View/TabbarViewController.m @@ -460,6 +460,10 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; [networkManager startMonitoring]; } +- (void)requestFaceList { + +} + - (void)cacheRoomResource { [Api requestRoomResource:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if (code == 200) {