KSCloudWebManager.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. //
  2. // KSCloudWebManager.m
  3. // KulexiuSchoolStudent
  4. //
  5. // Created by 王智 on 2024/1/19.
  6. //
  7. #import "KSCloudWebManager.h"
  8. #import <KSCloudAccompanyLibrary/CloudWebConfig.h>
  9. #import <KSCloudAccompanyLibrary/KSCloudWebViewController.h>
  10. #import <KSToolsLibrary/RecordCheckManager.h>
  11. #import "KSCloudPremissionAlertView.h"
  12. #import "KSBaseWKWebViewController.h"
  13. #import "KSAccompanyDraftViewController.h"
  14. #import <KSToolsLibrary/UIDevice+TFDevice.h>
  15. #import "AppDelegate+AppService.h"
  16. #import "AccompanyLoadingView.h"
  17. #import "KSWebLoadRefreshView.h"
  18. #import "KSLogManager.h"
  19. #import "KSDelayCheckView.h"
  20. @interface KSCloudWebManager ()<KSCloudWebViewControllerDelegate>
  21. @property (nonatomic, strong) AccompanyLoadingView *customLoading;
  22. @property (nonatomic, strong) KSWebLoadRefreshView *errorView;
  23. @property (nonatomic, strong) KSDelayCheckView *checkView;
  24. @end
  25. @implementation KSCloudWebManager
  26. + (instancetype)shareInstance {
  27. static KSCloudWebManager *manager = nil;
  28. static dispatch_once_t onceToken;
  29. dispatch_once(&onceToken, ^{
  30. manager = [[KSCloudWebManager alloc] init];
  31. });
  32. return manager;
  33. }
  34. - (void)clearMicDelay {
  35. UserDefaultRemoveObjectForKey(@"micDelay");
  36. }
  37. - (instancetype)init {
  38. self = [super init];
  39. if (self) {
  40. [self clearMicDelay];
  41. }
  42. return self;
  43. }
  44. - (void)configCloudWebSource {
  45. CLOUD_CONFIG.scrpit_name = SCRIPT_NAME;
  46. CLOUD_CONFIG.agent_name = AGENT_NAME;
  47. CLOUD_CONFIG.agent_domain = AGENT_DOMAIN;
  48. CLOUD_CONFIG.token_type = UserDefault(Token_type);
  49. CLOUD_CONFIG.current_token = UserDefault(TokenKey);
  50. CLOUD_CONFIG.user_ID = UserDefault(UIDKey);
  51. CLOUD_CONFIG.socket_host = SOCKET_URL;
  52. CLOUD_CONFIG.authFilePath = CERT_PATH;
  53. CLOUD_CONFIG.need_auth = SSL_AUTH;
  54. CLOUD_CONFIG.themeColor = THEMECOLOR;
  55. CLOUD_CONFIG.soundFilePath = [[NSBundle mainBundle] pathForResource:@"synthgms" ofType:@"sf2"];
  56. }
  57. - (void)showWebView:(NSDictionary *)parm fromController:(CustomNavViewController *)navCtrl {
  58. KSCloudWebViewController *ctrl = [[KSCloudWebViewController alloc] init];
  59. ctrl.webViewDelegate = self;
  60. ctrl.url = [parm ks_stringValueForKey:@"url"];
  61. ctrl.parmDic = parm;
  62. NSInteger orientation = [parm ks_integerValueForKey:@"orientation"];
  63. BOOL isLandScape = orientation == 0 ? YES : NO;
  64. ctrl.ks_landScape = isLandScape;
  65. [ctrl showCustomLoading];
  66. [navCtrl pushViewController:ctrl animated:YES];
  67. }
  68. - (void)openSettingView {
  69. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
  70. }
  71. // 回调权限
  72. - (void)NotiferShowPremissAlert:(NSString *)message {
  73. [KSCloudPremissionAlertView configDescMessage:message cancel:^{
  74. } confirm:^{
  75. [self openSettingView];
  76. }];
  77. }
  78. // 下载
  79. - (void)notiferDownloadFileUrl:(NSString *)url success:(void (^)(NSURL * _Nonnull, NSString * _Nonnull))success faliure:(void (^)(void))faliure {
  80. [KSNetworkingManager downloadFileRequestWithFileUrl:url progress:^(int64_t bytesRead, int64_t totalBytes) {
  81. } success:^(NSURL * _Nonnull fileUrl) {
  82. if (success) {
  83. success(fileUrl,url);
  84. }
  85. } faliure:^(NSError * _Nonnull error) {
  86. if (faliure) {
  87. faliure();
  88. }
  89. }];
  90. }
  91. // 上传
  92. - (void)uploadFile:(NSString *)uploadFileUrl success:(void (^)(NSString * _Nonnull))success faliure:(void (^)(NSString * _Nonnull))faliure {
  93. [LOADING_MANAGER showCustomLoading:@"上传中..."];
  94. NSData *fileData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:uploadFileUrl]];
  95. NSString *suffix = [NSString stringWithFormat:@".%@",[uploadFileUrl pathExtension]];
  96. [UPLOAD_MANAGER configWithfilePath:@"/user/"];
  97. [UPLOAD_MANAGER videoUpload:fileData fileName:@"video" fileSuffix:suffix progress:^(int64_t bytesWritten, int64_t totalBytes) {
  98. // 显示进度
  99. int progress = (int)(bytesWritten / totalBytes * 100);
  100. __block NSString *tipsMessage = [NSString stringWithFormat:@"上传中 %d%%",progress];
  101. dispatch_main_async_safe(^{
  102. [LOADING_MANAGER.loadingView setDisplayText:tipsMessage];
  103. });
  104. } successCallback:^(NSMutableArray * _Nonnull fileUrlArray) {
  105. [LOADING_MANAGER removeCustomLoading];
  106. NSString *fileUrl = [fileUrlArray lastObject];
  107. success(fileUrl);
  108. } faliure:^(NSError * _Nullable error, NSString * _Nullable descMessaeg) {
  109. [LOADING_MANAGER removeCustomLoading];
  110. faliure(descMessaeg);
  111. }];
  112. }
  113. // 错误上报
  114. - (void)cloudPageOccourError:(NSMutableDictionary *)uploadParm {
  115. [uploadParm setValue:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] forKey:@"version"];
  116. NSString *content = [uploadParm mj_JSONString];
  117. NSMutableDictionary *submitParm = [KSLogManager generateLogMessageWithContent:content type:@"ERROR"];
  118. NSMutableArray *uploadArray = [NSMutableArray arrayWithObject:submitParm];
  119. [KSNetworkingManager sysExceptionLogUpdate:KS_POST token:UserDefault(TokenKey) logArray:uploadArray success:^(NSDictionary * _Nonnull dic) {
  120. if ([dic ks_integerValueForKey:@"code"] == 200) {
  121. }
  122. } faliure:^(NSError * _Nonnull error) {
  123. }];
  124. }
  125. #pragma mark ------- KSCloudWebViewControllerDelegate
  126. - (void)openWebViewWithParm:(NSDictionary *)parm inNavController:(UINavigationController *)navController {
  127. KSBaseWKWebViewController *detailCtrl = [[KSBaseWKWebViewController alloc] init];
  128. detailCtrl.url = [parm ks_stringValueForKey:@"url"];
  129. detailCtrl.parmDic = parm;
  130. NSInteger orientation = [parm ks_integerValueForKey:@"orientation"];
  131. BOOL isLandScape = orientation == 0 ? YES : NO;
  132. detailCtrl.ks_landScape = isLandScape;
  133. if ([parm ks_boolValueForKey:@"showLoadingAnim"]) {
  134. [detailCtrl showCustomLoading];
  135. }
  136. [navController pushViewController:detailCtrl animated:YES];
  137. }
  138. - (void)showMergeViewWithParm:(NSDictionary *)parm displayInView:(UIView *)displayView callBackController:(KSCloudWebViewController *)controller {
  139. KSAccompanyDraftViewController *ctrl = [[KSAccompanyDraftViewController alloc] init];
  140. ctrl.ks_landScape = YES;
  141. ctrl.recordId = [parm ks_stringValueForKey:@"recordId"];
  142. ctrl.songName = [parm ks_stringValueForKey:@"title"];
  143. ctrl.coverImage = [parm ks_stringValueForKey:@"coverImg"];
  144. if ([[parm allKeys] containsObject:@"speedRate"]) {
  145. ctrl.musicSpeed = [parm ks_floatValueForKey:@"speedRate"];
  146. }
  147. else {
  148. ctrl.musicSpeed = 1.0f;
  149. }
  150. if ([[parm allKeys] containsObject:@"speedRate"]) {
  151. ctrl.musicSpeed = [parm ks_floatValueForKey:@"speedRate"];
  152. }
  153. else {
  154. ctrl.musicSpeed = 1.0f;
  155. }
  156. NSString *musicSheetId = [parm ks_stringValueForKey:@"musicSheetId"];
  157. ctrl.musicSheetId = musicSheetId;
  158. if ([[parm allKeys] containsObject:@"musicRenderType"]) {
  159. ctrl.musicRenderType = [parm ks_stringValueForKey:@"musicRenderType"];
  160. }
  161. else {
  162. ctrl.musicRenderType = @"staff";
  163. }
  164. if ([[parm allKeys] containsObject:@"part-index"]) {
  165. ctrl.partIndex = [parm ks_integerValueForKey:@"part-index"];
  166. }
  167. else {
  168. ctrl.partIndex = 0;
  169. }
  170. MJWeakSelf;
  171. NSInteger defaultDelay = [parm ks_integerValueForKey:@"defaultDelay"];
  172. NSURL *videoUrl = [parm valueForKey:@"videoUrl"];
  173. NSURL *bgAudioUrl = [parm valueForKey:@"bgAudioUrl"];
  174. NSURL *recordUrl = [parm valueForKey:@"recordUrl"];
  175. NSString *accompanyUrl = [parm ks_stringValueForKey:@"remoteBgUrl"];
  176. [ctrl configWithVideoUrl:videoUrl bgAudioUrl:bgAudioUrl remoteBgUrl:accompanyUrl recordUrl:recordUrl offsetTime:defaultDelay mergeCallback:^(MERGEBACK backType) {
  177. if (backType == MERGEBACK_RETRY) {
  178. [weakSelf callbackRetryEvaluating:controller];
  179. }
  180. else if (backType == MERGEBACK_PUBLISH) {
  181. [weakSelf callBackMergeSuccess:controller];
  182. }
  183. }];
  184. [controller.navigationController pushViewController:ctrl animated:NO];
  185. }
  186. - (void)callbackRetryEvaluating:(KSCloudWebViewController *)controller {
  187. [controller retryEvaluatingMusic];
  188. }
  189. - (void)callBackMergeSuccess:(KSCloudWebViewController *)controller {
  190. [controller musicPublishCallBack];
  191. }
  192. - (void)changeCurrentPageLandScape:(BOOL)landScape changeController:(KSCloudWebViewController *)controller {
  193. if (landScape) {
  194. // 切换到横屏
  195. if (IS_IPAD) {
  196. controller.zh_statusBarHidden = YES;
  197. }
  198. AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
  199. delegate.allowAutoRotate = YES;
  200. [UIDevice switchNewOrientation:UIInterfaceOrientationLandscapeRight inController:controller];
  201. }
  202. else {
  203. if (IS_IPAD) {
  204. controller.zh_statusBarHidden = NO;
  205. }
  206. AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
  207. delegate.allowAutoRotate = NO;
  208. [UIDevice switchNewOrientation:UIInterfaceOrientationPortrait inController:controller];
  209. }
  210. }
  211. - (void)notiferShowAICustomLoadingDisplayInView:(UIView *)view callBackController:(KSCloudWebViewController *)controller {
  212. MJWeakSelf;
  213. [self.customLoading loadingCallback:^{
  214. [weakSelf notiferBack:controller];
  215. }];
  216. if ([view.subviews containsObject:self.customLoading]) {
  217. return;
  218. }
  219. [view addSubview:self.customLoading];
  220. [self.customLoading mas_makeConstraints:^(MASConstraintMaker *make) {
  221. make.left.top.right.bottom.mas_equalTo(view);
  222. }];
  223. [view bringSubviewToFront:self.customLoading];
  224. [self.customLoading showLoading];
  225. }
  226. - (void)notiferRemoveAICustomLoading {
  227. [self.customLoading stopLoading];
  228. _customLoading = nil;
  229. }
  230. #pragma mark ----- 延迟检测流程
  231. - (void)showDelayCheckViewDisplay:(UIView *)displayView callBackController:(KSCloudWebViewController *)controller {
  232. if (_checkView) {
  233. if ([displayView.subviews containsObject:self.checkView]) {
  234. [self.checkView removeFromSuperview];
  235. _checkView = nil;
  236. }
  237. }
  238. MJWeakSelf;
  239. self.checkView = [KSDelayCheckView shareInstance];
  240. [displayView addSubview:self.checkView];
  241. [self.checkView mas_makeConstraints:^(MASConstraintMaker *make) {
  242. make.left.top.right.bottom.mas_equalTo(displayView);
  243. }];
  244. [displayView bringSubviewToFront:self.checkView];
  245. [self.checkView changeCheckType:DELAYCHECK_TYPE_PREPARE];
  246. [self.checkView delayCheckCallback:^(DELAYCHECK_CALLBACK action) {
  247. [weakSelf delayFinishAction:action callback:controller];
  248. }];
  249. BOOL isConnected = [controller isSocketConnected];
  250. self.checkView.isSocketConnected = isConnected;
  251. if (isConnected == NO) {
  252. [controller connectSocket];
  253. }
  254. // 检测耳机状态
  255. [controller checkAudioType];
  256. }
  257. - (void)changeDelayCheckStatus:(CHECK_DELAY_TYPE)checkStatus {
  258. if (self.checkView) {
  259. switch (checkStatus) {
  260. case CHECK_DELAY_TYPE_START:
  261. {
  262. [self.checkView changeCheckType:DELAYCHECK_TYPE_ING];
  263. }
  264. break;
  265. case CHECK_DELAY_TYPE_FAILED:
  266. {
  267. [self.checkView changeCheckType:DELAYCHECK_TYPE_FAIL];
  268. }
  269. break;
  270. case CHECK_DELAY_TYPE_SUCCESS:
  271. {
  272. [self.checkView changeCheckType:DELAYCHECK_TYPE_SUCCESS];
  273. }
  274. break;
  275. case CHECK_DELAY_TYPE_CANCEL:
  276. {
  277. [self.checkView cancelDelayCheck];
  278. self.checkView = nil;
  279. }
  280. break;
  281. default:
  282. break;
  283. }
  284. }
  285. }
  286. - (void)displayCurrentHeadsetTypes:(NSDictionary *)parm {
  287. BOOL checkIsWired = [parm ks_boolValueForKey:@"checkIsWired"];
  288. if (self.checkView) {
  289. if (!checkIsWired != self.checkView.isHeadsetOff) {
  290. self.checkView.isHeadsetOff = !checkIsWired;
  291. }
  292. }
  293. }
  294. - (void)socketConnectedCallback {
  295. if (self.checkView) {
  296. self.checkView.isSocketConnected = YES;
  297. }
  298. }
  299. - (void)delayFinishAction:(DELAYCHECK_CALLBACK)action callback:(KSCloudWebViewController *)controller {
  300. switch (action) {
  301. case DELAYCHECK_CALLBACK_START:
  302. {
  303. [controller startAppDelayCheck];
  304. }
  305. break;
  306. case DELAYCHECK_CALLBACK_CANCEL:
  307. {
  308. [controller cancelAppDelayCheck];
  309. self.checkView = nil;
  310. }
  311. break;
  312. case DELAYCHECK_CALLBACK_FINISH:
  313. {
  314. [controller finishDelayCheck];
  315. self.checkView = nil;
  316. }
  317. break;
  318. case DELAYCHECK_CALLBACK_FAILED: // 失败
  319. {
  320. [controller checkDelayBreak];
  321. }
  322. break;
  323. default:
  324. break;
  325. }
  326. }
  327. #pragma mark ---- error View
  328. - (void)notiferShowErrorViewDisplayInView:(UIView *)view callBackController:(KSCloudWebViewController *)controller {
  329. MJWeakSelf;
  330. [_errorView failViewActionCallback:^(BOOL isBack) {
  331. [weakSelf hideErrorViewInView:view];
  332. if (isBack) {
  333. [weakSelf notiferBack:controller];
  334. }
  335. else {
  336. [weakSelf notiferRefresh:controller];
  337. }
  338. }];
  339. }
  340. - (void)notiferRemoveErrorInView:(UIView *)view {
  341. [self hideErrorViewInView:view];
  342. }
  343. - (void)hideErrorViewInView:(UIView *)view {
  344. if ([view.subviews containsObject:self.errorView]) {
  345. [self.errorView removeFromSuperview];
  346. }
  347. _errorView = nil;
  348. }
  349. - (void)notiferRefresh:(KSCloudWebViewController *)controller {
  350. [controller loadRequest];
  351. }
  352. #pragma mark ----- 小酷AI loading
  353. - (AccompanyLoadingView *)customLoading {
  354. if (!_customLoading) {
  355. _customLoading = [AccompanyLoadingView shareInstance];
  356. }
  357. return _customLoading;
  358. }
  359. - (void)notiferBack:(KSCloudWebViewController *)controller {
  360. if (_customLoading) {
  361. [self notiferRemoveAICustomLoading];
  362. }
  363. if (_errorView) {
  364. [_errorView removeFromSuperview];
  365. _errorView = nil;
  366. }
  367. [controller backPreViewAction];
  368. }
  369. #pragma mark --- web error
  370. - (KSWebLoadRefreshView *)errorView {
  371. if (!_errorView) {
  372. _errorView = [KSWebLoadRefreshView shareInstance];
  373. }
  374. return _errorView;
  375. }
  376. @end