AISleepCoachController.m 10.1 KB
//
//  AISleepCoachController.m
//  DreamSleep
//
//  Created by peter on 2022/4/1.
//

#import "AISleepCoachController.h"
#import <WebKit/WebKit.h>
#import <JavaScriptCore/JavaScriptCore.h>
#import "RelaxTrainController.h"
#import "SomeProxy.h"
#import "UnityGameController.h"
#import "UserRequestModel.h"
#import "DsMaskView.h"

@interface AISleepCoachController () <WKNavigationDelegate, WKScriptMessageHandler, DsWebControllerDelegate, RelaxTrainControllerDelegate>
@property (strong, nonatomic) WKWebView *aiWebView;
@property (strong, nonatomic) NSMutableURLRequest *request;
@property (strong, nonatomic) UIProgressView *progressView;
@property (strong, nonatomic) ExceptionDefaultView *exceptionView;
@property (nonatomic, strong) DsMaskView *dsMaskView;
@end

@implementation AISleepCoachController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.view.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
    
    // 创建WKWebView对象,添加到界面(storyboard没有控件)
    [self.view addSubview:self.aiWebView];
    [self.view addSubview:self.progressView];
    
    // 监听AI睡眠教练页面需要刷新数据通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(needUpdateAiCoach) name:NeedUpdateAICoach object:nil];
}

- (void)dealloc {
    [self.aiWebView.configuration.userContentController removeScriptMessageHandlerForName:@"AppModel"];
    [self.aiWebView removeObserver:self forKeyPath:@"estimatedProgress"];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:NeedUpdateAICoach object:nil];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    [self.dsMaskView display];
}

#pragma mark - 登录成功后刷新
- (void)needUpdateAiCoach {
    NSHTTPCookie *sidCookie = nil;
    for (NSHTTPCookie *cookie in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies) {
        // connect.sid是后台下发的cookie字段
        if ([cookie.name isEqualToString:@"connect.sid"]) {
            sidCookie = cookie;
            break;;
        }
    }
    // 将APP获取的cookie同步给wkwebview容器里面的cookie(wkwebview存在cookie不同步的巨坑,该同步API在iOS 11及以后支持)
    [self.aiWebView.configuration.websiteDataStore.httpCookieStore setCookie:sidCookie completionHandler:^{
        [self.aiWebView loadRequest:self.request];
    }];
}

- (void)startOpen {
    if (![LoginUtils getUserLoginData]) {
        [LoginUtils jumpToLoginControllerWithTarget:self];
    }
}

#pragma mark - DsWebControllerDelegate && RelaxTrainControllerDelegate
- (void)reloadAIPage {
    [self.aiWebView reload];
}

#pragma mark - WKWebView的监听方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"estimatedProgress"]) {
        self.progressView.progress = self.aiWebView.estimatedProgress;
        if (self.progressView.progress == 1) { self.progressView.hidden = YES; }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler {
    NSString *url = navigationAction.request.URL.absoluteString;
    DSLog(@"AI睡眠教练主页面入口->跳转链接:%@", url);
    
    if ([url isEqualToString:AICoachURL]) {
        decisionHandler(WKNavigationActionPolicyAllow);
    } else {
        // 开启新的webview页面加载
        DsWebController *newWebVC = [[DsWebController alloc] initWithLink:url isShowNavi:NO];
        newWebVC.refreshDelegate = self;
        [self.navigationController pushViewController:newWebVC animated:YES];
        decisionHandler(WKNavigationActionPolicyCancel);
    }
}

// 开始加载
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}

// 加载成功
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    self.exceptionView.hidden = YES;
    self.aiWebView.hidden = NO;
}

