// // MSRoomGameWebVC.m // YuMi // // Created by duoban on 2024/4/28. // #import "MSRoomGameWebVC.h" #import "LittleGameInfoModel.h" #import "RoomInfoModel.h" #import "XPIAPRechargeViewController.h" @interface MSWeakWebViewScriptMessageDelegate : NSObject //WKScriptMessageHandler 这个协议类专门用来处理JavaScript调用原生OC的方法 @property (nonatomic, weak) id scriptDelegate; - (instancetype)initWithDelegate:(id)scriptDelegate; @end @implementation MSWeakWebViewScriptMessageDelegate - (instancetype)initWithDelegate:(id)scriptDelegate { self = [super init]; if (self) { _scriptDelegate = scriptDelegate; } return self; } //遵循WKScriptMessageHandler协议,必须实现如下方法,然后把方法向外传递 //通过接收JS传出消息的name进行捕捉的回调方法 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { if ([self.scriptDelegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) { [self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message]; } } @end NSString * const kMSGetConfig = @"getConfig"; NSString * const kMSDestroy = @"destroy"; NSString * const kMSGameRecharge = @"gameRecharge"; NSString * const kMSGameLoaded = @"gameLoaded"; @interface MSRoomGameWebVC () @property (strong, nonatomic) WKWebView *webView; @property (strong, nonatomic) UIProgressView *progressView; @property (nonatomic, strong) WKUserContentController *ms_userContentController; @property (nonatomic,weak) id hostDelegate; @property(nonatomic,strong) ActivityInfoModel *gameModel; @property(nonatomic,strong) UIButton *backBtn; @property (nonatomic, assign) BOOL isBaiShun; @property (nonatomic, assign) BOOL isCharing; @end @implementation MSRoomGameWebVC - (instancetype)initWithDelegate:(id)delegate gameModel:(ActivityInfoModel *)gameModel { self = [super init]; if (self) { self.hostDelegate = delegate; self.gameModel = gameModel; self.isBaiShun = [gameModel.code.uppercaseString isEqualToString:@"BAISHUN"]; } return self; } - (BOOL)isHiddenNavBar { return YES; } - (void)viewDidLoad { [super viewDidLoad]; [self installUI]; [self setupBackButton]; [self showLoading]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if (!self.isBaiShun && self.isCharing) { self.isCharing = NO; [self updateCoin]; } } - (void)setupBackButton { self.backBtn = [UIButton new]; [self.view addSubview:self.backBtn]; self.backBtn.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight); [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]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSDestroy]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameRecharge]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:kMSGameLoaded]; /// LEADERCC [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"closeGame"]; [_ms_userContentController addScriptMessageHandler:weakScriptMessageDelegate name:@"pay"]; WKWebViewConfiguration *config = [WKWebViewConfiguration new]; config.allowsInlineMediaPlayback = YES; [config setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"]; //⾳视频的播放不需要⽤⼾⼿势触发, 即为⾃动播放 config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone; config.preferences = [[WKPreferences alloc]init]; WKPreferences *preferences = [WKPreferences new]; preferences.javaScriptCanOpenWindowsAutomatically = YES; config.preferences = preferences; config.preferences.javaScriptEnabled = YES; config.userContentController = _ms_userContentController; CGRect frame = CGRectZero; if (self.isBaiShun) { frame = CGRectMake(0,0, KScreenWidth, KScreenHeight); } else { if(self.gameModel.showType == ActivityShowType_Half){ frame = CGRectMake(0, KScreenHeight * 0.3, KScreenWidth, KScreenHeight * 0.7); } else { frame = CGRectMake(0,0, KScreenWidth, KScreenHeight); } } self.webView = [[WKWebView alloc] initWithFrame:frame configuration:config]; [self.webView.scrollView setBackgroundColor:[UIColor clearColor]]; [self.webView setBackgroundColor:[UIColor clearColor]]; [self.webView setUIDelegate:self]; self.webView.navigationDelegate = self; //设置⽹⻚透明 [self.webView setOpaque:NO]; //设置⽹⻚全屏 if (@available(iOS 11.0, *)) { self.webView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } [self.view addSubview:self.webView]; NSString *h5Url = self.gameModel.skipContent; NSURL *url = [self handleGameURL:h5Url]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; [self.webView loadRequest:request]; } - (NSURL *)handleGameURL:(NSString *)url { if (self.isBaiShun) { return [NSURL URLWithString:url]; } else { url = [url stringByAppendingFormat:@"&uid=%@", [AccountInfoStorage instance].getUid]; url = [url stringByAppendingFormat:@"&token=%@", self.gameModel.gameModel.code]; url = [url stringByAppendingFormat:@"&lang=%@", @"zh-CN"]; url = [url stringByAppendingFormat:@"&roomid=%ld", (long)self.hostDelegate.getRoomInfo.uid]; return [NSURL URLWithString:url]; } return nil; } - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation { [self hideHUD]; if (self.isBaiShun) { } else { self.backBtn.frame = CGRectMake(0, 0, KScreenWidth, KScreenHeight*0.3); } #if DEBUG NSString *fileName = @"vconsole.min.js"; // 你要查找的文件名 NSString *directory = [[NSBundle mainBundle] resourcePath]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtPath:directory]; NSString *filePath; for (NSString *path in enumerator) { if ([[path lastPathComponent] containsString:fileName]) { filePath = [directory stringByAppendingPathComponent:path]; break; } } if (filePath.length > 0) { NSString *vConsoleScript = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]; [self.webView evaluateJavaScript:vConsoleScript completionHandler:nil]; // 初始化 vConsole NSString *initVConsoleScript = @"var vConsole = new VConsole();"; [self.webView evaluateJavaScript:initVConsoleScript completionHandler:nil]; } #endif } - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{ if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURLCredential *card = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,card); }); } } // 调⽤JS - (void)callJs:(NSString*)method withJavaScriptValue:(nullable id)arguments { @kWeakify(self); if (arguments) { NSData *data = [NSJSONSerialization dataWithJSONObject:arguments options:(NSJSONWritingPrettyPrinted) error:nil]; NSString *jsonStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *jsMethods = [NSString stringWithFormat:@"%@(%@)", method, jsonStr]; [self.webView evaluateJavaScript:jsMethods completionHandler:^(id _Nullable resp, NSError * _Nullable error) { @kStrongify(self); NSLog(@"error = %@ , response = %@",error, resp); [self.backBtn removeFromSuperview]; }]; } else { NSString *jsMethods = [NSString stringWithFormat:@"%@({})", method]; [self.webView evaluateJavaScript:jsMethods completionHandler:^(id _Nullable resp, NSError * _Nullable error) { @kStrongify(self); NSLog(@"error = %@ , response = %@",error, resp); [self.backBtn removeFromSuperview]; }]; } } - (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString { if (jsonString == nil && jsonString.length == 0) { return nil; } NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *err; NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err]; if(err) { NSLog(@"json解析失败:%@",err); return nil; } return dic; } // 绑定协议⽅法 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message { /// BaiShun if (self.isBaiShun) { NSDictionary *dicBody = [self dictionaryWithJsonString:message.body]; if ([message.name isEqualToString:kMSGetConfig]) { [self getConfig:dicBody]; } else if ([message.name isEqualToString:kMSDestroy]) { [self destroy:dicBody]; } else if ([message.name isEqualToString:kMSGameLoaded]) { [self gameLoaded:dicBody]; } else if ([message.name isEqualToString:kMSGameRecharge]) { [self gameRecharge:dicBody]; } else { NSLog(@"未实现⽅法 : %@ --> %@", message.name, message.body); } } else { /// LeaderCC NSString* method = [NSString stringWithFormat:@"%@:", message.name]; SEL selector = NSSelectorFromString(method); if([self respondsToSelector:selector]){ [self performSelector:selector withObject:message.body]; }else{ NSLog(@"未實現方法 : %@ --> %@", message.name, message.body); } } } #pragma mark - LeaderCC Delegate // 关闭游戏 - (void)closeGame:(NSDictionary*)args { // NSLog(@"1234"); 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)pay:(NSDictionary*)args { //拉起充值商城 TODO 客⼾端 TTAlertConfig *config = [[TTAlertConfig alloc]init]; config.message = YMLocalizedString(@"XPNobleCenterViewController3"); config.actionStyle = TTAlertActionBothStyle; @kWeakify(self); [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ @kStrongify(self); XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; webVC.type = @"4"; [self.navigationController pushViewController:webVC animated:YES]; self.isCharing = YES; } cancelHandler:^{ }]; } - (void)updateCoin { // 平时游戏币更新不需要调用该方法,以防止影响游戏开奖动画。 [self.webView evaluateJavaScript:@"updateCoin()" completionHandler:^(id _Nullable result, NSError * _Nullable error) { if (error) { NSLog(@"Error calling JS function: %@", error.localizedDescription); } else { NSLog(@"JS function called successfully, result: %@", result); } }]; } #pragma mark - BaiShun Delegate // 获取信息配置 - (void) getConfig:(NSDictionary*)args { NSLog(@"BSGAME %s","游戏调⽤getConfig"); NSString* method = [args objectForKey:@"jsCallback"]; RoomInfoModel *roomInfo = self.hostDelegate.getRoomInfo; ActivityInfoItemModel *gameModel = self.gameModel.gameModel; NSString *appChannel = gameModel.appChannel ?: @""; int64_t appId = gameModel.appId; NSString *userId = [AccountInfoStorage instance].getUid; NSString *code = gameModel.code ?: @""; NSString *roomId = [NSString stringWithFormat:@"%ld",roomInfo.uid]; NSString *gameMode = gameModel.gameMode ?: @""; NSDictionary *gameConfig = gameModel.gameConfig ?: @{}; int gsp = gameModel.gsp; // 数据只是参考值,需要根据⾃⼰APP进⾏赋值 NSObject* configData = @{ @"appChannel":appChannel, @"appId":@(appId), @"userId":userId, @"code":code, @"roomId":roomId, @"gameMode":gameMode, @"language":[self getlanguage], @"gameConfig":gameConfig, @"gsp":@(gsp), }; [self callJs:method withJavaScriptValue:configData]; } -(NSString *)getlanguage{ NSString *language = [NSBundle getLanguageText]; if ([language hasPrefix:@"zh"]) { if ([language rangeOfString:@"Hans"].location != NSNotFound) { language = @"0"; // 简体中文 } else { language = @"1"; // 繁體中文 } }else if([language hasPrefix:@"ar"]){///阿拉伯语 language = @"7"; }else{///英文 language = @"2"; } return language; } // 销毁游戏 - (void) destroy:(NSDictionary*)args { NSLog(@"BSGAME %s","游戏调⽤destroy"); //关闭游戏 TODO 客⼾端 [self willMoveToParentViewController:nil]; //1 [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 { NSLog(@"BSGAME %s","游戏调⽤gameRecharge"); //拉起充值商城 TODO 客⼾端 TTAlertConfig *config = [[TTAlertConfig alloc]init]; config.message = YMLocalizedString(@"XPNobleCenterViewController3"); config.actionStyle = TTAlertActionBothStyle; @kWeakify(self); [TTPopup alertWithConfig:config showBorder:NO confirmHandler:^{ @kStrongify(self); XPIAPRechargeViewController * webVC =[[XPIAPRechargeViewController alloc] init]; webVC.type = @"4"; [self.navigationController pushViewController:webVC animated:YES]; self.isCharing = YES; } cancelHandler:^{ }]; } // 游戏加载完毕 - (void) gameLoaded:(NSDictionary*)args { // 游戏加载完毕 TODO 客⼾端 [self.backBtn removeFromSuperview]; } @end