From ace27b7e915b31d0811c6829b2c7d60db30a8924 Mon Sep 17 00:00:00 2001 From: liyuhua <15626451870@163.com> Date: Tue, 7 May 2024 19:40:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=AC=E8=81=8A=E5=A4=A7=E5=8E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YuMi.xcodeproj/project.pbxproj | 40 + YuMi/Config/ClientConfig.m | 1 + YuMi/Config/ClientDataModel.h | 1 + YuMi/Config/ClientDataModel.m | 1 + YuMi/Modules/YMMessage/Api/Api+Message.h | 6 + YuMi/Modules/YMMessage/Api/Api+Message.m | 12 + .../Model/MSSessionPublicChatHallTopModel.h | 20 + .../Model/MSSessionPublicChatHallTopModel.m | 12 + .../YMMessage/Model/MSSessionScrollingModel.h | 26 + .../YMMessage/Model/MSSessionScrollingModel.m | 12 + .../YMMessage/Presenter/MessagePresenter.h | 13 +- .../YMMessage/Presenter/MessagePresenter.m | 61 ++ .../Protocol/MSSessionScrollingProtocol.h | 18 + .../YMMessage/Protocol/MessageProtocol.h | 8 +- .../View/Session/Content/MessageContentText.m | 6 +- .../View/Session/MSSessionPublicChatHallVC.h | 16 + .../View/Session/MSSessionPublicChatHallVC.m | 801 ++++++++++++++++++ .../View/Session/SessionViewController.m | 5 +- .../Session/View/MSSessionScrollingView.h | 36 + .../Session/View/MSSessionScrollingView.m | 220 +++++ .../View/Session/View/SessionNavView.h | 4 + .../View/Session/View/SessionNavView.m | 7 +- .../View/AnimationView/XPRoomAnimationView.m | 2 +- .../XPRoomFunctionContainerView.m | 50 +- .../View/MenuContainerView/MSRoomMenuGameVC.m | 9 + .../Tool/XPRoomMessageParser.m | 36 +- .../XPRoomMessageContainerView.m | 1 + .../View/StageView/MicroView/MicroView.m | 2 +- .../UserCard/Presenter/XPUserCardPresenter.m | 2 +- .../UserCard/Protocol/XPUserCardProtocol.h | 1 + .../UserCard/View/XPUserCardViewController.m | 4 +- .../YMRoom/View/XPRoomViewController.m | 5 +- YuMi/Modules/YMWeb/MSRoomGameWebVC.m | 36 +- YuMi/Structure/MVP/Model/PIBaseModel.m | 28 +- YuMi/Tools/CALayer/CALayer+Animation.h | 20 + YuMi/Tools/CALayer/CALayer+Animation.m | 29 + YuMi/ar.lproj/Localizable.strings | 13 +- YuMi/en.lproj/Localizable.strings | 11 +- YuMi/zh-Hans.lproj/Localizable.strings | 9 +- YuMi/zh-Hant.lproj/Localizable.strings | 9 +- 40 files changed, 1508 insertions(+), 85 deletions(-) create mode 100644 YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.h create mode 100644 YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.m create mode 100644 YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.h create mode 100644 YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.m create mode 100644 YuMi/Modules/YMMessage/Protocol/MSSessionScrollingProtocol.h create mode 100644 YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.h create mode 100644 YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.m create mode 100644 YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.h create mode 100644 YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.m create mode 100644 YuMi/Tools/CALayer/CALayer+Animation.h create mode 100644 YuMi/Tools/CALayer/CALayer+Animation.m diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index d3cde682..012700b3 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -212,6 +212,11 @@ 234489092AC3C5FF0070E5D5 /* SudMGP.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 234489072AC3C5DA0070E5D5 /* SudMGP.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 234D821E2AEC57CF0022EFEB /* YYTextAsyncLayer+PITextAsyncLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 234D821D2AEC57CF0022EFEB /* YYTextAsyncLayer+PITextAsyncLayer.m */; }; 234F44E32B3EA4F900E2B532 /* PILineManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 234F44E22B3EA4F900E2B532 /* PILineManager.swift */; }; + 2357145A2BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 235714592BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.m */; }; + 235714602BE8BD5C004C81D6 /* MSSessionScrollingModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2357145F2BE8BD5C004C81D6 /* MSSessionScrollingModel.m */; }; + 235714642BE8BEA0004C81D6 /* CALayer+Animation.m in Sources */ = {isa = PBXBuildFile; fileRef = 235714632BE8BEA0004C81D6 /* CALayer+Animation.m */; }; + 235714672BE8C009004C81D6 /* MSSessionScrollingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 235714662BE8C009004C81D6 /* MSSessionScrollingView.m */; }; + 2357146B2BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 2357146A2BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.m */; }; 235A451A2B04A352009753F5 /* PIRoomActivityWebView.m in Sources */ = {isa = PBXBuildFile; fileRef = 235A45192B04A352009753F5 /* PIRoomActivityWebView.m */; }; 235A451D2B04A452009753F5 /* PIRoomActivityWebCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 235A451C2B04A452009753F5 /* PIRoomActivityWebCell.m */; }; 235A45232B04BEB6009753F5 /* PIBaseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 235A45222B04BEB6009753F5 /* PIBaseModel.m */; }; @@ -1924,6 +1929,17 @@ 234D821C2AEC57CF0022EFEB /* YYTextAsyncLayer+PITextAsyncLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "YYTextAsyncLayer+PITextAsyncLayer.h"; path = "YuMi/Appdelegate/YYTextAsyncLayer+PITextAsyncLayer.h"; sourceTree = SOURCE_ROOT; }; 234D821D2AEC57CF0022EFEB /* YYTextAsyncLayer+PITextAsyncLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = "YYTextAsyncLayer+PITextAsyncLayer.m"; path = "YuMi/Appdelegate/YYTextAsyncLayer+PITextAsyncLayer.m"; sourceTree = SOURCE_ROOT; }; 234F44E22B3EA4F900E2B532 /* PILineManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PILineManager.swift; sourceTree = ""; }; + 235714582BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSSessionPublicChatHallVC.h; sourceTree = ""; }; + 235714592BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSSessionPublicChatHallVC.m; sourceTree = ""; }; + 2357145E2BE8BD5C004C81D6 /* MSSessionScrollingModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSSessionScrollingModel.h; sourceTree = ""; }; + 2357145F2BE8BD5C004C81D6 /* MSSessionScrollingModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSSessionScrollingModel.m; sourceTree = ""; }; + 235714622BE8BEA0004C81D6 /* CALayer+Animation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CALayer+Animation.h"; sourceTree = ""; }; + 235714632BE8BEA0004C81D6 /* CALayer+Animation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "CALayer+Animation.m"; sourceTree = ""; }; + 235714652BE8C009004C81D6 /* MSSessionScrollingView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSSessionScrollingView.h; sourceTree = ""; }; + 235714662BE8C009004C81D6 /* MSSessionScrollingView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSSessionScrollingView.m; sourceTree = ""; }; + 235714682BE8C055004C81D6 /* MSSessionScrollingProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSSessionScrollingProtocol.h; sourceTree = ""; }; + 235714692BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MSSessionPublicChatHallTopModel.h; sourceTree = ""; }; + 2357146A2BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MSSessionPublicChatHallTopModel.m; sourceTree = ""; }; 235A45182B04A352009753F5 /* PIRoomActivityWebView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PIRoomActivityWebView.h; sourceTree = ""; }; 235A45192B04A352009753F5 /* PIRoomActivityWebView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PIRoomActivityWebView.m; sourceTree = ""; }; 235A451B2B04A452009753F5 /* PIRoomActivityWebCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PIRoomActivityWebCell.h; sourceTree = ""; }; @@ -4922,6 +4938,7 @@ 189DD5A726DFA09700AB55B1 /* Tools */ = { isa = PBXGroup; children = ( + 235714612BE8BE88004C81D6 /* CALayer */, 234F44E12B3EA4DC00E2B532 /* YMLine */, 23CEFC082AFB8FC100576D89 /* sdkContent */, 23FF255C2ABA8EEE0064E904 /* PIIAPTool */, @@ -5113,6 +5130,10 @@ 18F404BA2760982000A6C548 /* ChatLimitModel.m */, E885D5342977CE28004DC088 /* SessionSettingModel.h */, E885D5352977CE28004DC088 /* SessionSettingModel.m */, + 2357145E2BE8BD5C004C81D6 /* MSSessionScrollingModel.h */, + 2357145F2BE8BD5C004C81D6 /* MSSessionScrollingModel.m */, + 235714692BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.h */, + 2357146A2BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.m */, ); path = Model; sourceTree = ""; @@ -5160,6 +5181,7 @@ isa = PBXGroup; children = ( 18F404C6276099DF00A6C548 /* MessageProtocol.h */, + 235714682BE8C055004C81D6 /* MSSessionScrollingProtocol.h */, ); path = Protocol; sourceTree = ""; @@ -5524,6 +5546,15 @@ path = YMLine; sourceTree = ""; }; + 235714612BE8BE88004C81D6 /* CALayer */ = { + isa = PBXGroup; + children = ( + 235714622BE8BEA0004C81D6 /* CALayer+Animation.h */, + 235714632BE8BEA0004C81D6 /* CALayer+Animation.m */, + ); + path = CALayer; + sourceTree = ""; + }; 236B2E1B2AA0786E003967A8 /* Library */ = { isa = PBXGroup; children = ( @@ -6400,6 +6431,8 @@ 23FF256C2ABC48810064E904 /* XPSessionMainViewController.m */, 9B7D80482753783D003DAC0C /* SessionViewController.h */, 9B7D80492753783D003DAC0C /* SessionViewController.m */, + 235714582BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.h */, + 235714592BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.m */, E8E20BD9281645300033B688 /* SessionInfoViewController.h */, E8E20BDA281645300033B688 /* SessionInfoViewController.m */, E86E79D428A4EA0C006DAF48 /* SessionRiskCache.h */, @@ -9486,6 +9519,8 @@ E88E4A7F297673DC00019A50 /* SessionNavLiveView.m */, E885D5372977D10E004DC088 /* SessionSettingUserView.h */, E885D5382977D10E004DC088 /* SessionSettingUserView.m */, + 235714652BE8C009004C81D6 /* MSSessionScrollingView.h */, + 235714662BE8C009004C81D6 /* MSSessionScrollingView.m */, ); path = View; sourceTree = ""; @@ -11587,6 +11622,7 @@ E85E7B372A4EB0D300B6D00A /* XPMineGuildListCell.m in Sources */, E85E7B502A4EB0D300B6D00A /* XPMineGuildListVC.m in Sources */, E824546126F5F4E400BE8163 /* XPMineResetPayPwdViewController.m in Sources */, + 2357146B2BEA0110004C81D6 /* MSSessionPublicChatHallTopModel.m in Sources */, E81D58822720082A003063FE /* MicroWaveView.m in Sources */, E8A73F8728586A6F00FD9CBC /* XPGiftWeekStarCollectionViewCell.m in Sources */, E80E09B62A42078F00CD2BE7 /* XPRoomStarKitchenModel.m in Sources */, @@ -11792,6 +11828,7 @@ 23FF256E2ABC48810064E904 /* XPSessionMainViewController.m in Sources */, E85E7B092A4EB0D200B6D00A /* XPGuildRemoveMemberPresenter.m in Sources */, E8950186282CAC80007E459A /* XPMonentsTooBarView.m in Sources */, + 2357145A2BE8BC6C004C81D6 /* MSSessionPublicChatHallVC.m in Sources */, E86507E5281A7D4D006951B0 /* MessageContentTweetView.m in Sources */, E824544B26F5BBB800BE8163 /* XPMineModifPayPwdViewController.m in Sources */, E81C1B2227705F950020D1E4 /* Api+ArrangeMic.m in Sources */, @@ -11893,6 +11930,7 @@ 23CEFC5F2AFB8FC100576D89 /* BSLogTableViewController.m in Sources */, 236B2E4D2AA07D06003967A8 /* XPRoomLittleGameContainerView.m in Sources */, E87AE8C1284E184300CAFBB3 /* RoomNewUserGreetModel.m in Sources */, + 235714602BE8BD5C004C81D6 /* MSSessionScrollingModel.m in Sources */, 9BC5C91C277C8A7B007C8719 /* XPReleaseRadioViewController.m in Sources */, 23B2AEC42A6516C200543D17 /* LoginForgetPasswordViewController.m in Sources */, 186A534C26FC6ED900D67B2C /* TTAlertView.m in Sources */, @@ -11971,6 +12009,7 @@ 238B37C92AC55A2C00BFC9D5 /* XPTreasureFairyStoreResultSmallView.m in Sources */, E8C1CD7027D894B800376F83 /* RoomFaceTitleItemModel.m in Sources */, E85E7B4B2A4EB0D300B6D00A /* XPMineGuildManagerSetViewController.m in Sources */, + 235714642BE8BEA0004C81D6 /* CALayer+Animation.m in Sources */, 189DD73D26E21C3F00AB55B1 /* YYUtility+Device.m in Sources */, 187EEEDC26E89B32002833B2 /* BaseModel.m in Sources */, 23CEFC682AFCCE7700576D89 /* PIGiftInfoSegmentedView.m in Sources */, @@ -12017,6 +12056,7 @@ 238B37B02AC55A2C00BFC9D5 /* XPTreasureFairyStoreResultCell.m in Sources */, E8AEAEED27141AE20017FCE0 /* XPRoomBackContainerView.m in Sources */, E88B5CC126FB407B00DA9178 /* XPMineUserInfoViewController.m in Sources */, + 235714672BE8C009004C81D6 /* MSSessionScrollingView.m in Sources */, 2331C1AC2A60F32D00E1D940 /* CandyTreeRecordModel.m in Sources */, E81E09CF290F750800A1F410 /* AdvertiseModel.m in Sources */, 2305F3472AD94E9D00AD403C /* XPMaskManagerCell.m in Sources */, diff --git a/YuMi/Config/ClientConfig.m b/YuMi/Config/ClientConfig.m index dee0b475..10d19136 100644 --- a/YuMi/Config/ClientConfig.m +++ b/YuMi/Config/ClientConfig.m @@ -92,6 +92,7 @@ model.appStoreAuditNoticeVersion = isHigh; self.configInfo = model; [[NSNotificationCenter defaultCenter] postNotificationName:@"reloadnewtab" object:nil]; + } else { if (self.retryCount < 10) { [self clientInit]; diff --git a/YuMi/Config/ClientDataModel.h b/YuMi/Config/ClientDataModel.h index 74c89740..8b509656 100644 --- a/YuMi/Config/ClientDataModel.h +++ b/YuMi/Config/ClientDataModel.h @@ -39,6 +39,7 @@ typedef NS_ENUM(NSInteger, FaceLivenessStrategy) { @property (nonatomic, strong) NSArray *officialMsgUids; ///官方账号 小秘书 红包消息 @property (nonatomic,strong) NSArray *officialAccountUids; +@property(nonatomic,copy) NSDictionary *publicChatRoomIdMap; ///星座礼物顶部是否开启 @property (nonatomic,assign) BOOL twelveStarSwitch; /// 开房是否需要实名 diff --git a/YuMi/Config/ClientDataModel.m b/YuMi/Config/ClientDataModel.m index 906813b7..59424417 100644 --- a/YuMi/Config/ClientDataModel.m +++ b/YuMi/Config/ClientDataModel.m @@ -16,4 +16,5 @@ } } + @end diff --git a/YuMi/Modules/YMMessage/Api/Api+Message.h b/YuMi/Modules/YMMessage/Api/Api+Message.h index c3e2030c..17463687 100644 --- a/YuMi/Modules/YMMessage/Api/Api+Message.h +++ b/YuMi/Modules/YMMessage/Api/Api+Message.h @@ -14,6 +14,12 @@ NS_ASSUME_NONNULL_BEGIN + (void)getChatLimit:(HttpRequestHelperCompletion)complection receiverUid:(NSString *)receiverUid ; ///获取私聊限制接口 +(void)getPrivateChatCheck:(HttpRequestHelperCompletion)complection content:(NSString *)content toUid:(NSString *)toUid; +///聊天室发送头条 ++(void)sendPublicChatHallTopText:(HttpRequestHelperCompletion)complection content:(NSString *)content; +///获取聊天室头条 ++(void)getPublicChatHallTopText:(HttpRequestHelperCompletion)complection; +///获取聊天室数据 ++(void)getPublicChatHallList:(HttpRequestHelperCompletion)complection; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/Api/Api+Message.m b/YuMi/Modules/YMMessage/Api/Api+Message.m index 07df3a24..3df26989 100644 --- a/YuMi/Modules/YMMessage/Api/Api+Message.m +++ b/YuMi/Modules/YMMessage/Api/Api+Message.m @@ -17,4 +17,16 @@ +(void)getPrivateChatCheck:(HttpRequestHelperCompletion)complection content:(NSString *)content toUid:(NSString *)toUid{ [self makeRequest:@"privateChat/check" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__, content,toUid,nil]; } +///聊天室发送头条 ++(void)sendPublicChatHallTopText:(HttpRequestHelperCompletion)complection content:(NSString *)content{ + [self makeRequest:@"publicChatTopRecord/send" method:HttpRequestHelperMethodPOST completion:complection, __FUNCTION__, content,nil]; +} +///获取聊天室发送头条 ++(void)getPublicChatHallTopText:(HttpRequestHelperCompletion)complection{ + [self makeRequest:@"publicChatTopRecord/send" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__, nil]; +} +///获取聊天室数据 ++(void)getPublicChatHallList:(HttpRequestHelperCompletion)complection{ + [self makeRequest:@"publicChatTopRecord/getChatForTop50" method:HttpRequestHelperMethodGET completion:complection, __FUNCTION__, nil]; +} @end diff --git a/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.h b/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.h new file mode 100644 index 00000000..4b8569f9 --- /dev/null +++ b/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.h @@ -0,0 +1,20 @@ +// +// MSSessionPublicChatHallTopModel.h +// YuMi +// +// Created by duoban on 2024/5/7. +// + +#import "PIBaseModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MSSessionPublicChatHallTopModel : PIBaseModel +@property(nonatomic,copy) NSString *uid; +@property(nonatomic,copy) NSString *content; +@property(nonatomic,assign) BOOL isTop; +@property(nonatomic,copy) NSString *partitionId; +@property(nonatomic,assign) NSString *recordStatus; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.m b/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.m new file mode 100644 index 00000000..b73796a2 --- /dev/null +++ b/YuMi/Modules/YMMessage/Model/MSSessionPublicChatHallTopModel.m @@ -0,0 +1,12 @@ +// +// MSSessionPublicChatHallTopModel.m +// YuMi +// +// Created by duoban on 2024/5/7. +// + +#import "MSSessionPublicChatHallTopModel.h" + +@implementation MSSessionPublicChatHallTopModel + +@end diff --git a/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.h b/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.h new file mode 100644 index 00000000..0357c67d --- /dev/null +++ b/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.h @@ -0,0 +1,26 @@ +// +// MSSessionScrollingModel.h +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "PIBaseModel.h" +#import "MSSessionScrollingProtocol.h" +NS_ASSUME_NONNULL_BEGIN + +@interface MSSessionScrollingModel : PIBaseModel +@property (nonatomic,assign)NSTimeInterval beginTime; +@property (nonatomic,assign)NSTimeInterval endTime; +@property (nonatomic,copy)NSString *content; +@property (nonatomic,copy)NSString *fromAvatar; +@property(nonatomic,copy) NSString *fromNick; +@property(nonatomic,copy) NSString *fromUid; +@property (nonatomic,copy)NSString *gender; +@property(nonatomic,copy) NSString *partitionId; +@property (nonatomic,copy)NSString *toAvatar; +@property(nonatomic,copy) NSString *toNick; +@property(nonatomic,copy) NSString *toUid; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.m b/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.m new file mode 100644 index 00000000..4bc402fb --- /dev/null +++ b/YuMi/Modules/YMMessage/Model/MSSessionScrollingModel.m @@ -0,0 +1,12 @@ +// +// MSSessionScrollingModel.m +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "MSSessionScrollingModel.h" + +@implementation MSSessionScrollingModel + +@end diff --git a/YuMi/Modules/YMMessage/Presenter/MessagePresenter.h b/YuMi/Modules/YMMessage/Presenter/MessagePresenter.h index c09b700e..a7d5918d 100644 --- a/YuMi/Modules/YMMessage/Presenter/MessagePresenter.h +++ b/YuMi/Modules/YMMessage/Presenter/MessagePresenter.h @@ -6,7 +6,7 @@ // #import "BaseMvpPresenter.h" - +#import "UserInfoModel.h" NS_ASSUME_NONNULL_BEGIN @interface MessagePresenter : BaseMvpPresenter @@ -24,7 +24,16 @@ NS_ASSUME_NONNULL_BEGIN // 获取用户信息 - (void)getUserInfoWithUid:(NSString *)uid; - +///进入聊天室 +- (void)enterNIMRoom:(NSString *)roomId user:(UserInfoModel *)userInfo; +///退出聊天室 +- (void)exitNIMRoom:(NSString *)roomId; +///聊天室发送头条 +-(void)sendPublicChatHallTopTextWithcontent:(NSString *)content; +///获取聊天室发送头条 +-(void)getPublicChatHallTopText; +///获取聊天室数据 +-(void)getPublicChatHallList; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/Presenter/MessagePresenter.m b/YuMi/Modules/YMMessage/Presenter/MessagePresenter.m index 0cbcb5a9..0b940178 100644 --- a/YuMi/Modules/YMMessage/Presenter/MessagePresenter.m +++ b/YuMi/Modules/YMMessage/Presenter/MessagePresenter.m @@ -13,6 +13,7 @@ #import "UserInfoModel.h" #import "AccountInfoStorage.h" #import "NIMMessageUtils.h" +#import "XPMessageRemoteExtModel.h" @implementation MessagePresenter @@ -61,5 +62,65 @@ [[self getView] attentionUserSuccess:targetUid]; } showLoading:YES] uid:uid likedUid:targetUid ticket:ticket type:type]; } +- (void)enterNIMRoom:(NSString *)roomId user:(UserInfoModel *)userInfo { + NIMChatroomEnterRequest *request = [[NIMChatroomEnterRequest alloc] init]; + request.roomId = roomId; + //设置ext + XPMessageRemoteExtModel * extModel = [[XPMessageRemoteExtModel alloc] init]; + extModel.defUser = userInfo.defUser; + extModel.erbanNo = userInfo.erbanNo; + extModel.carName = userInfo.carName; + extModel.inRoomNameplatePic = userInfo.nameplatePic; + extModel.inRoomNameplateWord = userInfo.nameplateWord; + extModel.isCustomWord = userInfo.isCustomWord; + extModel.charmUrl = userInfo.userLevelVo.charmUrl; + extModel.experLevelSeq = userInfo.userLevelVo.experLevelSeq; + extModel.experUrl = userInfo.userLevelVo.experUrl; + extModel.newUser = userInfo.newUser; + extModel.vipIcon = userInfo.userVipInfoVO.vipIcon; + extModel.fromUid = userInfo.fromUid; + extModel.fromType = userInfo.fromType; + extModel.fromNick = userInfo.fromNick; + extModel.iosBubbleUrl = userInfo.iosBubbleUrl; + extModel.androidBubbleUrl = userInfo.androidBubbleUrl; + extModel.enterHide = userInfo.userVipInfoVO.enterHide; + extModel.preventKick = userInfo.userVipInfoVO.preventKick; + extModel.enterRoomEffects = userInfo.userVipInfoVO.enterRoomEffects; + extModel.gender = userInfo.gender; + extModel.fromSayHelloChannel = userInfo.fromSayHelloChannel; + extModel.platformRole = userInfo.platformRole; + + NSMutableDictionary *ext = [NSMutableDictionary dictionaryWithObject:extModel.model2dictionary forKey:[NSString stringWithFormat:@"%ld", userInfo.uid]]; + request.roomExt = [ext toJSONString]; + + [[NIMSDK sharedSDK].chatroomManager enterChatroom:request completion:^(NSError * _Nullable error, NIMChatroom * _Nullable chatroom, NIMChatroomMember * _Nullable me) { + if (error) { + [[self getView] enterPublicChatHallFail:error.code]; + } else { + [[self getView] enterPublicChatHallSuccess:chatroom]; + } + }]; +} +- (void)exitNIMRoom:(NSString *)roomId { + [[NIMSDK sharedSDK].chatroomManager exitChatroom:roomId completion:nil]; +} +///聊天室发送头条 +-(void)sendPublicChatHallTopTextWithcontent:(NSString *)content{ + [Api sendPublicChatHallTopText:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + + } showLoading:YES errorToast:YES] content:content]; +} +///获取聊天室发送头条 +-(void)getPublicChatHallTopText{ + [Api getPublicChatHallTopText:[self createHttpCompletion:^(BaseModel * _Nonnull data) { + + }]]; +} +///获取聊天室数据 +-(void)getPublicChatHallList{ + [Api getPublicChatHallList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { + + }]; +} @end diff --git a/YuMi/Modules/YMMessage/Protocol/MSSessionScrollingProtocol.h b/YuMi/Modules/YMMessage/Protocol/MSSessionScrollingProtocol.h new file mode 100644 index 00000000..b1b0f1c7 --- /dev/null +++ b/YuMi/Modules/YMMessage/Protocol/MSSessionScrollingProtocol.h @@ -0,0 +1,18 @@ +// +// MSSessionScrollingProtocol.h +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol MSSessionScrollingProtocol +@required +@property (nonatomic,readonly)NSTimeInterval beginTime; +@property (nonatomic,readonly)NSTimeInterval endTime; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/Protocol/MessageProtocol.h b/YuMi/Modules/YMMessage/Protocol/MessageProtocol.h index eb93b450..e0c80b29 100644 --- a/YuMi/Modules/YMMessage/Protocol/MessageProtocol.h +++ b/YuMi/Modules/YMMessage/Protocol/MessageProtocol.h @@ -7,12 +7,12 @@ #import -@class ChatLimitModel, UserInfoModel; +@class ChatLimitModel, UserInfoModel,NIMChatroom; NS_ASSUME_NONNULL_BEGIN @protocol MessageProtocol - +@optional - (void)onGetLimitChat:(ChatLimitModel *)chatLimit; ///获取用户信息成功 @@ -24,6 +24,10 @@ NS_ASSUME_NONNULL_BEGIN ///获取用户信息 - (void)onGetUserInfoSuccess:(UserInfoModel *)userInfo; +///进入聊天室成功 +-(void)enterPublicChatHallSuccess:(NIMChatroom *)chatRoom; +///进入聊天室失败 +-(void)enterPublicChatHallFail:(NSInteger)code; @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/View/Session/Content/MessageContentText.m b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentText.m index 6d793065..b03a996d 100644 --- a/YuMi/Modules/YMMessage/View/Session/Content/MessageContentText.m +++ b/YuMi/Modules/YMMessage/View/Session/Content/MessageContentText.m @@ -71,9 +71,7 @@ }]; } } --(void)aa{ - NSLog(@"%f,%f",self.messageText.frame.size.width,(CONTENT_WIDTH_MAX - MESSAGE_TEXT_PADDING * 2)); -} + - (YYLabel *)messageText { if (!_messageText) { _messageText = [[YYLabel alloc]initWithFrame:CGRectZero]; @@ -81,8 +79,6 @@ _messageText.textColor = DJDKMIMOMColor.mainTextColor; _messageText.numberOfLines = 0; _messageText.userInteractionEnabled = YES; - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(aa)]; - [_messageText addGestureRecognizer:tap]; } return _messageText; } diff --git a/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.h b/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.h new file mode 100644 index 00000000..bb28ee60 --- /dev/null +++ b/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.h @@ -0,0 +1,16 @@ +// +// MSSessionPublicChatHallVC.h +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "MvpViewController.h" +#import +NS_ASSUME_NONNULL_BEGIN + +@interface MSSessionPublicChatHallVC : MvpViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.m b/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.m new file mode 100644 index 00000000..641ec096 --- /dev/null +++ b/YuMi/Modules/YMMessage/View/Session/MSSessionPublicChatHallVC.m @@ -0,0 +1,801 @@ +// +// MSSessionPublicChatHallVC.m +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "MSSessionPublicChatHallVC.h" +#import +#import +#import +#import +///Tool +#import "XCCurrentVCStackManager.h" +#import "NIMMessageMaker.h" +#import "UITableView+NIMScrollToBottom.h" +#import "QEmotionHelper.h" +#import "QKeyboardManager.h" +#import "ClientConfig.h" +///Model +#import "QPhotoImageModel.h" +#import "AttachmentModel.h" +#import "MessageBaseModel.h" +#import "MessageTextModel.h" +#import "MessageAudioModel.h" +#import "MessageTimeModel.h" +#import "MessageImageModel.h" +#import "MessageUnSupportModel.h" +#import "MessageTipsModel.h" +///View +#import "MessageCell.h" +#import "XPMineUserInfoViewController.h" +#import "SessionNavView.h" +#import "QInputBarView.h" +#import "QKeyboardManager.h" +#import "QEmotionBoardView.h" +#import "QinputPhotoView.h" +#import "SessionUserInfoTableViewCell.h" +///P +#import "MessagePresenter.h" +#import "MessageProtocol.h" +#import "Api+Message.h" +#import "XPRoomMessageConstant.h" + +@interface MSSessionPublicChatHallVC () +@property (nonatomic, strong) NIMSession * session; +@property (nonatomic, strong) NSMutableArray * messages; +@property (nonatomic,strong) SessionNavView *sessionNavView; +@property (nonatomic, strong) UITableView * sessionTableView; +@property (nonatomic,strong) NIMMessage *lastMessage; +@property(nonatomic,strong)QInputBarView *inputBarView; +@property(nonatomic,strong)QKeyboardManager *keyboardManager; +@property (nonatomic, strong) UserInfoModel *userInfo; +///相册 +@property (nonatomic,strong) QinputPhotoView *photoView; +/// +@property (nonatomic,strong) NSArray *phototArray; +@property(nonatomic,assign) BOOL isLoadHistoryMessage; +@property(nonatomic,copy) NSString *publicChatMessageRoomId; +@end + +@implementation MSSessionPublicChatHallVC +- (BOOL)isHiddenNavBar { + return YES; +} + +- (void)dealloc { + [[NIMSDK sharedSDK].chatManager removeDelegate:self]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (MessagePresenter *)createPresenter { + return [[MessagePresenter alloc] init]; +} + + + +- (void)viewDidLoad { + [super viewDidLoad]; + self.isLoadHistoryMessage = YES; + [self initViews]; + [self initLayout]; + [self initHeaderAndFooterRrfresh]; + [IQKeyboardManager sharedManager].enable = NO; + [IQKeyboardManager sharedManager].enableAutoToolbar = NO; + + [[NIMSDK sharedSDK].chatManager addDelegate:self]; + +} + + + +- (void)initHeaderAndFooterRrfresh { + [self initData]; +} + + + +#pragma mark - 提前加载相册中的图片 +- (void)loadAlbumPhotos { + [YYUtility checkAssetsLibrayAvailable:^{ + } denied:^{ + } restriction:^{ + }]; +} + +#pragma mark - cell的样式 +- (MessageBaseModel *)modeTransformMessage:(NIMMessage *)message { + MessageBaseModel * model; + switch (message.messageType) { + case NIMMessageTypeText: + model = [[MessageTextModel alloc] initWithMessage:message]; + break; + case NIMMessageTypeAudio: + model = [[MessageAudioModel alloc] initWithMessage:message]; + break; + case NIMMessageTypeImage: + model = [[MessageImageModel alloc] initWithMessage:message]; + break; + case NIMMessageTypeTip: + model = [[MessageTipsModel alloc] initWithMessage:message]; + break; + + default: + model = [[MessageUnSupportModel alloc] initWithMessage:message]; + break; + break; + } + return model; +} + + + +- (UINavigationController *)getKeyWindowNav { + if ([XCCurrentVCStackManager shareManager].getCurrentVC) { + return [XCCurrentVCStackManager shareManager].getCurrentVC.navigationController; + } + return self.navigationController; +} + +- (MessageBaseModel *)createTimeMessage:(NIMMessage *)message { + MessageTimeModel * timeModel = [[MessageTimeModel alloc] initWithMessage:message]; + timeModel.time = [self timestrToTimeSecond:[NSString stringWithFormat:@"%f", message.timestamp]]; + return timeModel; +} + +- (NSString *)timestrToTimeSecond:(NSString *)timeStr {//timestr 豪秒 + NSTimeInterval interval = [timeStr doubleValue]; + NSDate *date = [NSDate dateWithTimeIntervalSince1970:interval]; + return [NSDate stringFromDate:date]; +} + +- (void)addTimeMessage:(NIMMessage *)message { + if (self.messages.count > 0) { + NIMMessage * lastMessage = self.messages.lastObject.message; + CGFloat dur = message.timestamp - lastMessage.timestamp; + if (dur / 60 > 5) { + NIMMessage * newMessage = [[NIMMessage alloc] init]; + newMessage.timestamp = message.timestamp; + [newMessage setValue:self.session forKey:@"session"]; + MessageBaseModel * timeModel = [self createTimeMessage:newMessage]; + [self.messages addObject:timeModel]; + } + } +} + +- (void)addRevokeMessage:(NIMMessage *)message title:(NSString *)title { + NIMMessage * revokeMessage = [[NIMMessage alloc] init]; + [revokeMessage setValue:self.session forKey:@"session"]; + [revokeMessage setValue:@(NIMMessageTypeTip) forKey:@"messageType"]; + revokeMessage.timestamp = [PLTimeUtil getNowTimeTimestampMillisecond].longLongValue; + revokeMessage.text = title; + [[NIMSDK sharedSDK].conversationManager saveMessage:revokeMessage forSession:self.session completion:nil]; +} + +#pragma mark - Private Method + +- (void)initInputView { + // 初始化输入工具条,frame可以先这样临时设置,下面的addBottomInputBarView方法会重置输入条frame + // 如果你想要自定义输入条View,请参考TextFieldViewController代码 + QInputBarViewConfiguration *inputBarViewConfiguration = [QInputBarViewConfiguration defaultInputBarViewConfiguration]; + inputBarViewConfiguration.voiceButtonHidden = NO;//隐藏语音按钮 + inputBarViewConfiguration.extendButtonHidden = YES;//隐藏拓展按钮 + inputBarViewConfiguration.toolHidden = NO; + inputBarViewConfiguration.giftButtonHidden = NO; + inputBarViewConfiguration.cameraButtonHidden = NO; + inputBarViewConfiguration.photoButtonHidden = NO; + _inputBarView = [[QInputBarView alloc] initWithFrame:CGRectMake(0,0,self.view.frame.size.width,inputBarViewConfiguration.inputViewHeight)]; + [_inputBarView setupWithConfiguration:inputBarViewConfiguration]; + _inputBarView.delegate = self; + //keyboard管理类,用来管理键盘,各大面板的切换 + _keyboardManager = [[QKeyboardManager alloc] initWithViewController:self]; + _keyboardManager.dataSource = self; + //因为addBottomInputBarView方法会立刻触发delegate,所以这里需要先设置delegate + _keyboardManager.delegate = self; + [_keyboardManager addBottomInputBarView:_inputBarView belowViewController:NO]; + //把输入框(如果有的话)绑定给管理类 + [_keyboardManager bindTextView:_inputBarView.inputTextView]; +} + + +- (void)initViews { + [self.view addSubview:self.sessionNavView]; + [self.view addSubview:self.sessionTableView]; + [self initInputView]; +} + +- (void)initLayout { + [self.sessionNavView mas_makeConstraints:^(MASConstraintMaker *make) { + make.height.mas_equalTo(kNavigationHeight); + make.leading.top.trailing.mas_equalTo(self.view); + }]; +} + +- (void)viewDidLayoutSubviews{ + +} + +- (void)initData { +// NIMUser * user = [[NIMSDK sharedSDK].userManager userInfo:self.session.sessionId]; +// if (user) { +// self.sessionNavView.title = user.userInfo.nickName; +// } else { +// self.sessionNavView.title = YMLocalizedString(@"XNDJTDDLoadingTool0"); +// } + + [self.presenter getUserInfo:self.session.sessionId]; +} + +- (BOOL)isExistMessages:(NIMMessage *)message{ + BOOL isExist = NO; + NIMMessage * model; + for (NIMMessage *item in self.messages.reverseObjectEnumerator.allObjects) { + if ([item isKindOfClass:[NIMMessage class]] && [item.messageId isEqualToString:message.messageId]) { + model = item; + isExist = YES; + break; + } + } + if (model) { + model = message; + } + return isExist; +} + + + + + +///获取用户信息成功 +- (void)onGetSessionUserInfoSuccess:(UserInfoModel *)userInfo { + _userInfo = userInfo; + self.sessionNavView.userInfo = userInfo; + self.publicChatMessageRoomId = [ClientConfig shareConfig].configInfo.publicChatRoomIdMap[_userInfo.partitionId]; + + if(self.publicChatMessageRoomId.length > 0){ + _session = [NIMSession session:self.publicChatMessageRoomId type:NIMSessionTypeChatroom]; + [self.presenter enterNIMRoom:self.publicChatMessageRoomId user:userInfo]; + } + + +} + +///进入聊天室成功 +-(void)enterPublicChatHallSuccess:(NIMChatroom *)chatRoom{ + [self handleFetchHistoryMessage]; +} +///进入聊天室失败 +-(void)enterPublicChatHallFail:(NSInteger)code{ + +} + +- (void)handleFetchHistoryMessage { + + NSString *roomId = self.publicChatMessageRoomId; + NIMHistoryMessageSearchOption *option = [[NIMHistoryMessageSearchOption alloc] init]; + option.limit = 100; + option.order = NIMMessageSearchOrderAsc; + option.messageTypes = @[@(NIMMessageTypeText),@(NIMMessageTypeImage),@(NIMMessageTypeAudio)]; + [[NIMSDK sharedSDK].chatroomManager fetchMessageHistory:roomId option:option result:^(NSError * _Nullable error, NSArray * _Nullable messages) { + if(error != nil){ + self.isLoadHistoryMessage = NO; + } + NIMHistoryMessageSearchOption *option = [[NIMHistoryMessageSearchOption alloc] init]; + option.limit = [ClientConfig shareConfig].configInfo.roomMessageCount; + option.order = NIMMessageSearchOrderDesc; + option.messageTypes = @[@(NIMMessageTypeText),@(NIMMessageTypeCustom)]; + [[NIMSDK sharedSDK].chatroomManager fetchMessageHistory:roomId option:option result:^(NSError * _Nullable error, NSArray * _Nullable messages) { + if(error != nil){ + self.isLoadHistoryMessage = NO; + } + dispatch_async(dispatch_get_main_queue(), ^{///回到主线程 + /// + if (self.messages.count > kRoomMessageMaxLength) { + NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)]; + NSArray *needRemoveMsgArray = [self.messages objectsAtIndexes:set]; + [self.messages removeObjectsInArray:needRemoveMsgArray]; + }else{ + + for (NIMMessage *message in messages) { + [self addTimeMessage:message]; + if (message.isDeleted) { + continue; + } + MessageBaseModel * model = [self modeTransformMessage:message]; + [self.messages addObject:model]; + } + } + // 执行插入 + + [self.sessionTableView reloadData]; + //执行插入动画并滚动 + if(self.messages.count > 0){ + NSIndexPath *ip = [NSIndexPath indexPathForRow:self.messages.count-1 inSection:0]; //取最后一行数据 + [self.sessionTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionBottom animated:YES]; //滚动到最后一行 + + } + + }); + }]; + + }]; +} + +#pragma mark - MessageCellDelegate +- (void)updateMessageSuccess:(NIMMessage *)message { + if ([message.session.sessionId isEqualToString:self.session.sessionId]) { + [self.sessionTableView reloadData]; + } +} + +- (void)didTapAvatar:(NSString *)uid { + XPMineUserInfoViewController * infoVC = [[XPMineUserInfoViewController alloc] init]; + infoVC.uid = uid.integerValue; + [[self getKeyWindowNav] pushViewController:infoVC animated:YES]; +} + + + + +#pragma mark - SessionNavViewDelegate + + +- (void)sessionNavView:(SessionNavView *)view didClickBack:(UIButton *)sender { + [self.navigationController popViewControllerAnimated:YES]; +} + + + + +#pragma mark - UITableViewDataSource +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + + return self.messages.count; + +} + +- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath { + + MessageBaseModel * message = [self.messages safeObjectAtIndex1:indexPath.row]; + NSString * identifier = [message cellContent:message]; + ///从复用池中获取所需要的cell + MessageCell * cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + if (!cell) { + ///如果没有的话 根据identifier 注册一下 重新获取一下即可 + [tableView registerClass:[MessageCell class] forCellReuseIdentifier:identifier]; + ///如果注册过了 就不需要判断cell是否为空 + cell = [tableView dequeueReusableCellWithIdentifier:identifier]; + } + cell.delegate = self; + [cell renderWithMessage:[self.messages safeObjectAtIndex1:indexPath.row]]; + return cell; + +} + +- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { + MessageBaseModel *msg = [self.messages safeObjectAtIndex1:indexPath.row]; + return msg.height; +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + [self.keyboardManager hideAllBoardView]; +} + +#pragma mark - NIMChatManagerDelegate +- (void)onRecvMessages:(NSArray *)messages { + if(!messages.count){ + return; + } + NIMMessage *message = messages.firstObject; + NIMSession *session = message.session; + + if (self.messages.count > kRoomMessageMaxLength) { + NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, kRoomMessageMaxLength/2)]; + NSArray *needRemoveMsgArray = [self.messages objectsAtIndexes:set]; + [self.messages removeObjectsInArray:needRemoveMsgArray]; + } + for (NIMMessage *message in messages) { + [self addTimeMessage:message]; + if (message.isDeleted) { + continue; + } + MessageBaseModel * model = [self modeTransformMessage:message]; + [self.messages addObject:model]; + } + [self.sessionTableView reloadData]; + [self.sessionTableView nim_scrollToBottom:YES]; + +} + +- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error { + if (message.session.sessionType != NIMSessionTypeChatroom) { + return; + } + + [self addTimeMessage:message]; + + if (![self isExistMessages:message]) { + MessageBaseModel * model = [self modeTransformMessage:message]; + [self.messages addObject:model]; + } + + if (message.yidunAntiSpamRes) { + NSDictionary * spamRes = message.yidunAntiSpamRes.toJSONObject; + NSDictionary * spamResExt = ((NSString *)spamRes[@"ext"]).toJSONObject; + if ([spamResExt[@"antispam"][@"suggestion"] intValue] == 2) { + NSDictionary * dic = @{@"suggestion": @"2"}; + message.localExt = dic; + [[NIMSDK sharedSDK].conversationManager updateMessage:message forSession:self.session completion:nil]; + } + } + [self.sessionTableView reloadData]; + [self.sessionTableView nim_scrollToBottom:YES]; +} + + + + + + +- (void)sendTextMessage:(NSString *)text { + + NIMMessage *message = [NIMMessageMaker msgWithText:text]; + + [[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil]; + + + +} + +- (void)audioRecordCompletion:(NSString *)recordPath { + + NIMMessage *message = [NIMMessageMaker msgWithAudio:recordPath]; + + [[[NIMSDK sharedSDK] chatManager] sendMessage:message toSession:self.session error:nil]; + + +} + +#pragma mark - TZImagePickerControllerDelegate +- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto infos:(NSArray *)infos { + [photos enumerateObjectsUsingBlock:^(UIImage * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (obj) { + NIMMessage * message = [NIMMessageMaker msgWithImage:obj]; + // 发送消息 + [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; + + + } + }]; +} + + + +#pragma mark - SessionUserInfoTableViewCellDelegate +- (void)sessionUserInfoTableViewCell:(SessionUserInfoTableViewCell *)view showUserInfoVC:(UserInfoModel *)userInfo { + [self didTapAvatar:[NSString stringWithFormat:@"%ld", userInfo.uid]]; +} + +#pragma mark - InputBoardDataSource +//@return 点加号按钮弹出的拓展面板View,且无需设置frame +- (UIView *)keyboardManagerExtendBoardView:(QKeyboardManager *)keyboardManager { + UIView *boardView = [UIView new]; + boardView.backgroundColor = UIColor.clearColor; + return boardView; +} + +//@return 点表情按钮弹出的表情面板View,且无需设置frame +- (UIView *)keyboardManagerEmotionBoardView:(QKeyboardManager *)keyboardManager { + QEmotionBoardView *emotionView = [[QEmotionBoardView alloc] init]; + QEmotionHelper *faceManager = [QEmotionHelper sharedEmotionHelper]; + emotionView.emotions = faceManager.emotionArray; + emotionView.delegate = self; + if (@available(iOS 11.0, *)) { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + emotionView.backgroundColor = [UIColor colorNamed:@"q_input_extend_bg" inBundle:bundle compatibleWithTraitCollection:nil]; + } else { + emotionView.backgroundColor = [UIColor colorWithRed:(246)/255.0f green:(246)/255.0f blue:(246)/255.0f alpha:1]; + } + return emotionView; +} + +//@return 点表情按钮弹出的表情面板View,且无需设置frame +- (UIView *)keyboardManagerPhotoBoardView:(QKeyboardManager *)keyboardManager{ + QinputPhotoView *emotionView = [[QinputPhotoView alloc] init]; + self.photoView = emotionView; + emotionView.photoList = self.phototArray; + emotionView.delegate = self; + emotionView.backgroundColor = [UIColor colorWithRed:(246)/255.0f green:(246)/255.0f blue:(246)/255.0f alpha:1]; + return emotionView; +} + +//@return 点表情按钮弹出的表情面板View的高度 +- (CGFloat)keyboardManagerEmotionBoardHeight:(QKeyboardManager *)keyboardManager { + return 294; +} + +//@return 点加号按钮弹出的拓展面板View的高度 +- (CGFloat)keyboardManagerExtendBoardHeight:(QKeyboardManager *)keyboardManager { + return 174; +} + +- (CGFloat)keyboardManagerPhotoBoardHeight:(QKeyboardManager *)keyboardManager { + return 184 + kSafeAreaBottomHeight; +} + +//点击表情按钮,切换到表情面板 +- (void)inputBarView:(QInputBarView *)inputBarView onEmotionButtonClick:(UIButton *)emotionSwitchButton { + if (emotionSwitchButton.isSelected) { + [_keyboardManager switchToEmotionBoardKeyboard]; + } else { + _inputBarView.inputTextView.text = @""; + [_inputBarView textViewBecomeFirstResponder]; + } +} + +- (void)inputBarView:(QInputBarView *)inputBarView onVoiceSwitchButtonClick:(UIButton *)voiceSwitchButton { + if (!voiceSwitchButton.isSelected) { + _inputBarView.inputTextView.text = @""; + [_inputBarView textViewBecomeFirstResponder]; + } else { + [_keyboardManager hideAllBoardView]; + } +} + +- (void)inputBarView:(QInputBarView *)inputBarView onGiftButtonClick:(UIButton *)emotionSwitchButton { + [_keyboardManager hideAllBoardView]; + +} + +- (void)inputBarView:(QInputBarView *)inputBarView onCameraButtonClick:(UIButton *)emotionSwitchButton { + [_keyboardManager hideAllBoardView]; + @kWeakify(self); + [YYUtility checkCameraAvailable:^{ + @kStrongify(self); + UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; + imagePicker.delegate = self; + imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; + imagePicker.allowsEditing = YES; + [self presentViewController:imagePicker animated:YES completion:NULL]; + } denied:^{ + @kStrongify(self); + [self showNotPhoto:YMLocalizedString(@"SessionViewController19") content:YMLocalizedString(@"SessionViewController10")]; + } restriction:^{ + @kStrongify(self); + [self showNotPhoto:YMLocalizedString(@"SessionViewController19") content:YMLocalizedString(@"SessionViewController12")]; + }]; + +} + +- (void)inputBarView:(QInputBarView *)inputBarView onPhototButtonClick:(UIButton *)emotionSwitchButton { + if (emotionSwitchButton.isSelected) { + @kWeakify(self); + [YYUtility checkAssetsLibrayAvailable:^{ + @kStrongify(self); + [TZImagePickerConfig sharedInstance].allowPickingImage = YES; + dispatch_async(dispatch_get_global_queue(0, 0), ^{ + [[TZImageManager manager] getCameraRollAlbumWithFetchAssets:NO completion:^(TZAlbumModel *model) { + [[TZImageManager manager] getAssetsFromFetchResult:model.result completion:^(NSArray *models) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSMutableArray * array = [NSMutableArray array]; + if (models.count > 40) { + for (int i = 0; i < 40; i++) { + TZAssetModel * assets = [models objectAtIndex:i]; + QPhotoImageModel * infor = [[QPhotoImageModel alloc] init]; + infor.isOrigin = NO; + infor.assetInfo = assets; + [array addObject:infor]; + } + } else { + for (int i = 0; i < models.count; i++) { + TZAssetModel * assets = [models objectAtIndex:i]; + QPhotoImageModel * infor = [[QPhotoImageModel alloc] init]; + infor.isOrigin = NO; + infor.assetInfo = assets; + [array addObject:infor]; + } + } + self.phototArray = array; + if (self.phototArray.count > 0) { + self.photoView.photoList = self.phototArray; + [self.keyboardManager switchToPhotoBoardKeyboard]; + } else { + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; + imagePickerVc.modalPresentationStyle = UIModalPresentationOverFullScreen; + imagePickerVc.allowPickingVideo = NO; + imagePickerVc.allowTakeVideo = NO; + imagePickerVc.naviBgColor = [DJDKMIMOMColor appCellBackgroundColor]; + imagePickerVc.naviTitleColor = [DJDKMIMOMColor mainTextColor]; + imagePickerVc.barItemTextColor = [DJDKMIMOMColor mainTextColor]; + [self presentViewController:imagePickerVc animated:YES completion:nil]; + } + }); + }]; + }]; + }); + } denied:^{ + @kStrongify(self); + [self showNotPhoto:YMLocalizedString(@"SessionViewController20") content:YMLocalizedString(@"SessionViewController14")]; + } restriction:^{ + @kStrongify(self); + [self showNotPhoto:YMLocalizedString(@"SessionViewController20") content:YMLocalizedString(@"SessionViewController16")]; + }]; + } else { + [_keyboardManager hideAllBoardView]; + _inputBarView.inputTextView.text = @""; + [_inputBarView textViewResignFirstResponder]; + } + +} + +- (void)showNotPhoto:(NSString *)title content:(NSString *)content { + TTAlertConfig *config = [[TTAlertConfig alloc] init]; + config.title = title; + config.message = content; + + [TTPopup alertWithConfig:config confirmHandler:^{ + NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + if ([[UIApplication sharedApplication] canOpenURL:url]) { + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) { + + }]; + } + } cancelHandler:^{ + }]; +} + +#pragma mark - InputBoardDelegate +- (void)keyboardManager:(QKeyboardManager *)keyboardManager onWholeInputViewHeightDidChange:(CGFloat)wholeInputViewHeight reason:(WholeInputViewHeightDidChangeReason)reason { + [UIView animateWithDuration:0.2 animations:^{ + [self.sessionTableView nim_scrollToBottom:NO]; + [self.sessionTableView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.leading.trailing.mas_equalTo(self.view); + make.top.mas_equalTo(self.sessionNavView.mas_bottom); + make.bottom.mas_equalTo(self.view).offset(-wholeInputViewHeight - kSafeAreaBottomHeight); + }]; + }]; +} + +#pragma mark - QEmotionBoardViewDelegate +/** + * 选中表情时的回调 + * @param index 被选中的表情在`emotions`里的索引 + * @param emotion 被选中的表情对应的`QMUIEmotion`对象 + */ +- (void)emotionView:(QEmotionBoardView *)emotionView didSelectEmotion:(QEmotion *)emotion atIndex:(NSInteger)index { + //把😊插入到输入栏 + [_inputBarView insertEmotion:emotion.displayName]; +} + +// 删除按钮的点击事件回调 +- (void)emotionViewDidSelectDeleteButton:(QEmotionBoardView *)emotionView { + if (![_inputBarView deleteEmotion]){ + //根据当前的光标,这次点击删除按钮并没有删除表情,那么就删除文字 + [_inputBarView.inputTextView deleteBackward]; + } +} + +// 发送按钮的点击事件回调 +- (void)emotionViewDidSelectSendButton:(QEmotionBoardView *)emotionView { + [self sendTextMessage:[_inputBarView textViewInputNormalText]]; + _inputBarView.inputTextView.text = @""; + [_keyboardManager hideAllBoardView]; + +} + +/** + * 点击了系统键盘的发送按钮 + * @param inputNormalText :"害~你好啊[微笑]" + */ +- (void)inputBarView:(QInputBarView *)inputBarView onKeyboardSendClick:(NSString *)inputNormalText { + [self sendTextMessage:inputNormalText]; + _inputBarView.inputTextView.text = @""; + [_keyboardManager hideAllBoardView]; +} + +#pragma mark - QinputPhotoViewDelegate +- (void)qinputPhotoView:(QinputPhotoView *)view didClickSend:(NSArray *)photoList { + for (int i = 0; i < photoList.count; i++) { + QPhotoImageModel * imageInfo = [photoList safeObjectAtIndex1:i]; + UIImage * image; + if (view.isOrigin) { + image = imageInfo.originImage; + } else { + image = imageInfo.compressImage; + } + if (image == nil){ + continue; + } + // 发送消息 + NIMMessage * message = [NIMMessageMaker msgWithImage:image]; + + + [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; + [view resetChoosePhotos]; + + + + + } +} + +- (void)qinputPhotoView:(QinputPhotoView *)view didClickPhoto:(UIButton *)sender { + TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self]; + imagePickerVc.modalPresentationStyle = UIModalPresentationOverFullScreen; + imagePickerVc.allowPickingVideo = NO; + imagePickerVc.allowTakeVideo = NO; + imagePickerVc.naviBgColor = [DJDKMIMOMColor appCellBackgroundColor]; + imagePickerVc.naviTitleColor = [DJDKMIMOMColor mainTextColor]; + imagePickerVc.barItemTextColor = [DJDKMIMOMColor mainTextColor]; + [self presentViewController:imagePickerVc animated:YES completion:nil]; +} + +#pragma mark - UIImagePickerControllerDelegate +- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info +{ + UIImage *selectedPhoto = [info objectForKey:UIImagePickerControllerEditedImage]; + if (selectedPhoto) { + if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { + UIImageWriteToSavedPhotosAlbum(selectedPhoto, nil, nil, nil); + } + NIMMessage * message = [NIMMessageMaker msgWithImage:selectedPhoto]; + + // 发送消息 + [[NIMSDK sharedSDK].chatManager sendMessage:message toSession:self.session error:nil]; + + + } + [picker dismissViewControllerAnimated:YES completion:^{}]; +} + +- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ + [picker dismissViewControllerAnimated:YES completion:^{ + }]; +} + + +#pragma mark - Getters And Setters +- (NSArray *)messages { + if (!_messages) { + _messages = [[NSMutableArray alloc] init]; + } + return _messages; +} + +#pragma mark - Event Response +- (void)closeKeyBoard { + [self.view endEditing:YES]; + [self.inputBarView textViewResignFirstResponder]; +} + +- (UITableView *)sessionTableView { + if (!_sessionTableView) { + _sessionTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain]; + _sessionTableView.delegate = self; + _sessionTableView.dataSource = self; + _sessionTableView.backgroundColor = UIColor.clearColor; + _sessionTableView.separatorStyle = UITableViewCellSeparatorStyleNone; + _sessionTableView.showsVerticalScrollIndicator = NO; + if (@available(iOS 11.0, *)) { + _sessionTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; + } + } + return _sessionTableView; +} + +- (SessionNavView *)sessionNavView { + if (!_sessionNavView) { + _sessionNavView = [[SessionNavView alloc] init]; + _sessionNavView.delegate = self; + _sessionNavView.isPublicChatHall = YES; + } + return _sessionNavView; +} + + +@end diff --git a/YuMi/Modules/YMMessage/View/Session/SessionViewController.m b/YuMi/Modules/YMMessage/View/Session/SessionViewController.m index 229ce113..39d8c5f4 100644 --- a/YuMi/Modules/YMMessage/View/Session/SessionViewController.m +++ b/YuMi/Modules/YMMessage/View/Session/SessionViewController.m @@ -675,9 +675,12 @@ #pragma mark - NIMChatManagerDelegate - (void)onRecvMessages:(NSArray *)messages { + if(!messages.count){ + return; + } NIMMessage *message = messages.firstObject; NIMSession *session = message.session; - if (![session isEqual:self.session] || !messages.count) { + if (![session isEqual:self.session] ) { return; } for (NIMMessage *message in messages) { diff --git a/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.h b/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.h new file mode 100644 index 00000000..9bba30cf --- /dev/null +++ b/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.h @@ -0,0 +1,36 @@ +// +// MSSessionScrollingView.h +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import +#import "MSSessionScrollingProtocol.h" +NS_ASSUME_NONNULL_BEGIN + +@class MSSessionScrollingView; + +@protocol MSSessionScrollingViewDelegate +@property (nonatomic,readonly)NSTimeInterval curTime; +- (UIView *)MSSessionScrollingView:(MSSessionScrollingView *)view scrollingWithModel:(id)model; +- (void)MSSessionScrollingView:(MSSessionScrollingView *)view didClickView:(UIView *)scrollingView atPoint:(CGPoint)point; + +@end + + +@interface MSSessionScrollingView : UIView +@property(nonatomic,weak) iddelegate; +@property (nonatomic,strong) NSMutableArray > *modelList; + +@property (nonatomic, assign)BOOL isPause; +@property (nonatomic, assign)BOOL isChange; + +/// 暂停 +- (void)pauseAnimation; +/// 继续 +- (void)resumeAnimation; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.m b/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.m new file mode 100644 index 00000000..5b59129d --- /dev/null +++ b/YuMi/Modules/YMMessage/View/Session/View/MSSessionScrollingView.m @@ -0,0 +1,220 @@ +// +// MSSessionScrollingView.m +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "MSSessionScrollingView.h" +#import "CALayer+Animation.h" + +static const CGFloat ktimerSec = 0.1; +static const CGFloat kDandaoCount = 5; + +@interface MSSessionScrollingView() +@property (nonatomic,weak)NSTimer *timer; +@property (nonatomic,strong)NSMutableArray *waitTimeList; +@property (nonatomic,strong)NSMutableArray *leftTimeList; +@property (nonatomic,strong)NSMutableArray *scrollingList; + +@end +@implementation MSSessionScrollingView + +- (instancetype)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(ms_ClickView:)]; + [self addGestureRecognizer:tap]; + [self installUI]; + [self installConstraints]; + } + return self; +} +-(void)installUI{ + +} +-(void)installConstraints{ + +} + + +- (void)ms_ClickView:(UITapGestureRecognizer *)tap { + CGPoint point = [tap locationInView:tap.view]; + for (UIView *danmuView in self.scrollingList) { + CGRect frame = danmuView.layer.presentationLayer.frame; + BOOL isContain = CGRectContainsPoint(frame, point); + if (isContain) { + if ([self.delegate respondsToSelector:@selector(MSSessionScrollingView:didClickView:atPoint:)]) { + [self.delegate MSSessionScrollingView:self didClickView:danmuView atPoint:point]; + } + break; + } + } +} + +#pragma mark -- 生命周期方法 +- (void)didMoveToSuperview { + [super didMoveToSuperview]; + [self timer]; + self.layer.masksToBounds = YES; +} +-(void)dealloc { + [self.timer invalidate]; + self.timer = nil; +} +#pragma mark -- 接口 +/// 暂停 +- (void)pauseAnimation { + _isPause = YES; + [[self.scrollingList valueForKeyPath:@"layer"] makeObjectsPerformSelector:@selector(ms_pauseAnimate)]; + [self.timer invalidate]; + self.timer = nil; +} +/// 继续 +- (void)resumeAnimation{ + _isPause = NO; + [[self.scrollingList valueForKeyPath:@"layer"] makeObjectsPerformSelector:@selector(ms_resumeAnimate)]; + + [self timer]; +} + +#pragma mark -- 私有方法 +- (void)checkAndBiu { + if (_isPause) { + return; + } + // 实时更新弹道记录的时间信息 + for (int i = 0; i < kDandaoCount; i++) { + double waitValue = [self.waitTimeList[i] doubleValue] - ktimerSec; + if (waitValue <= 0.0) { + waitValue = 0.0; + } + self.waitTimeList[i] = @(waitValue); + + double leftValue = [self.leftTimeList[i] doubleValue] - ktimerSec; + if (leftValue <= 0.0) { + leftValue = 0.0; + } + self.leftTimeList[i] = @(leftValue); + } + + + [self.modelList sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { + if (obj1.beginTime < obj2.beginTime) { + return NSOrderedAscending; + } + return NSOrderedDescending; //降序 + }]; + // 检测模型数组里面所有的模型,是否可以发射 如果可以,直接发射 + NSMutableArray *deleteModelArr = [NSMutableArray array]; + for (id model in self.modelList) { + //1.检测开始时间是否有到达 + NSTimeInterval beginTime = model.beginTime; + NSTimeInterval curTime = self.delegate.curTime; + if (beginTime > curTime) { + break; + } + //2.检测碰撞 + BOOL result = [self checkBoomAndBiuWith:model]; + if (result) { + [deleteModelArr addObject:model]; + } + } + [self.modelList removeObjectsInArray:deleteModelArr]; +} +#pragma mark -- 检测碰撞 +- (BOOL)checkBoomAndBiuWith:(id)model { + + CGFloat danmakuH = self.frame.size.height / kDandaoCount + 10; + // 遍历所有的弹道,在每个弹道里面,进行检测(检测开始碰撞 检测结束碰撞) + for (int i = 0 ; i < kDandaoCount; i++) { + //1.获取该弹道的绝对等待时间 + NSTimeInterval waitTime = [self.waitTimeList[i] doubleValue]; + if (waitTime > 0.0) { + continue; + } + //2.绝对等待时间没有 暂时可以发射 需要判断 是否与前一个弹幕视图产生碰撞 + UIView * danmakuView = [self.delegate MSSessionScrollingView:self scrollingWithModel:model]; + NSTimeInterval leftTime = [self.leftTimeList[i] doubleValue]; + // 速度 = (弹幕视图的宽度 + 弹幕背景的宽度)/endTime + double speed = ( danmakuView.frame.size.width + self.frame.size.width) / model.endTime; + double distance = leftTime * speed; + if (distance > self.frame.size.width) { + continue; + } + if(danmakuH * (i+1) + 5> self.frame.size.height){ + continue; + } + + [self.scrollingList addObject:danmakuView]; + + //重置数据 + // 距离/秒 = 速度v + self.waitTimeList[i] = @(danmakuView.frame.size.width / speed); + self.leftTimeList[i] = @(model.endTime); + + //3.弹幕肯定可以发射 + //3.1 先把弹幕视图,加到弹幕背景里面 + CGRect frame = danmakuView.frame; + frame.origin = CGPointMake(self.frame.size.width, danmakuH * i); + danmakuView.frame = frame; + [self addSubview:danmakuView]; + + [UIView animateWithDuration:model.endTime delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ + CGRect frame = danmakuView.frame; + frame.origin.x = - danmakuView.frame.size.width; + danmakuView.frame = frame; + } completion:^(BOOL finished) { + [danmakuView removeFromSuperview]; + [self.scrollingList removeObject:danmakuView]; + }]; + + return YES; + } + + return NO; +} +#pragma mark --set get +- (NSMutableArray *)modelList { + if (!_modelList) { + _modelList = [NSMutableArray array]; + } + return _modelList; +} + +-(NSTimer *)timer { + if (!_timer) { + NSTimer *timer = [NSTimer timerWithTimeInterval:ktimerSec repeats:YES block:^(NSTimer * _Nonnull timer) { + [self checkAndBiu]; + }]; + [[NSRunLoop currentRunLoop]addTimer:timer forMode:NSRunLoopCommonModes]; + _timer = timer; + } + return _timer; +} +- (NSMutableArray *)waitTimeList { + if (!_waitTimeList) { + _waitTimeList = [NSMutableArray arrayWithCapacity:kDandaoCount]; + for (int i = 0; i < kDandaoCount; i ++) { + _waitTimeList[i] = @0.0; + } + } + return _waitTimeList; +} + +- (NSMutableArray *)leftTimeList { + if (!_leftTimeList) { + _leftTimeList = [NSMutableArray arrayWithCapacity:kDandaoCount]; + for (int i = 0; i < kDandaoCount; i ++) { + _leftTimeList[i] = @0.0; + } + } + return _leftTimeList; +} + +- (NSMutableArray *)scrollingList { + if (!_scrollingList) { + _scrollingList = [NSMutableArray array]; + } + return _scrollingList; +} +@end diff --git a/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.h b/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.h index f1eb3d83..ffba19b1 100644 --- a/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.h +++ b/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.h @@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN @class SessionNavView, UserInfoModel; @protocol SessionNavViewDelegate + +@optional ///点击了举报 - (void)sessionNavView:(SessionNavView *)view didClickReport:(UIButton *)sender; ///点击了关注 @@ -28,6 +30,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic,strong) UserInfoModel *userInfo; ///是否已经喜欢了 @property (nonatomic,assign) BOOL isLike; + +@property(nonatomic,assign) BOOL isPublicChatHall; ///代理 @property (nonatomic,weak) id delegate; ///是否在房间中 diff --git a/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.m b/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.m index ed08fb4b..f1b5b276 100644 --- a/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.m +++ b/YuMi/Modules/YMMessage/View/Session/View/SessionNavView.m @@ -51,7 +51,12 @@ } return self; } - +- (void)setIsPublicChatHall:(BOOL)isPublicChatHall{ + _isPublicChatHall = isPublicChatHall; + self.liveView.hidden = _isPublicChatHall; + self.reportButton.hidden = _isPublicChatHall; + self.likeButton.hidden = _isPublicChatHall; +} #pragma mark - Private Method - (void)initSubViews { self.backgroundColor = [DJDKMIMOMColor appCellBackgroundColor]; diff --git a/YuMi/Modules/YMRoom/View/AnimationView/XPRoomAnimationView.m b/YuMi/Modules/YMRoom/View/AnimationView/XPRoomAnimationView.m index 6cf4db53..fc8084a1 100644 --- a/YuMi/Modules/YMRoom/View/AnimationView/XPRoomAnimationView.m +++ b/YuMi/Modules/YMRoom/View/AnimationView/XPRoomAnimationView.m @@ -441,7 +441,7 @@ CGFloat width = image.size.width <= 0 ? kGetScaleWidth(60) : image.size.width; CGFloat height = image.size.height ; CGFloat getHeigth = KScreenWidth * height / width; - bannerView = [[PIUniversalBannerView alloc]initWithFrame:CGRectMake(0, top, KScreenWidth, getHeigth) ]; + bannerView = [[PIUniversalBannerView alloc]initWithFrame:CGRectMake(KScreenWidth, top, KScreenWidth, getHeigth) ]; [self showGeneralFloatingScreenView:bannerView model:model]; }fail:^(NSError * _Nonnull error) { diff --git a/YuMi/Modules/YMRoom/View/BaseUIContainerView/XPRoomFunctionContainerView.m b/YuMi/Modules/YMRoom/View/BaseUIContainerView/XPRoomFunctionContainerView.m index 4558f1bd..2aee36c6 100644 --- a/YuMi/Modules/YMRoom/View/BaseUIContainerView/XPRoomFunctionContainerView.m +++ b/YuMi/Modules/YMRoom/View/BaseUIContainerView/XPRoomFunctionContainerView.m @@ -273,33 +273,31 @@ }]; } - (void)showLittleGameMiniView:(RoomType)type micCount:(NSInteger)micCount { -// if([ClientConfig shareConfig].canOpen){ -// if (type == RoomType_MiniGame) { -// if (!self.littleGameMiniView.superview) { -// [self addSubview:self.littleGameMiniView]; -// [self.littleGameMiniView mas_makeConstraints:^(MASConstraintMaker *make) { -// make.trailing.mas_equalTo(0); -// make.top.mas_equalTo(kNavigationHeight); -// make.height.mas_equalTo(23); -// }]; -// } -// self.littleGameMiniView.micCount = micCount; -// if (micCount > 6) { -// [self.littleGameMiniView removeFromSuperview]; -// } -// } else { -// if (self.littleGameMiniView.superview) { -// [self.littleGameMiniView removeFromSuperview]; -// } -// } -// }else{ -// if (self.littleGameMiniView.superview) { -// [self.littleGameMiniView removeFromSuperview]; -// } -// } - if (self.littleGameMiniView.superview) { - [self.littleGameMiniView removeFromSuperview]; + if([ClientConfig shareConfig].canOpen){ + if (type == RoomType_MiniGame) { + if (!self.littleGameMiniView.superview) { + [self addSubview:self.littleGameMiniView]; + [self.littleGameMiniView mas_makeConstraints:^(MASConstraintMaker *make) { + make.trailing.mas_equalTo(0); + make.top.mas_equalTo(kNavigationHeight); + make.height.mas_equalTo(23); + }]; + } + self.littleGameMiniView.micCount = micCount; + if (micCount > 6) { + [self.littleGameMiniView removeFromSuperview]; + } + } else { + if (self.littleGameMiniView.superview) { + [self.littleGameMiniView removeFromSuperview]; + } + } + }else{ + if (self.littleGameMiniView.superview) { + [self.littleGameMiniView removeFromSuperview]; + } } + } - (void)configLittleGameState { diff --git a/YuMi/Modules/YMRoom/View/MenuContainerView/MSRoomMenuGameVC.m b/YuMi/Modules/YMRoom/View/MenuContainerView/MSRoomMenuGameVC.m index bab369f4..4bf2fdc3 100644 --- a/YuMi/Modules/YMRoom/View/MenuContainerView/MSRoomMenuGameVC.m +++ b/YuMi/Modules/YMRoom/View/MenuContainerView/MSRoomMenuGameVC.m @@ -14,6 +14,7 @@ #import "XPSailingViewController.h" #import "XPRoomViewController.h" #import "MSRoomGameWebVC.h" +#import "XPRoomAnimationView.h" @interface MSRoomMenuGameVC () @property(nonatomic,strong) MSRoomMenuGameView *gameView; ///host 代理 @@ -117,7 +118,15 @@ vc.view.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight); XPRoomViewController *roomVC = (XPRoomViewController *)self.hostDelegate; [roomVC addChildViewController:vc]; + XPRoomAnimationView *animationView; + for (id obj in self.hostDelegate.getSuperView.subviews) { + if ([obj isKindOfClass:[XPRoomAnimationView class]]){ + animationView = obj; + break; + } + } [self.hostDelegate.getSuperView addSubview:vc.view]; + [self.hostDelegate.getSuperView bringSubviewToFront:animationView]; } } diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/Tool/XPRoomMessageParser.m b/YuMi/Modules/YMRoom/View/MessageContainerView/Tool/XPRoomMessageParser.m index 25d0aa2d..d6bbc588 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/Tool/XPRoomMessageParser.m +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/Tool/XPRoomMessageParser.m @@ -1010,19 +1010,20 @@ #pragma mark - 踢出房间/拉黑/下麦 - (XPMessageInfoModel *)createKickUserAttribute:(AttachmentModel *)attachment info:(XPKickUserModel *)info messageInfo:(XPMessageInfoModel *)messageInfo{ - NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] init]; - [attribute appendAttributedString:[self createNickAtrribute:info.targetNick uid:info.targetUid]]; - [attribute appendAttributedString:[self createTextAttribute:YMLocalizedString(@"XPRoomMessageParser92") color:[DJDKMIMOMColor messageDefaultTextColor] font:kRoomMessageDefalutFont]]; - [attribute appendAttributedString:[self createNickAtrribute:info.handleNick uid:info.handleUid]]; - NSString * content= @""; - if (attachment.second == Custom_Message_Sub_Kick_BeKicked || attachment.second == Custom_Message_Sub_Hall_Super_Admin_Kick_Manager_Out_Room) { - content = YMLocalizedString(@"XPRoomMessageParser93"); - } else if(attachment.second == Custom_Message_Sub_Kick_BlackList) { - content = YMLocalizedString(@"XPRoomMessageParser94"); - } else if(attachment.second == Custom_Message_Sub_Queue_Kick) { - content = YMLocalizedString(@"XPRoomMessageParser95"); - } - [attribute appendAttributedString:[self createTextAttribute:content color:[DJDKMIMOMColor messageDefaultTextColor] font:kRoomMessageDefalutFont]]; + + NSString * content= @""; + if (attachment.second == Custom_Message_Sub_Kick_BeKicked || attachment.second == Custom_Message_Sub_Hall_Super_Admin_Kick_Manager_Out_Room) { + content = [NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageParser93"),info.targetNick,info.handleNick]; + } else if(attachment.second == Custom_Message_Sub_Kick_BlackList) { + content = [NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageParser94"),info.targetNick,info.handleNick]; + } else if(attachment.second == Custom_Message_Sub_Queue_Kick) { + content = [NSString stringWithFormat:YMLocalizedString(@"XPRoomMessageParser95"),info.targetNick,info.handleNick]; + } + NSMutableAttributedString * attribute = [[NSMutableAttributedString alloc] initWithString:content attributes:@{NSForegroundColorAttributeName:[DJDKMIMOMColor messageDefaultTextColor],NSFontAttributeName:[UIFont systemFontOfSize:kRoomMessageDefalutFont]}]; + [attribute addAttributes:@{NSForegroundColorAttributeName:[DJDKMIMOMColor messageNickColor],NSFontAttributeName:[UIFont systemFontOfSize:kRoomMessageDefalutFont]} range:[content rangeOfString:info.targetNick]]; + [attribute addAttributes:@{NSForegroundColorAttributeName:[DJDKMIMOMColor messageNickColor],NSFontAttributeName:[UIFont systemFontOfSize:kRoomMessageDefalutFont]} range:[content rangeOfString:info.handleNick]]; + [self attributeAddHihtLight:attribute range:[content rangeOfString:info.targetNick] uid:info.targetUid]; + [self attributeAddHihtLight:attribute range:[content rangeOfString:info.handleNick] uid:info.handleUid]; messageInfo.content = attribute; return messageInfo; } @@ -1239,7 +1240,14 @@ [self attributeAddHihtLight:attribute uid:uid]; return attribute; } - +- (void)attributeAddHihtLight:(NSMutableAttributedString *)attribute range:(NSRange)range uid:(NSInteger)uid { + @kWeakify(self); + [attribute yy_setTextHighlightRange:range color:nil backgroundColor:nil tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) { + @kStrongify(self); + if (uid <= 0) {return;} + [self showUserCard:uid]; + }]; +} - (void)attributeAddHihtLight:(NSMutableAttributedString *)attribute uid:(NSInteger)uid { @kWeakify(self); [attribute yy_setTextHighlightRange:NSMakeRange(0, attribute.length) color:nil backgroundColor:nil tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) { diff --git a/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m b/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m index e246aad7..a79a9939 100644 --- a/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m +++ b/YuMi/Modules/YMRoom/View/MessageContainerView/XPRoomMessageContainerView.m @@ -513,6 +513,7 @@ NSString * const kRoomShowTopicKey = @"kRoomShowTopicKey"; @(CustomMessageType_LuckyBag): [NSSet setWithObjects: @(Custom_Message_Sub_Room_Gift_LuckBag_Server), + @(Custom_Message_Sub_Room_Gift_LuckBag_FullScree), nil], @(CustomMessageType_Gift_Compound): [NSSet setWithObjects:@(Custom_Message_Sub_Gift_Compound), diff --git a/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m b/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m index e97ab233..3c4d184a 100644 --- a/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m +++ b/YuMi/Modules/YMRoom/View/StageView/MicroView/MicroView.m @@ -418,7 +418,7 @@ if (self.roomInfo.type == RoomType_Anchor || (self.roomInfo.roomModeType == RoomModeType_Open_AcrossRoomPK_mode && self.roomInfo.roomId > 0) || (self.roomInfo.roomModeType == RoomModeType_Open_Blind && micState.position == 999)) { self.positionCharmImgView.hidden = YES; } - self.nickLabel.text = [NSString stringWithFormat:YMLocalizedString(@"MicroView0"), micState.position + 1]; + self.nickLabel.text = YMLocalizedString(@"MicroView0"); } -(UserInfoModel *)getUser{ return self.userInfo; diff --git a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m index 5750d0c9..cea80ea2 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m +++ b/YuMi/Modules/YMRoom/View/UserCard/Presenter/XPUserCardPresenter.m @@ -63,7 +63,7 @@ [Api attentionStatusCompletion:[self createHttpCompletion:^(BaseModel * _Nonnull data) { BOOL isLike = ((NSNumber *)data.data).boolValue; self.attentionItem.isSelect = isLike; - [[self getView] onGetFunctionArraySccess:self.functionArray]; + [[self getView] onGetFollowDataSccess]; }errorToast:NO] uid:uid isLikeUid:targetUid]; } diff --git a/YuMi/Modules/YMRoom/View/UserCard/Protocol/XPUserCardProtocol.h b/YuMi/Modules/YMRoom/View/UserCard/Protocol/XPUserCardProtocol.h index 730ddc4d..13ed20d5 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/Protocol/XPUserCardProtocol.h +++ b/YuMi/Modules/YMRoom/View/UserCard/Protocol/XPUserCardProtocol.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN ///获取用户卡片中 functioin的数据源 - (void)onGetFunctionArraySccess:(NSArray *)array; +- (void)onGetFollowDataSccess; ///获取用户卡片中 操作麦的 functioin的数据源 - (void)onGetMicroFunctionArraySuccess:(NSArray *)array; ///关注成功 diff --git a/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m b/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m index 770972f2..b8e2eff0 100644 --- a/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m +++ b/YuMi/Modules/YMRoom/View/UserCard/View/XPUserCardViewController.m @@ -599,7 +599,9 @@ [self.presenter getMicroFunctionItemsByUserInfo:self.cardInfo]; } - +-(void)onGetFollowDataSccess{ + [self.collectionView reloadData]; +} - (void)onGetMicroFunctionArraySuccess:(NSArray *)array { if (array.count <= 0) { if (self.datasource.count > 0){ diff --git a/YuMi/Modules/YMRoom/View/XPRoomViewController.m b/YuMi/Modules/YMRoom/View/XPRoomViewController.m index 7ebb7dc6..a4935d57 100644 --- a/YuMi/Modules/YMRoom/View/XPRoomViewController.m +++ b/YuMi/Modules/YMRoom/View/XPRoomViewController.m @@ -1692,7 +1692,10 @@ NSString * const kHadQuitOtherRoomKey = @"kHadQuitOtherRoomKey";//是否退出 isHave = YES; }else if (attachment.first == CustomMessageType_Tarot && (attachment.second == Custom_Message_Sub_Tarot_Advanced || attachment.second == Custom_Message_Sub_Tarot_Intermediate)){ isHave = YES; - }if (attachment.first == CustomMessageType_RedPacket && attachment.second == Custom_Message_Sub_AllDiamandRedPacket) { + }else if(attachment.first == CustomMessageType_LuckyBag && attachment.second == Custom_Message_Sub_Room_Gift_LuckBag_FullScree){ + isHave = YES; + } + if (attachment.first == CustomMessageType_RedPacket && attachment.second == Custom_Message_Sub_AllDiamandRedPacket) { if(self.isShowRedPacket == YES)return; XPRedPacketModel *data = [XPRedPacketModel modelWithDictionary:attachment.data]; data.validityType = 0; diff --git a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m index bc79b70f..901052b7 100644 --- a/YuMi/Modules/YMWeb/MSRoomGameWebVC.m +++ b/YuMi/Modules/YMWeb/MSRoomGameWebVC.m @@ -52,6 +52,7 @@ NSString * const kMSGameLoaded = @"gameLoaded"; @property (nonatomic, strong) WKUserContentController *ms_userContentController; @property (nonatomic,weak) id hostDelegate; @property(nonatomic,strong) ActivityInfoModel *gameModel; +@property(nonatomic,strong) UIButton *backBtn; @end @implementation MSRoomGameWebVC @@ -71,9 +72,16 @@ NSString * const kMSGameLoaded = @"gameLoaded"; - (void)viewDidLoad { [super viewDidLoad]; [self installUI]; + self.backBtn = [UIButton new]; + [self.view addSubview:self.backBtn]; + [self.backBtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.view); + }]; + [self.backBtn addTarget:self action:@selector(backBtnAction) forControlEvents:UIControlEventTouchUpInside]; } -(void)installUI{ + self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4]; MSWeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[MSWeakWebViewScriptMessageDelegate alloc] initWithDelegate:self]; _ms_userContentController = [[WKUserContentController alloc] init]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGetConfig]; @@ -103,6 +111,7 @@ NSString * const kMSGameLoaded = @"gameLoaded"; [self.webview.scrollView setBackgroundColor:[UIColor clearColor]]; [self.webview setBackgroundColor:[UIColor clearColor]]; [self.webview setUIDelegate:self]; + self.webview.navigationDelegate = self; //设置⽹⻚透明 [self.webview setOpaque:NO]; //设置⽹⻚全屏 @@ -199,7 +208,6 @@ NSString * const kMSGameLoaded = @"gameLoaded"; NSString *code = gameModel.code ?: @""; NSString *roomId = [NSString stringWithFormat:@"%ld",roomInfo.uid]; NSString *gameMode = gameModel.gameMode ?: @""; - NSString *language = gameModel.language ?: @""; NSDictionary *gameConfig = gameModel.gameConfig ?: @{}; int gsp = gameModel.gsp; // 数据只是参考值,需要根据⾃⼰APP进⾏赋值 @@ -240,7 +248,19 @@ NSString * const kMSGameLoaded = @"gameLoaded"; [self.view removeFromSuperview]; //2 [self removeFromParentViewController]; //3 } - +-(void)backBtnAction{ + TTAlertConfig *config = [[TTAlertConfig alloc]init]; + config.message = YMLocalizedString(@"MSRoomGameWebVC0"); + config.actionStyle = TTAlertActionBothStyle; + [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ + [self willMoveToParentViewController:nil]; //1 + [self.view removeFromSuperview]; //2 + [self removeFromParentViewController]; //3 + } cancelHandler:^{ + + }]; + +} // 提⽰余额不⾜ - (void) gameRecharge:(NSDictionary*)args { @@ -257,14 +277,22 @@ NSString * const kMSGameLoaded = @"gameLoaded"; }]; } - // 游戏加载完毕 - (void) gameLoaded:(NSDictionary*)args { - NSLog(@"BSGAME %s","游戏调⽤gameLoaded"); // 游戏加载完毕 TODO 客⼾端 + [self.backBtn removeFromSuperview]; } +//加载完成 +- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { + //加载完成后隐藏progressView +} +//加载失败 +- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error { + //加载失败同样需要隐藏progressView + +} @end diff --git a/YuMi/Structure/MVP/Model/PIBaseModel.m b/YuMi/Structure/MVP/Model/PIBaseModel.m index cc7d37b5..989c4bbf 100644 --- a/YuMi/Structure/MVP/Model/PIBaseModel.m +++ b/YuMi/Structure/MVP/Model/PIBaseModel.m @@ -8,13 +8,29 @@ #import "PIBaseModel.h" @implementation PIBaseModel -- (NSString *)description{ - - return [self toJSONString]; +- (NSString *)debugDescription { + //判断是否时NSArray 或者NSDictionary NSNumber 如果是的话直接返回 debugDescription + if ([self isKindOfClass:[NSArray class]] || [self isKindOfClass:[NSDictionary class]] || [self isKindOfClass:[NSString class]] || [self isKindOfClass:[NSNumber class]]) { + return [self debugDescription]; + } + //声明一个字典 + NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; + //得到当前class的所有属性 + uint count; + objc_property_t *properties = class_copyPropertyList([self class], &count); -} -- (NSString *)debugDescription{ + //循环并用KVC得到每个属性的值 + for (int i = 0; i -- %@",[self class],self,dictionary]; } @end diff --git a/YuMi/Tools/CALayer/CALayer+Animation.h b/YuMi/Tools/CALayer/CALayer+Animation.h new file mode 100644 index 00000000..4e8fbaff --- /dev/null +++ b/YuMi/Tools/CALayer/CALayer+Animation.h @@ -0,0 +1,20 @@ +// +// CALayer+Animation.h +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface CALayer (Animation) +// 暂停动画 +- (void)ms_pauseAnimate; + +// 恢复动画 +- (void)ms_resumeAnimate; +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/CALayer/CALayer+Animation.m b/YuMi/Tools/CALayer/CALayer+Animation.m new file mode 100644 index 00000000..f643e5b4 --- /dev/null +++ b/YuMi/Tools/CALayer/CALayer+Animation.m @@ -0,0 +1,29 @@ +// +// CALayer+Animation.m +// YuMi +// +// Created by duoban on 2024/5/6. +// + +#import "CALayer+Animation.h" + +@implementation CALayer (Animation) +// 暂停动画 +- (void)ms_pauseAnimate { + CFTimeInterval pausedTime = [self convertTime:CACurrentMediaTime() fromLayer:nil]; + self.speed = 0.0; + self.timeOffset = pausedTime; +} + +// 恢复动画 +- (void)ms_resumeAnimate { + + CFTimeInterval pausedTime = [self timeOffset]; + self.speed = 1.0; + self.timeOffset = 0.0; + self.beginTime = 0.0; + CFTimeInterval timeSincePause = [self convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; + self.beginTime = timeSincePause; + +} +@end diff --git a/YuMi/ar.lproj/Localizable.strings b/YuMi/ar.lproj/Localizable.strings index 8efe543e..cb2aa201 100644 --- a/YuMi/ar.lproj/Localizable.strings +++ b/YuMi/ar.lproj/Localizable.strings @@ -1856,7 +1856,7 @@ ineHeadView12" = "الحمل"; "MicroGiftValueView0" = "9999 مليون+"; "MicroGiftValueView1" = "%lld مليون"; -"MicroView0" = "مكان %d"; +"MicroView0" = "مكان"; "MicroView1" = "موقع"; "MicroView2" = "الفريق الأحمر"; "MicroView3" = "الفريق الأزرق"; @@ -2063,10 +2063,9 @@ ineHeadView12" = "الحمل"; "XPRoomMessageParser89" = "تهانينا"; "XPRoomMessageParser90" = "الانضمام إلى نادي المعجبين"; "XPRoomMessageParser91" = "غادر نادي المعجبين"; -"XPRoomMessageParser92" = "تم"; -"XPRoomMessageParser93" = "طرد من الغرفة"; -"XPRoomMessageParser94" = "تم وضعه في الزنزانة"; -"XPRoomMessageParser95" = "الرجاء النزول من الميكروفون"; +"XPRoomMessageParser93" = "تم إزالة %@ من الغرفة بواسطة %@"; +"XPRoomMessageParser94" = "تم وضع %@ في الغرفة السوداء بواسطة %@"; +"XPRoomMessageParser95" = "تم طلب %@ للتنحي عن الميكروفون بواسطة %@"; "XPRoomMessageParser96" = "قام بمشاركة الغرفة"; "XPRoomMessageParser97" = "بدأ متابعة مالك الغرفة"; "XPRoomMessageParser98" = "تبرع"; @@ -2076,7 +2075,7 @@ ineHeadView12" = "الحمل"; "XPRoomMessageParser102" = "ل"; "XPRoomMessageParser103" = "تمنح"; "XPRoomMessageParser104" = "قيمة "; -"XPRoomMessageParser105" = "هدايا العملات الذهبية"; +"XPRoomMessageParser105" = "هدايا العملات الذهبية"; "XPRoomMessageParser106" = "أرسل هدية ل"; "XPRoomMessageParser107" = "قدم هدية ل"; "XPRoomMessageParser108" = "تم منح"; @@ -3798,5 +3797,7 @@ ineHeadView12" = "الحمل"; "MJRefreshHeaderNoneLastDateText" = "لا سجلات"; +//MSRoomGameWebVC +"MSRoomGameWebVC0"="هل أنت متأكد أنك تريد الخروج من اللعبة؟"; diff --git a/YuMi/en.lproj/Localizable.strings b/YuMi/en.lproj/Localizable.strings index e8cc1c91..815079ff 100644 --- a/YuMi/en.lproj/Localizable.strings +++ b/YuMi/en.lproj/Localizable.strings @@ -1596,7 +1596,7 @@ "MicroGiftValueView0" = "99.99M+"; "MicroGiftValueView1" = "%lldM"; -"MicroView0" = "Mic %d Position"; +"MicroView0" = "Mic"; "MicroView1" = "Slot"; "MicroView2" = "Red Team"; "MicroView3" = "Blue Team"; @@ -1801,10 +1801,9 @@ "XPRoomMessageParser89" = "Congratulations"; "XPRoomMessageParser90" = "Joined fan club"; "XPRoomMessageParser91" = "Left fan club"; -"XPRoomMessageParser92" = "was"; -"XPRoomMessageParser93" = "Kicked out of the room"; -"XPRoomMessageParser94" = "Jailed"; -"XPRoomMessageParser95" = "Please leave the mic"; +"XPRoomMessageParser93" = "%@ was removed from the room by %@"; +"XPRoomMessageParser94" = "%@ was put into the black room by %@"; +"XPRoomMessageParser95" = "%@ was asked to step down from the mic by %@"; "XPRoomMessageParser96" = "Shared the room"; "XPRoomMessageParser97" = "Followed the room owner"; "XPRoomMessageParser98" = "  Reward  "; @@ -3599,3 +3598,5 @@ "MJRefreshHeaderLastTimeText" = "Latest update:"; "MJRefreshHeaderDateTodayText" = "Today"; "MJRefreshHeaderNoneLastDateText" = "No record"; +//MSRoomGameWebVC +"MSRoomGameWebVC0"="Are you sure you want to exit the game?"; diff --git a/YuMi/zh-Hans.lproj/Localizable.strings b/YuMi/zh-Hans.lproj/Localizable.strings index 2eb36152..5ade3624 100644 --- a/YuMi/zh-Hans.lproj/Localizable.strings +++ b/YuMi/zh-Hans.lproj/Localizable.strings @@ -1415,10 +1415,9 @@ "XPRoomMessageParser89" = "恭喜"; "XPRoomMessageParser90" = "加入粉丝团"; "XPRoomMessageParser91" = "已退出粉丝团"; -"XPRoomMessageParser92" = "被"; -"XPRoomMessageParser93" = "请出房间"; -"XPRoomMessageParser94" = "关进小黑屋"; -"XPRoomMessageParser95" = "请下麦"; +"XPRoomMessageParser93" = "%@被%@请出房间"; +"XPRoomMessageParser94" = "%@被%@关进小黑屋"; +"XPRoomMessageParser95" = "%@被%@请下麦"; "XPRoomMessageParser96" = "分享了房间"; "XPRoomMessageParser97" = "关注了房主"; "XPRoomMessageParser98" = " 打赏 "; @@ -3255,3 +3254,5 @@ "MJRefreshHeaderLastTimeText" = "最后更新:"; "MJRefreshHeaderDateTodayText" = "今天"; "MJRefreshHeaderNoneLastDateText" = "无记录"; +//MSRoomGameWebVC +"MSRoomGameWebVC0"="确定退出游戏吗?"; diff --git a/YuMi/zh-Hant.lproj/Localizable.strings b/YuMi/zh-Hant.lproj/Localizable.strings index 052eb68b..de001253 100644 --- a/YuMi/zh-Hant.lproj/Localizable.strings +++ b/YuMi/zh-Hant.lproj/Localizable.strings @@ -1418,10 +1418,9 @@ "XPRoomMessageParser89" = "恭喜"; "XPRoomMessageParser90" = "加入粉絲團"; "XPRoomMessageParser91" = "已退出粉絲團"; -"XPRoomMessageParser92" = "被"; -"XPRoomMessageParser93" = "請出房間"; -"XPRoomMessageParser94" = "關進小黑屋"; -"XPRoomMessageParser95" = "請下麥"; +"XPRoomMessageParser93" = "%@被%@請出房間"; +"XPRoomMessageParser94" = "%@被%@關進小黑屋"; +"XPRoomMessageParser95" = "%@被%@請下麥"; "XPRoomMessageParser96" = "分享了房間"; "XPRoomMessageParser97" = "關註了房主"; "XPRoomMessageParser98" = " 打賞 "; @@ -3249,3 +3248,5 @@ "MJRefreshHeaderLastTimeText" = "最後更新:"; "MJRefreshHeaderDateTodayText" = "今天"; "MJRefreshHeaderNoneLastDateText" = "無記錄"; +//MSRoomGameWebVC +"MSRoomGameWebVC0"="確定退出遊戲嗎?";