// 加载失败
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    self.exceptionView.hidden = NO;
    self.aiWebView.hidden = YES;
    DSLog(@"加载失败:%@", error);
}

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"AppModel"]) {
        NSDictionary *bodyDic = message.body;
        int type = [bodyDic[@"type"] intValue];
        DSLog(@"bodyDic:%@", bodyDic);
        switch (type) {
            case 1: // 未登录点击开启
            {
                [self startOpen];
            }
                break;
            case 2: // 登录点击开启-开启我的页面里面的AI睡眠教练
            {
                [UserRequestModel autoLoginRequestWithCompletion:^(UserRequestModel * _Nonnull requestModel) {
                    if (requestModel.resCode == DSResCodeSuccess) {
                        [[NSNotificationCenter defaultCenter] postNotificationName:NeedUpdateStartAI object:nil];
                    }
                }];
            }
                break;
            case 3: // 轻拍哄睡
            {
                UnityGameController *gameVC = [UnityGameController new];
                gameVC.gameType = GameTypeCoax;
                [self.navigationController pushViewController:gameVC animated:YES];
            }
                break;
            case 4: // 安心记事本
            {
                [DSProgressHUD showToast:@"该功能未来会被替换"];
            }
                break;
            case 5: // 练习腹式呼吸法
            {
                RelaxTrainController *relaxVC = [RelaxTrainController new];
                relaxVC.refreshDelegate = self;
                relaxVC.params = bodyDic;
                [self.navigationController pushViewController:relaxVC animated:YES];
            }
                break;
            default:
                break;
        }
        
        // 注入js代码用于强制刷新小梦睡眠
        //            NSString *jsCallBack = @"window.parent.location.reload()";
        //            [self.aiWebView evaluateJavaScript:jsCallBack completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        //                [self.aiWebView loadRequest:self.request];
        //                DSLog(@"注入成功...");
        //                if (error) {
        //                    DSLog(@"err is %@", error.domain);
        //                }
        //            }];
    }
}

#pragma mark - lazy
- (WKWebView *)aiWebView {
    if (!_aiWebView) {
        // 进行配置控制器
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
        // 实例化对象
        configuration.userContentController = [WKUserContentController new];
        // 调用JS方法
        [configuration.userContentController addScriptMessageHandler:[[SomeProxy alloc] initObject:self] name:@"AppModel"];
        
        // 进行偏好设置
        WKPreferences *preferences = [WKPreferences new];
        preferences.javaScriptCanOpenWindowsAutomatically = YES;
        preferences.javaScriptEnabled = YES;
        configuration.preferences = preferences;
        
        // 初始化WKWebView
        _aiWebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight - kTabBarHeight) configuration:configuration];
        _aiWebView.backgroundColor = DSWhite;
        _aiWebView.hidden = YES;
        _aiWebView.scrollView.bounces = NO;
        [_aiWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
        _aiWebView.navigationDelegate = self;
        _aiWebView.scrollView.showsVerticalScrollIndicator = NO;
        _aiWebView.scrollView.showsHorizontalScrollIndicator = NO;
        // 解决页面顶部出现白色问题
        _aiWebView.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        self.request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:AICoachURL] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];
        [_aiWebView loadRequest:self.request];
    }
    return _aiWebView;
}

- (UIProgressView *)progressView {
    if (!_progressView) {
        _progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 0)];
        _progressView.tintColor = HighlightColor;
        // 通过放大Y轴来改变高度
        _progressView.transform = CGAffineTransformMakeScale(1.0f, 3.0f);;
    }
    return _progressView;
}

- (ExceptionDefaultView *)exceptionView {
    if (!_exceptionView) {
        WS(weakSelf);
        _exceptionView = [[ExceptionDefaultView alloc] initWithType:ExceptionTypeNet block:^{
            weakSelf.progressView.hidden = NO;
            weakSelf.progressView.progress = 0;
            weakSelf.exceptionView.hidden = YES;
            [weakSelf.aiWebView loadRequest:weakSelf.request];
        } superView:self.view];
    }
    return _exceptionView;
}

- (DsMaskView *)dsMaskView {
    if (!_dsMaskView) {
        _dsMaskView = [[DsMaskView alloc] initWithSuperView:self.view];
    }
    return _dsMaskView;
}

#pragma mark - 关闭侧滑
- (BOOL)enableInteractivePopGestureRecognizer {
    return NO;
}

#pragma mark - 隐藏导航栏
- (BOOL)isShowNavigationBar {
    return YES;
}

#pragma mark - 品牌模式
- (NaviStyle)navigationBarStyle {
    return NaviStyleDefault;
}

#pragma mark - 设置状态栏文字颜色
- (UIStatusBarStyle)preferredStatusBarStyle {
    return [self.dk_manager.themeVersion isEqualToString:DKThemeVersionNormal] ? UIStatusBarStyleDefault : UIStatusBarStyleLightContent;
}

@end