Commit 1a2a9e6b authored by jz's avatar jz

add files

parent 42d48fd1
//
// GMBaseWebViewController.h
// ZhengXing
//
// Created by wangyang on 3/5/19.
// Copyright (c) 2019 Wanmei Creative. All rights reserved.
// 后期替代WMBaseViewController&WMBrowserViewController
@import GMShareSDK;
//#import <GMShareSDK/GMShareSDK.h>
#define kWebPhantom @"phantom"// 常用于H5新页面
#define kWebHybrid @"hybrid" // 常用于H5老页面
//#import <GMShareSDK/GMShareView.h>
////#import "GMShareView.h"
//#import <GMShareSDK/WMShareObject.h>
//#import <GMShareSDK/GMDiaryShareView.h>
//#import <GMShareSDK/GMClientH5Object.h>
#import "GMWebViewModel.h"
typedef NS_ENUM(NSInteger, GMWebPageType) {
GMWebPageTypeNomal = 0,
GMWebPageTypeSign = 1, // 签到H5页面
GMWebPageTypeTopicDetail = 2,// 日记贴
GMWebPageTypeAnswer = 3,// 回答
GMWebPageTypeArticle = 4,// 话题
GMWebPageTypeSpecial = 5,// 专栏
GMWebPageTypeUserTopic = 6,// 用户贴
GMWebPageTypeQuestion = 7,// 回答 7.20 灰度用
GMWebPageTypeHospitalRank = 8,// 医院榜单
GMWebPageTypeDoctorRank = 9,// 医生榜单
};
@import GMKit;
@class GMWebViewComponent;
@interface GMBaseWebViewController : WMBaseViewController<GMClientH5BridgeDelegate> {
/**
* @brief 下面都是从js中得到的数据。其中_jsGlobalObject字典包含其它数据
*/
NSDictionary *_jsGlobalObject;
// 是否显示了分享
BOOL _isShowShare;
// 是否收藏
BOOL _isFavored;
// 是否是自己发的贴
BOOL _isPrivate;
// 是否是签到,签到导航栏透明,返回按钮、title颜色、rightIcon单独设置
BOOL _isSign;
}
@property (nonatomic, strong) GMWebViewComponent *webCompent;
/// web上数据处理
@property (nonatomic, strong) GMWebViewModel *viewModel;
/**
* @brief 要请求的 H5 url 除了 http://backend.dev.gengmei.cc/hybrid" 这部分后的path。比如一个h5是 http://backend.dev.gengmei.cc/hybrid/topic/3332214,那么path指需要赋值@"/topic/3332214"即可.
@note 在viewDidLoad前配置好。必须以"/"开头。重写moreQueryParameters可以添加额外query
*/
@property (nonatomic, strong) NSString *path;
/**
* @brief 对于从服务器那儿获取到的完整H5 url,使用该属性。
@note 在viewDidLoad前配置好。会覆盖path属性。重写moreQueryParameters可以添加额外query
*/
@property (nonatomic, strong) NSString *fullURL;
/// 通过webPageType 页面不同设置不同的差异性
@property (nonatomic, assign) GMWebPageType webPageType;
#pragma mark - 分享
@property (nonatomic, strong) GMShareView *shareView;
@property (nonatomic, strong) GMDiaryShareView *diaryShareView;
/*** @brief 收藏url**/
@property (nonatomic,strong) NSString *favUrl;
/*** @brief 从_jsGlobalObject中获取的分享Model */
@property (nonatomic, strong) WMShareObject *shareObject;
/*** @brief 日记分享Model数组 */
@property (nonatomic, strong) NSMutableArray *diaryShareArr;
/*** @brief 微信分享Model */
@property (nonatomic, strong) WMShareObject *weixinShareObject;
/*** @brief 分享的配置 */
@property (nonatomic, strong) GMShareConfigObject *shareConfigObject;
@property (nonatomic , strong) NSString *favorType;
/**
设置打开的权限类型
*/
@property (nonatomic, assign) NSInteger settingType;
@property (nonatomic, assign) BOOL backNeedRefresh;
/**
* @brief 重写该方法,为fullURL在请求前添加更多参数。必须以 & 开头
* 原方法只返回了空字符串,不需要call super
*
* @return 要额外添加的参数。如:&key1=value&key2=value
*/
- (NSString *)moreQueryParameters;
/**
调用该方法以重新构造URL并且[_webView loadRequest:request];
*/
- (void)reloadURL;
/**
处理请求URL
*/
- (void)handleURL;
// 一般情况下 页面刷新时候调用
- (void)refreshWebView;
// 本地获取通用数据
- (NSString *)nativeCommonParam;
@end
//
// WMDiaryAndTopicBaseController.m
// ZhengXing
//
// Created by wangyang on 3/5/15.
// Copyright (c) 2015 Wanmei Creative. All rights reserved.
//
#import "GMBaseWebViewController.h"
//#import "AppDelegate+AppInit.h"
//#import "Gengmei-Swift.h"
#import "UIViewController+UrlScheme.h"
#import "WMBaseViewController+OCNavigationBar.h"
#import <mach/mach_time.h>
#import "GMCookieManager.h"
#import "GMWebViewUrlProtocol.h"
#import "GMWeixinShareView.h"
#import "WMShareObject.h"
@interface GMBaseWebViewController ()<MFMessageComposeViewControllerDelegate, GMCommonAlertViewDelegate,GMPhotoPickDismissDelegate,WKWebViewDelegate,GMShareViewDelegate, GMDiaryShareViewDelegate>
{
// 是否显示微信快照和朋友圈快照
BOOL _isShowScreenshot;
GMAddressManager *_manager;
// 是否需要回调权限打开状态
BOOL _isSettingCallback;
// 表示要上传的照片是可以公开的还是具体保护性的
BOOL _isPrivatePhoto;
// 接受h5的参数,图片上传成功后,以这个参数为key,把图片Url返回给h5
NSString *_requestCoder;
// 是否显示了来自h5设置的rightButton
BOOL _isJsRightButton;
BOOL _isJsNearRightButton;
// 导航栏是否透明,YES透明,NO不透明
BOOL _isNavigationAlpha;
// 导航栏是否隐藏
BOOL _isNavigationHidden;
}
@property (nonatomic, assign) CGFloat animationDistance;
@property (nonatomic, strong) GMPlayerView *playBackView;
@property (nonatomic, assign) BOOL goToAppSettingsPage;// 跳转到系统设置页面
@end
@implementation GMBaseWebViewController
#pragma mark - init
- (void)initController {
[super initController];
self.viewModel = [GMWebViewModel new];
self.goToAppSettingsPage = NO;
self.webPageType = GMWebPageTypeNomal;
// 短信链接唤起app埋点 @author 李震(WMBrowserViewController)
if ([AppDelegate shareInstance].extraParam.isNonEmpty) {
self.extraParam = [AppDelegate shareInstance].extraParam;
[AppDelegate shareInstance].extraParam = @"";
}
}
#pragma mark - view lifeCycle
- (void)viewDidLoad {
[super viewDidLoad];
[self initReferer];
[self initRefererLink];
[self initReferrerTabName];
self.navigationBar.isShowShadow = NO;
self.backNeedRefresh = NO;
CGFloat top = OCNavigationBar.barHeight;
[self.webCompent mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.top.mas_equalTo(top);
make.bottom.mas_equalTo(0);
}];
// 设置Agent,关键字是最后的那个Gengmei,这样服务端就知道是通过app内部加载网页。
NSDictionary *dictionary = USER_AGENT_DIC;
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
// 加载URL
[self reloadURL];
// 添加通知监听
[self addActiveObserver];
// 导航栏渐变
[self prepareNavigation];
}
/// 通过webPageType 页面不同设置不同的差异性
/// @param webPageType webPageType
- (void)setWebPageType:(GMWebPageType)webPageType {
_webPageType = webPageType;
switch (webPageType) {
case GMWebPageTypeSign:
self.pageName = @"new_sign";
break;
case GMWebPageTypeQuestion:
{
self.pageName = @"question_answer_detail";
}
break;
default:
break;
}
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self nativeAppearToCallJS];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if (self.backNeedRefresh) {
[self refreshWebView];
self.backNeedRefresh = NO;
}
[self nativeDisAppearToCallJS];
}
#pragma mark - Load Request
- (void)reloadURL {
[self handleURL];
[self webViewLoadRequest];
}
- (void)webViewLoadRequest {
if (self.fullURL == nil || [self.fullURL isEqualToString:@""]) {
return;
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
self.webCompent.fullUrl = self.fullURL;
// self.webCompent.fullUrl = @"http://172.30.8.83:3000/phantom/question/3482021";
[self.webCompent webviewLoad:self];
}
// 一般情况下 页面刷新时候调用
- (void)refreshWebView {
//自己本地调用webview刷新时候,绑定关系还存在,不需要重新绑定GMClient和window上的方法.
[self.webCompent reload];
}
#pragma mark - Handle URL
/**
不允许重写
*/
- (void)handleURL {
if (_fullURL.length == 0) {
// 使用path拼接,并且加上query
_fullURL = [self wrapWebUrlWithPath];
} else {
// 为fullURL加上默认query
_fullURL = [self wrapWebUrlWithFullURL];
}
if (![_fullURL isNonEmpty]) return;
// 额外的参数
_fullURL = [_fullURL stringByAppendingString:[self moreQueryParameters]];
/// 添加referrer_link
_fullURL = [self addReferrerLinkWithFullURL];
self.webCompent.fullUrl = _fullURL;
}
/**
不允许重写
*/
- (NSString *)wrapWebUrlWithPath {
if (![_path isNonEmpty]) {
return @"";
}
NSString *path = self.path;
NSString *parames = [NSString stringWithString:GMNetworking.urlCommonParameters];
if ([path containsString:@"?"]) {
parames = [parames stringByReplacingOccurrencesOfString:@"?" withString:@"&"];
}
NSString *wrapedUrl = [NSString stringWithFormat:@"%@%@%@", GMServerDomains.apiHost, path,parames];
// 兼容新老页面,在此认为新的没有host域名的h5页面默认携带phantom,而不进行拼接
NSArray *pathArray = [path componentsSeparatedByString:@"/"];
if (![pathArray containsObject:kWebPhantom] && ![pathArray containsObject:kWebHybrid]) {
wrapedUrl = [NSString stringWithFormat:@"%@/%@%@%@", GMServerDomains.apiHost, kWebHybrid, path, parames];
}
return wrapedUrl;
}
/**
不允许重写
*/
- (NSString *)wrapWebUrlWithFullURL {
// 因为有的 fullURL 带了一部分 query,而将要拼接的urlCommonParameters还带了一个问号,所以要做判断
NSString *defaultQuery = GMNetworking.urlCommonParameters;
if ([_fullURL rangeOfString:@"?"].length > 0) {
defaultQuery = [defaultQuery stringByReplacingOccurrencesOfString:@"?" withString:@"&"];
}
NSString *wrapedUrl = [NSString stringWithFormat:@"%@%@", _fullURL, defaultQuery];
return wrapedUrl;
}
/// 添加referrer_link 不允许重写
- (NSString *)addReferrerLinkWithFullURL {
NSString *referrerLink = @"";
NSDictionary *param = [_fullURL urlQueryToDictionary];
if (![param.allKeys containsObject:@"referrer_link"]) {
BOOL aiConsultGray = GMLaunchManager.shareManager.appConfigObject.aiConsultGray;
NSString *referrerLinkString = [self.referrerLink componentsJoinedByString:@","];
referrerLink = [NSString stringWithFormat:@"&ai_consult_gray=%@&referrer_link=%@",(aiConsultGray ? @"1" : @"0"),referrerLinkString];
}
return [NSString stringWithFormat:@"%@%@", _fullURL, referrerLink];
}
- (NSString *)moreQueryParameters {
return @"";
}
- (void)setFullURL:(NSString *)fullURL {
_fullURL = fullURL;
debugLog(@"%@", _fullURL);
NSDictionary *params = [fullURL urlQueryToDictionary];
if ([params.allKeys containsObject:@"referrer"]) {
self.referer = params[@"referrer"];
}
// cpc 相关
if ([params.allKeys containsObject:@"cpc_referer"]) {
self.cpc_referer = [params[@"cpc_referer"] integerValue];
}
if ([params.allKeys containsObject:@"is_cpc"]) {
self.is_cpc = [params[@"is_cpc"] boolValue];
}
// navigation_color_clear: 1透明,0不透明
if ([params[@"navigation_color_clear"] intValue]) {
_isNavigationAlpha = YES;
// referer: push:表示来源为推送;pop_ad:表示来源开屏小广告(没有倒计时);big_ad:表示来源开屏大广告(有倒计时)
self.navigationBar.leftIcon = @"back_circle_white";
self.navigationBar.buttonMargin = 10;
}
// 设置导航栏是否隐藏
_isNavigationHidden = [params[@"navigation_hidden"] boolValue];
}
#pragma mark - 分享 GMShareViewDelegate
- (void)willShowShareView:(GMShareView *)shareView {
shareView.hasFav = _isFavored;
shareView.showDelete = _isPrivate;
shareView.showScreenshot = _isShowScreenshot;
// 连续签到,补签分享,隐藏复制链接、举报、刷新
shareView.showReport = ![_shareConfigObject.hideReport boolValue];
shareView.showCopyLink = ![_shareConfigObject.hideCopyLink boolValue];
shareView.showRefresh = ![_shareConfigObject.hideRefresh boolValue];
if ([_shareConfigObject.hideReport boolValue] && [_shareConfigObject.hideCopyLink boolValue] && [_shareConfigObject.hideRefresh boolValue]) {
shareView.topLineView.hidden = YES;
} else {
shareView.topLineView.hidden = NO;
}
shareView.taskType = _shareConfigObject.taskType;
shareView.isReportShareResult = _shareConfigObject.isReportShareResult;
shareView.shareObject = _shareObject;
}
- (NSString *)shareViewNeedBusinessId {
return self.businessId;
}
- (void)shareResponseSuccess {
[self.webCompent.webView evaluateJavaScript:_shareConfigObject.shareCallback completionHandler:nil];
}
/**@brief 获取分享内容的协议方法需在子类实现,因为需要定制,删除和收藏的协议方法在子类实现即可*/
- (void)shareView:(GMShareView *)shareView favriteContentWithIndexPath:(NSIndexPath *)indexPath {
if ([[GMLoginManager shareInstance] showLoginViewIfNeeded]){
return;
}
GMHTTPMethod method = _isFavored ? GMHTTPMethodDelete : GMHTTPMethodPost;
__weak __typeof(self)weakSelf = self;
[GMNetworking requestOCWithApi:self.favUrl method:method parameters:nil completion:^(GMResponseOC * _Nonnull responseObject) {
if (responseObject.isSuccess) {
_isFavored = !_isFavored;
shareView.hasFav = _isFavored;
NSString *action;
if (_isFavored) {
action = @"do";
[weakSelf showComplete:@"收藏成功"];
}else{
action = @"undo";
[weakSelf showComplete:@"取消收藏成功"];
}
// 分享的埋点
NSDictionary *dic = @{@"action": action,
@"type": weakSelf.favorType,
@"business_id": weakSelf.businessId};
[Phobos track:@"favor" attributes:dic];
[shareView.shareCollectionView reloadItemsAtIndexPaths:@[indexPath]];
} else {
[weakSelf showWarning:responseObject.message];
}
}];
}
#pragma mark - GMShareViewDelegate
- (void)copyShareUrl{
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
if ([_shareObject.url isNonEmpty]) {
pasteboard.string = _shareObject.url;
[self toast:@"链接已复制到系统粘帖板"];
}
}
- (NSMutableDictionary *)fetchSharePublishContent:(GMSharePlatform)shareType{
//这里时间是native,所以只能弹普通的大分享
id shareImage = nil;
GMShareContentType contentType = GMShareContentTypeAuto;
WMShareBasicObject * object = [WMShareBasicObject new];
NSString *image = _shareObject.image;
if (image.length != 0) {
shareImage = [GMShareSDK compressWithUrl:image];
}else{
// 使用app logo做图标
shareImage = [UIImage imageNamed:@"icon"];
}
// 微信会话分享且微信小程序内容不为空的时候,认为是微信小程序分享
if (shareType == GMSharePlatformWechatSession && [_shareObject.wechatmini.path isNonEmpty]) {
shareType = GMSharePlatformWechatMiniProgram;
}
NSString *channel = @"";
switch (shareType) {
case GMSharePlatformWechatSession:
object = _shareObject.wechat;
channel = @"wechat";
break;
case GMSharePlatformWechatTimeline:
object = _shareObject.wechatline;
channel = @"wechatline";
break;
case GMSharePlatformQQFriend:
object = _shareObject.qq;
channel = @"qq";
break;
case GMSharePlatformQQSpace:
object = _shareObject.qq;
channel = @"qzone";
break;
case GMSharePlatformSinaWeibo:
object = _shareObject.weibo;
channel = @"tsina";
break;
case GMSharePlatformWechatSessionSnapShot:
object = _shareObject.wechatScreenshot;
contentType = GMShareContentTypeImage;
//这里不能压缩图片,要保证质量分享
shareImage = _shareObject.wechatScreenshot.content;
break;
case GMSharePlatformWechatTimelineSnapShot:
object = _shareObject.wechatlineScreenshot;
shareImage = _shareObject.wechatlineScreenshot.content;
contentType = GMShareContentTypeImage;
break;
default:
break;
}
if (_isSign) {
if ([_shareObject.url containsString:@"?"]) {
_shareObject.url = [NSString stringWithFormat:@"%@&referrer=%@",_shareObject.url, channel];
} else {
_shareObject.url = [NSString stringWithFormat:@"%@?referrer=%@",_shareObject.url, channel];
}
}
NSMutableDictionary *shareParams = [NSMutableDictionary dictionary];
if (shareType == GMSharePlatformWechatMiniProgram){
[shareParams shareSetupMiniProgramShareParamsByUrl:_shareObject.url
userName:_shareObject.wechatmini.userName
path:_shareObject.wechatmini.path
title:_shareObject.wechatmini.title
description:_shareObject.wechatmini.desc
thumbImage:_shareObject.wechatmini.thumbImageUrl
hdImageData:_shareObject.wechatmini.hdImageUrl];
} else {
[shareParams shareSetupShareParamsByText:object.content
images:shareImage
url:[NSURL URLWithString:_shareObject.url]
title:object.title
type:contentType];
}
return shareParams;
}
#pragma mark - GMClientH5BridgeDelegate
/**
* @brief pageData
*/
- (void)jsGlobalDataLoaded:(NSString *)jsonString {
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
_jsGlobalObject = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
if (_jsGlobalObject == nil) {
return;
}
// 从H5中取得全局变量
@try {
// JIRA 上曾有一个关于此处的bug上报,因为无法查明原因,所以加try catch
[self.webCompent.webView evaluateJavaScript:@"window.GLOBAL.pagedata" completionHandler:nil];
// 当前版本对h5返回businessid和pageName的处理,只在commonwebview中处理,basewebview中不处理
} @catch (NSException *exception) {
// [Bugly reportException:[NSException exceptionWithName:@"_jsGlobalObject获取异常" reason:exception.reason userInfo:@{@"exceptionInfo": exception.userInfo, @"url": self.fullURL}]];
}
if (_jsGlobalObject[@"page_name"]) {
self.pageName = _jsGlobalObject[@"page_name"];
}
if ([_jsGlobalObject[@"business_id"] isNonEmpty]) {
self.businessId = SafeString(_jsGlobalObject[@"business_id"]);
}
if ([_jsGlobalObject.allValues containsObject:@"back_need_refresh"]) {
_backNeedRefresh = [_jsGlobalObject[@"back_need_refresh"] boolValue];
}
// 是否收藏
_isFavored = [_jsGlobalObject[@"is_favord"] boolValue];
// 是否是自己的帖子
_isPrivate = [_jsGlobalObject[@"is_private"] boolValue];
//分享数据源
_shareObject = [[WMShareObject alloc] initWithDictionary:_jsGlobalObject[@"share_data"] error:nil];
_shareConfigObject = [[GMShareConfigObject alloc] initWithDictionary:_jsGlobalObject[@"share_config"] error:nil];
//同时不为空的时候才显示微信快照和朋友圈快照
_isShowScreenshot = [_shareObject.wechatScreenshot.content isNonEmpty] && [_shareObject.wechatScreenshot.content isNonEmpty];
// 是否隐藏分享按钮
if ([_jsGlobalObject.allKeys containsObject:@"hide_share"] &&
![_jsGlobalObject[@"hide_share"] boolValue] && _shareObject) {
_isShowShare = YES;
} else {
_isShowShare = NO;
}
_isSign = [_jsGlobalObject[@"navigation"][@"nav_type"] isEqualToString:@"sign"];
// 连续补签,分享日记
if ([_jsGlobalObject[@"topic_share_data"] count]) {
self.diaryShareArr = [NSMutableArray array];
[self.diaryShareArr addObjectsFromArray:[GMDiaryShareObject arrayOfModelsFromDictionaries:_jsGlobalObject[@"topic_share_data"] error:NULL]];
}
// 处理导航栏数据
[self dealNavigationData];
}
#pragma mark - Deal Navigation
// 导航栏隐藏显示
- (void)jsControlTitleBarVisible:(NSString *)jsonString {
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *showDic = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableLeaves
error:nil];
if ([showDic[@"show"] boolValue]) {
if (!_isSign) {
self.navigationBar.backgroundColor = [UIColor whiteColor];
self.navigationBar.isShowShadow = YES;
} else {
self.navigationBar.backgroundColor = [UIColor clearColor];
}
} else {
self.navigationBar.backgroundColor = [UIColor.blackColor colorWithAlphaComponent:0.6];
self.navigationBar.isShowShadow = NO;
}
}
// 设置导航数据
- (void)dealNavigationData {
NSDictionary *navDict = _jsGlobalObject[@"navigation"];
if (navDict) {
// 右侧图标
NSString *rightIcon = navDict[@"right_button"];
if (rightIcon.isNonEmpty) {
self.navigationBar.rightIconURL = rightIcon;
}
// 右侧文案
NSString *rightText = navDict[@"right_text"];
if (rightText.isNonEmpty) {
self.navigationBar.rightTitle = rightText;
}
self.navigationBar.rightButton.hidden = _isNavigationAlpha;
// 签到
if (_isSign) {
[self.navigationBar.rightButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.right.mas_equalTo(0);
}];
}
// 设置导航栏是否透明
if ([navDict.allKeys containsObject:@"navigation_color_clear"]) {
_isNavigationAlpha = [navDict[@"navigation_color_clear"] intValue] ? YES : NO;
}
self.animationDistance = [navDict[@"header_height"] intValue];
// 设置导航栏是否隐藏
_isNavigationHidden = [navDict[@"navigation_hidden"] boolValue];
// 设置侧滑手势禁用
self.fd_interactivePopDisabled = [navDict[@"pop_disabled"] boolValue];
}
// 设置导航栏
[self prepareNavigation];
// 设置导航栏Title
[self setupNavigateTitle];
}
/// 设置导航栏Title
- (void)setupNavigateTitle {
// 设置导航栏
NSString *title = [_jsGlobalObject[@"name"] isNonEmpty] ? _jsGlobalObject[@"name"] : self.title;
if (_isShowShare) {
[self setNavigateTitle:title rightButtonOption:OCBarButtonImageTypeShare];
} else {
[self setNavigateTitle:title rightButtonOption:OCBarButtonImageTypeDefault];
}
}
/// 设置导航栏是否隐藏
- (void)prepareNavigation {
// navigation_color_clear: 1透明,0不透明
CGFloat top = (_isNavigationAlpha || _isNavigationHidden)?0:OCNavigationBar.barHeight;
if (_isNavigationAlpha) {
self.navigationBar.leftIcon = @"back_circle_white";
self.navigationBar.buttonMargin = 10;
self.webCompent.webView.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
self.webCompent.webView.scrollView.delegate = self;
[self scrollViewDidScroll:self.webCompent.webView.scrollView];
}
[self.webCompent mas_updateConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(top);
}];
self.navigationBar.hidden = _isNavigationHidden;
}
/// 前端调用客户端方法进行返回操作
- (void)jsPopViewControllerAnimated:(BOOL)animated {
if ([self.parentViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigation = (UINavigationController *)self.parentViewController;
NSArray *controllers = navigation.viewControllers;
if (self.presentingViewController && controllers.count == 1) {
[self dismissViewControllerAnimated:YES completion:nil];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
} else {
[self dismissViewControllerAnimated:YES completion:nil];
}
}
#pragma mark - Deal Gload
/**
* @brief js调用该方法以hideLoading
*/
- (void)loadDomFinished {
[self hideLoading];
// 因为此时_jsGlobalObject还不能从H5中获取,所以只先设置一个title,与数据相关的分享功能先不展示
// self.title = [self.webCompent.webView evaluateJavaScript:@"document.title" completionHandler:nil];
[self.webCompent.webView evaluateJavaScript:@"document.title" completionHandler:^(id resonse, NSError * _Nullable error) {
NSLog(@"%@",resonse);
}];
}
- (void)jsShowLoading{
[self showLoading:nil];
}
- (void)jsHideLoading{
[self hideLoading];
}
- (void)jsLogout {
[[GMLoginManager shareInstance] doLogoutAndShowLoginView];
}
// 显示空白页面
- (void)jsShowNativeEmptyView {
[self showEmptyView:GMEmptyViewTypeException];
}
- (void)emptyViewDidClickReload {
[Phobos track:@"on_click_button" attributes:@{@"page_name": SafeString(self.pageName),
@"button_name": @"click_reload"}];
[self hideEmptyView];
[self refreshWebView];
}
// 网络状态 2: 其他 1:wifi 0:无网络
- (NSInteger)jsCheckNetworkState {
NSInteger networkState = 0;
if ([AFNetworkReachabilityManager sharedManager].isReachable) { // 联网状态
if ([AFNetworkReachabilityManager sharedManager].reachableViaWiFi == NO) { // 非WiFi
networkState = 2;
} else {
networkState = 1;
}
}
#warning h5
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('jsCheckNetworkStateCallback',%zd)",networkState];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
return networkState;
}
- (void)jsLocationShowAlertIfNotAllowed {
[GMLocationManager showAlertIfNotAllowed];
}
#pragma mark - ShareView
- (void)jsObjShowShareViewWithJSONString:(NSString *)JSONString{
if ([JSONString isNonEmpty]) {
_shareObject = [[WMShareObject alloc] initWithString:JSONString error:nil];
}
[self.shareView showWithShareUrl:_shareObject.url];
[self addShareTopView:self.shareView.topView];
}
- (void)jsObjShowDiaryShareViewWithJSONString:(NSString *)JSONString {
if ([JSONString isNonEmpty]) {
self.diaryShareArr = [NSMutableArray array];
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
NSArray *shareArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
[self.diaryShareArr addObjectsFromArray:[GMDiaryShareObject arrayOfModelsFromDictionaries:shareArr error:NULL]];
}
[self.diaryShareView showWithShareArr:self.diaryShareArr];
[self addShareTopView:self.diaryShareView.topView];
}
- (void)addShareTopView:(UIView *)topView {
// 连续签到,补签标题
[(GMShareTopView *)topView setName:_shareConfigObject.shareTitle title:_shareConfigObject.shareInfo subTitle:_shareConfigObject.shareTip];
if ([_shareConfigObject.shareTitle isNonEmpty] || [_shareConfigObject.shareInfo isNonEmpty] || [_shareConfigObject.shareTip isNonEmpty]) {
_shareView.topView.hidden = NO;
} else {
_shareView.topView.hidden = YES;
}
}
- (void)jsShowWXShareViewWithJSONString:(NSString *)JSONString{
if ([JSONString isNonEmpty]) {
_weixinShareObject = [[WMShareObject alloc] initWithString:JSONString error:nil];
}
if (_weixinShareObject != nil) {
GMWeixinShareView * weiXinShareView = [GMWeixinShareView shareView];
weiXinShareView.weixinShareObject = _weixinShareObject;
weiXinShareView.sourceController = self;
[self.view addSubview:weiXinShareView];
[weiXinShareView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view).insets(UIEdgeInsetsZero);
}];
[weiXinShareView layoutIfNeeded];
[weiXinShareView showShareView:nil];
}
}
// 根据type 展示跳转指定分享平台(V7.16.1)
- (void)jsSharewithType:(NSDictionary *)data {
NSString *type = data[@"type"]?:@"Wechat";
self.shareObject = [[WMShareObject alloc] initWithDictionary:data[@"share_data"] error:nil];
GMSharePlatform shareType = GMSharePlatformWechatTimeline;
if ([type isEqualToString:@"QZone"]) {
shareType = GMSharePlatformQQSpace;
}else if ([type isEqualToString:@"QQ"]) {
shareType = GMSharePlatformQQFriend;
}else if ([type isEqualToString:@"Wechat"]) {
shareType = GMSharePlatformWechatSession;
}else if ([type isEqualToString:@"WechatMoments"]) {
shareType = GMSharePlatformWechatTimeline;
}else if ([type isEqualToString:@"SinaWeibo"]) {
shareType = GMSharePlatformSinaWeibo;
}
self.shareView.shareUrl = self.shareObject.url;
[self.shareView shareWithType:shareType];
}
// 根据type 展示跳转指定分享平台(兼容之前的代码)
- (void)jsShare:(NSString *)shareDataString withType:(NSString *)type {
NSData *shareData = [shareDataString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:shareData options:NSJSONReadingAllowFragments error:NULL];
if ([type isNonEmpty]) {
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:data];
dict[@"type"] = type;
data = dict;
}
[self jsSharewithType:data];
}
/*** 回放 */
- (void)jsPlayVideo:(NSString *)JSONString {
if (![JSONString isNonEmpty]) {
[self toast:@"视频无法播放"];
return;
}
NSData *data = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:NULL];
NSString *playFrom = jsonDict[@"page_name"];
NSString *topicId = jsonDict[@"topic_id"];
NSString *businessId = jsonDict[@"business_id"];
NSString *cardType = jsonDict[@"card_type"];
NSInteger index = [jsonDict[@"index"] integerValue];
CGFloat currentTime = [jsonDict[@"currentTime"] floatValue];
NSInteger state = [jsonDict[@"state"] integerValue];
GMVideoObject *video = [GMVideoObject new];
video.businessId = SafeString(businessId);
video.cardType = SafeString(cardType);
video.pageName = SafeString(playFrom);
_playBackView = [[GMPlayerView alloc] init];
_playBackView.topicId = SafeString(topicId);
_playBackView.from = SafeString(playFrom);
_playBackView.video = video;
_playBackView.needSkipSeconds = currentTime;
_playBackView.index = index;
_playBackView.playState = state;
NSString *playUrl = jsonDict[@"url"];
[_playBackView play:playUrl animationRect:CGRectZero];
}
/**
获取用户通讯录
@author zhaiguojun 16-09-21 in 6.3.2
@since 6.4.1
*/
- (void)jsGetAddressBook {
dispatch_async(dispatch_get_main_queue(), ^{
_manager = [GMAddressManager new];
[_manager getAddressBookAuthorization];
});
}
/**
弹出通讯录供用户选择
@author zhaiguojun 16-09-28 in 6.4.1
*/
- (void)jsChooseOneContactPerson:(NSString *)key {
_manager = [GMAddressManager new];
__weak __typeof(self)weakSelf = self;
_manager.getOneContactPersonBlock = ^(NSDictionary *result){
NSData *jsParamData = [NSJSONSerialization dataWithJSONObject:@{key:result} options:0 error:NULL];
NSString *jsParam = [[NSString alloc] initWithData:jsParamData encoding:NSUTF8StringEncoding];
NSString *jsString = [NSString stringWithFormat:@"gm.util.setContactPerson('%@')",jsParam];
[weakSelf.webCompent.webView evaluateJavaScript:jsString completionHandler:nil];
};
[_manager chooseContactPersonAddressBookJsonString];
}
#pragma mark - AlertView
- (void)jsShowTaskAlert:(NSString *)extra {
NSData *data = [extra dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *extraDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
if (extraDic == nil) {
return;
}
[AppDelegate.shareInstance showPointAlert:extraDic];
}
- (void)jsShowAlertViewWithJSONString:(NSString *)JSONString {
WMAlertParameterObject *object = nil;
if ([JSONString isNonEmpty]) {
object = [[WMAlertParameterObject alloc] initWithString:JSONString error:nil];
}
__weak typeof(self)weakSelf = self;
NSString *title = object.title?:@"标题";
NSString *content = object.content?:@"内容";
NSString *confirmText = object.confirmText?:@"确定";
NSString *confirmCallback = object.confirmCallback?:@"";
UIAlertController *alert = [UIAlertController showCustomAlertWithTitle:title message:content];
[alert addAction:confirmText actionHandler:^{
[weakSelf.webCompent.webView evaluateJavaScript:confirmCallback completionHandler:nil];
}];
}
- (void)jsShowConfirmViewWithJSONString:(NSString *)JSONString{
WMAlertParameterObject *object = nil;
if ([JSONString isNonEmpty]) {
object = [[WMAlertParameterObject alloc] initWithString:JSONString error:nil];
}
NSString *title = object.title?:@"标题";
NSString *content = object.content?:@"内容";
NSString *confirmText = object.confirmText?:@"确定";
NSString *cancelText = object.cancelText?:@"取消";
NSString *confirmCallback = object.confirmCallback?:@"";
NSString *cancelCallback = object.cancelCallback?:@"";
__weak typeof(self)weakSelf = self;
UIAlertController *alert = [UIAlertController showCustomAlertWithTitle:title message:content];
[alert addAction:confirmText actionHandler:^{
[weakSelf.webCompent.webView evaluateJavaScript:confirmCallback completionHandler:nil];
}];
[alert addAction:cancelText actionHandler:^{
[weakSelf.webCompent.webView evaluateJavaScript:cancelCallback completionHandler:nil];
}];
}
- (void)jsShowToastWithJSONString:(NSString *)JSONString{
WMToastParameterObject *object = nil;
if ([JSONString isNonEmpty]) {
object = [[WMToastParameterObject alloc] initWithString:JSONString error:nil];
}
[self toast:SafeValue(object.text)];
}
#pragma mark - JumpToOtherPage
- (void)jsOpenBrowser:(NSString *)url{
UIAlertController *alert = [UIAlertController showCustomAlertWithTitle:@"提示" message:@"你访问的网址将以外部浏览器打开,是否继续?"];
[alert addAction:@"否" actionHandler:nil];
[alert addAction:@"是" actionHandler:^{
NSURL *browserUrl = [NSURL URLWithString:url];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[[UIApplication sharedApplication] openURL:browserUrl options:@{} completionHandler:NULL];
} else {
[[UIApplication sharedApplication] openURL:browserUrl];
}
}];
}
// 调起第三方APP 比如 爱奇艺 7.15.1
- (void)jsSkipToThirdApp:(NSString *)jsonString {
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
NSURL *url = [NSURL URLWithString:dic[@"target_url"]];
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:NULL];
} else {
[[UIApplication sharedApplication] openURL:url];
}
}
// 跳转到设置页面
- (void)jsJumpToLocationSettings {
[GMLocationManager jumpToSettings];
}
// 调用打电话
- (void)jsCallPhone:(NSString *)phone {
NSString *phoneStr = [NSString stringWithFormat:@"tel:%@",phone];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: phoneStr]];
}
// 发短信
- (void)jsSendMessage:(NSString *)phone withBody:(NSString *)body {
if ([GMMessageController canSendText]) {
GMMessageController *messageVc = [[GMMessageController alloc] init];
messageVc.messageComposeDelegate = self;
messageVc.recipients = @[phone];
messageVc.body = body;
#warning ios 13
messageVc.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:messageVc animated:YES completion:nil];
} else {
[self toast:@"当前设备不支持发短信"];
}
}
/*!
* @author zhaiguojun, 16-07-05
*
* @brief 选择图片上传,然后把返回的URL返回给前端
*
* @param requestCode 传过来的标识
*
* @since 6.2.0
*/
- (void)openAlbum:(NSString *)requestCode isPrivate:(BOOL)isPrivate{
_requestCoder = requestCode;
_isPrivatePhoto = isPrivate;
GMPhotoPickController *controller = [[GMPhotoPickController alloc] initWithMaxImageCount:1 maxVideoCount:0 maxCount:1 photoDisplayType:GMPhotosDisplayImageType];
controller.dismissDelegate = self;
controller.root.singleSelection = YES;
#warning ios 13
controller.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:controller animated:YES completion:NULL];
}
- (void)hintGotoSetting {
UIAlertAction *action = [UIAlertAction actionWithTitle:@"我知道了" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *gotoAction = [UIAlertAction actionWithTitle:@"去设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[self goToAppSystemSettings];
}];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请您先去设置允许APP访问您的相机 设置>隐私>相机" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:action];
[alert addAction:gotoAction];
[self presentViewController:alert animated:YES completion:nil];
}
/// 保险状态返回
/// @param dict has_bought: true(确定购买) / false(取消购买)
- (void)jsInsurancePurchase:(NSDictionary *)dict {
//可以考虑废弃 在GMInsuranceWebviewController做了处理 避免其他类用到这个方法因此先保存着
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:REFRESH_SETTLEMENT_LIST object:nil userInfo: dict];
[self.navigationController popViewControllerAnimated:YES];
});
}
#pragma mark - MFMessageComposeViewControllerDelegate
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
[controller dismissViewControllerAnimated:true completion:nil];
}
#pragma mark - local Data
- (void)jsSetLocalStorage:(NSString *)key withStorage:(NSString *)value {
if (![value isNonEmpty]) {
value = @"";
}
[GMCache storeObjectAtDocumentPathWithkey:key object:value];
}
- (NSString *)jsGetLocalStorage:(NSString *)key {
NSString *cacheKey = [GMCache fetchObjectAtDocumentPathWithkey:key];
#warning h5
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('getLocalStorage',%@)",cacheKey];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
if (![cacheKey isNonEmpty]) {
return @"";
}
return cacheKey;
}
- (void)jsSyncSSOInfo:(NSString *)jsonString {
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
if (info[@"user_id"] != nil) {
[[GMLoginManager shareInstance] loginSuccessWithUserInfo:info shouldBroadcast:NO];
}
if (info[@"cookie"] != nil && info[@"domain"] != nil) {
[GMCookieManager saveSessionId:info[@"cookie"] domain:info[@"domain"]];
}
}
- (void)jsNewbieCouponGot:(NSInteger)flag {
[GMCache storeObjectAtMemoryWithkey:kNewUserTicketHasGot object:@(flag)];
}
/**
* @author wangjun, 16-07-04 14:07:51
*
* 秒杀页面添加到系统日历事件
* @param jsonString H5传来的的美购信息
*/
- (void)jsRemindEvent:(NSString *)jsonString {
NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:NULL];
NSInteger beginTime = [json[@"start_time"] longValue];
NSInteger endTime = [json[@"end_time"] longValue];
NSString *title = json[@"title"];
NSString *url = json[@"url"];
NSString *serviceId = json[@"service_id"];
BOOL notify = [json[@"notify"] boolValue];
GMCalendarEventManager *manager = [[GMCalendarEventManager alloc] init];
__weak typeof(manager) weakManager = manager;
manager.authorizationAllowed = ^{
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[@"service_id"] = serviceId;
//7.3.0修改,@王成亮
[Phobos track:@"activity_promotion_seckill_notice" attributes:param];
[weakManager addEvent: title startDate: beginTime endDate: endTime serviceId: serviceId url: url];
};
if ([manager checkAuthorized]) {
if (notify) {
//添加提醒
NSMutableDictionary *param = [NSMutableDictionary dictionary];
param[@"service_id"] = serviceId;
[Phobos track:@"activity_promotion_seckill_notice" attributes:param];
[manager addEvent: title startDate: beginTime endDate: endTime serviceId: serviceId url: url];
} else {
//取消提醒
[manager removeEvent: serviceId];
}
}
}
/// 使用前端指定的颜色覆盖导航栏。默认只按照导航栏的高度进行覆盖。
/// 如果要自定义覆盖范围,可以完全重写这个方法
/// @param data 前端传过来的参数
- (void)showClientShadow:(NSDictionary *)data {
int isShow = [data[@"isShow"] intValue];
// color 的 value格式:“RGB,A”,并且每一位都是16进制
NSArray *colors = [data[@"color"] componentsSeparatedByString:@","];
if (isShow && colors.count == 2) {
self.navigationBar.isShowShadow = NO;
GMView *view = [[GMView alloc] initWithFrame:CGRectMake(0, 0, MAINSCREEN_WIDTH, OCNavigationBar.barHeight)];
[self.view addSubview:view];
view.tag = 2891;
CGFloat alpha = [colors.lastObject integerValue]/255.0;
view.backgroundColor = [UIColor colorWithHex:[colors.firstObject integerValue] alpha:alpha];
} else {
self.navigationBar.isShowShadow = YES;
[[self.view viewWithTag:2891] removeFromSuperview];
}
}
- (BOOL)jsIsLocationEnable {
BOOL isLocation = [GMLocationManager hasOpenLocationService];
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('isLocationEnableCallback',%d)",isLocation];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
return isLocation;
}
#pragma mark - 导航栏按键响应
- (void)backAction:(OCNavigationBarButton *)button {
// 目前只有签到页面和获取列表支持返回拦截,后续建议逐渐删除
if ([_jsGlobalObject[@"page_name"] isEqualToString:@"activity_list"]) {
[self.webCompent.webView evaluateJavaScript:@"window.gm.pack.run('activityListBack')" completionHandler:nil];
}
[self nativeBackToCallJS];
// 由前端控制当前页面的返回事件是否需要拦截
if (![_jsGlobalObject.allKeys containsObject:@"back_call"] ||
![_jsGlobalObject[@"back_call"] boolValue]) {
[super backAction:button];
}
}
- (void)rightButtonClicked:(OCNavigationBarButton *)button {
[super rightButtonClicked:button];
// 隐藏键盘,避免不必要的bug发生
[self.view endEditing:YES];
if (_isSign) {
return;
}
// 显示分享
if (_isShowShare) {
// self.shareView = nil 这句话不能删除。删除了会导致 shareView 的背景消失
self.shareView = nil;
[self.shareView showWithShareUrl:self.shareObject.url];
}
/*
统计预告分享pv uv(device)。另外数据端还可以利用这个做其它统计。in 7.0.5
*/
if ([self.pageName isNonEmpty] && _isShowShare) {
NSDictionary *dic = @{@"business_id": self.businessId,
@"page_name": self.pageName,
@"referrer": self.referer};
[Phobos track:@"on_click_common_webview_share" attributes:dic];
}
// 没有分享,只显示了一个JS_Button
if (!_isShowShare && _isJsRightButton) {
NSString *jumpURL = _jsGlobalObject[@"right_button"][@"url"];
NSString *jsFunction = _jsGlobalObject[@"right_button"][@"js_function"];
if ([jumpURL isNonEmpty]) {
[[GMRouter sharedInstance] pushScheme:jumpURL];
}
if ([jsFunction isNonEmpty]) {
[self.webCompent.webView evaluateJavaScript:jsFunction completionHandler:nil];
}
}
// 口红王子投票活动
if ([_jsGlobalObject[@"navigation"][@"right_action"] isNonEmpty]) {
NSString *rightAction = _jsGlobalObject[@"navigation"][@"right_action"];
[self.webCompent.webView evaluateJavaScript:rightAction completionHandler:nil];
}
}
- (void)nearRightButtonClicked:(OCNavigationBarButton *)button {
[super nearRightButtonClicked:button];
if (_isShowShare && _isJsRightButton) {
NSString *jumpURL = _jsGlobalObject[@"right_button"][@"url"];
NSString *jsFunction = _jsGlobalObject[@"right_button"][@"js_function"];
if ([jumpURL isNonEmpty]) {
[[GMRouter sharedInstance] pushScheme:jumpURL];
}
if ([jsFunction isNonEmpty]) {
[self.webCompent.webView evaluateJavaScript:jsFunction completionHandler:nil];
}
}
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (_isNavigationAlpha) {
// animationDistance 为0时表示header_height值在h5端还未确认
if (self.animationDistance > 0) {
[self animationBar:self.navigationBar withScrollView:scrollView];
} else {
CGFloat headerHeight = [_jsGlobalObject[@"header_height"] floatValue];
// 如果header_height不为0,表示图片大小已经确定,
if (headerHeight != 0) {
self.animationDistance = headerHeight - OCNavigationBar.barHeight;
}
}
CGFloat alpha = [self animationBar:self.navigationBar withScrollView:scrollView];
if (_isSign) {
// 签到 rightButton不隐藏ase
CGFloat offsetY = self.contentOffsetY > 0 ? self.contentOffsetY : scrollView.contentOffset.y;
self.navigationBar.rightButton.hidden = NO;
self.navigationBar.titleLabel.hidden = NO;
if (offsetY > [_jsGlobalObject[@"header_height"] floatValue] - OCNavigationBar.statusBarHeight) {
self.navigationBar.titleLabel.textColor = [UIColor colorWithWhite:0 alpha:alpha];
self.navigationBar.rightIconURL = _jsGlobalObject[@"navigation"][@"right_scrolled_button"];
self.navigationBar.leftIcon = @"back";
} else {
self.navigationBar.titleLabel.textColor = [UIColor whiteColor];
self.navigationBar.rightIconURL = _jsGlobalObject[@"navigation"][@"right_button"];
self.navigationBar.leftIcon = @"backWhite";
}
} else {
self.navigationBar.rightButton.hidden = !(alpha == 1);
}
}
}
- (void)showReport{
[self showComplete:@"举报成功,所长会尽快处理哒"];
}
/**
粘贴邀请好友口令到粘贴板
@param boardText 粘贴板文字
*/
- (void)jsClipboard:(NSString *)boardText {
UIPasteboard *board = [UIPasteboard generalPasteboard];
board.string = boardText;
[self toast:@"复制成功"];
}
#pragma mark - GMPhotoPickDismissDelegate
- (void)dismissPhotoPick:(NSArray<GMEditPhotoInfo *> *)infos{
if (infos.count == 0) {
return ;
}
GMEditPhotoInfo *model = infos.firstObject;
UIImage *image = model.finshedImage;
NSString *remoteUrl = _isPrivatePhoto ? API_UPLOAD_IMAGE_SAFE : API_UPLOAD_IMAGE;
WMImageUploadOperation *operation = [[WMImageUploadOperation alloc]initWithImage:image url:remoteUrl withCompressionQuality:0.75];
[operation setImageUploadFinishBlock:^(NSDictionary *JSON) {
NSString *publicUrl = @"";
NSString *jsParam = @"";
if (_isPrivatePhoto) {
publicUrl = JSON[@"data"][@"public_url"];
NSString *privateUrl = JSON[@"data"][@"private_url"];
if ([publicUrl isNonEmpty] && [privateUrl isNonEmpty]) {
NSDictionary *data = @{_requestCoder : @{@"private_url": privateUrl, @"public_url" : publicUrl}};
NSData *jsParamData = [NSJSONSerialization dataWithJSONObject:data options:0 error:NULL];
jsParam = [[NSString alloc] initWithData:jsParamData encoding:NSUTF8StringEncoding];
}
} else {
publicUrl = JSON[@"data"][@"public_url"];
NSDictionary *data = @{_requestCoder : @{@"public_url" : publicUrl}};
NSData *jsParamData = [NSJSONSerialization dataWithJSONObject:data options:0 error:NULL];
jsParam = [[NSString alloc] initWithData:jsParamData encoding:NSUTF8StringEncoding];
}
NSString *jsString = [NSString stringWithFormat:@"gm.util.setPageData('%@')",jsParam];
[self.webCompent.webView evaluateJavaScript:jsString completionHandler:nil];
}];
[operation startUpload];
}
// 签到页弹窗提示后,点击不再提醒会调用
- (void)jsSignNeverNotify {
[self.navigationController popViewControllerAnimated:YES];
}
- (int)jsIsUserLogin {
int isLogin = GMLoginManager.shareInstance.isVisitor ? 0 : 1;
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('isUserLoginCallback',%d)",isLogin];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
return isLogin;
}
// js 获取NativeData数据
- (NSString *)jsNativeDataLoaded {
NSString *trackerJson = [self nativeCommonParam];
if ([trackerJson isNonEmpty]) {
NSString *jsonStr = [NSString stringWithFormat:@"window.gm.pack.run('setNativeDataLoaded','%@')",trackerJson];
[self.webCompent.webView evaluateJavaScript:jsonStr completionHandler:nil];
return trackerJson;
}
return @"";
}
// 本地获取通用数据
- (NSString *)nativeCommonParam {
NSMutableDictionary *param = [NSMutableDictionary dictionaryWithDictionary:[NSDictionary trackerPageParam:self]];
[param setValue:SafeString(@(OCNavigationBar.barHeight)) forKey:@"title_bar_height"];
[param setValue:(self.referrerLink ? : @[]) forKey:@"referrer_link"];
// 仅当 cpc_referer 不为none时候传递此参数
if (self.cpc_referer != GMCpcNone) {
[param setValue:SafeString(@(self.is_cpc)) forKey:@"is_cpc"];
[param setValue:SafeString(@(self.cpc_referer)) forKey:@"cpc_referer"];
}
NSData *referrerData = [NSJSONSerialization dataWithJSONObject:param options:0 error:NULL];
NSString *trackerJson = [[NSString alloc] initWithData:referrerData encoding:NSUTF8StringEncoding];
if ([trackerJson isNonEmpty]) {
return trackerJson;
}
return @"";
}
- (NSString *)jsInflateUserInfo {
NSDictionary *userDic = @{@"user_id":@([GMLoginManager shareInstance].user.userId), @"user_name":SafeString([GMLoginManager shareInstance].user.nickName)};
NSData *userData = [NSJSONSerialization dataWithJSONObject:userDic options:0 error:NULL];
NSString *userParam = [[NSString alloc] initWithData:userData encoding:NSUTF8StringEncoding];
NSString *js = [NSString stringWithFormat:@"window.gm.pack.run('setInflateUserInfo',%@)",userParam];
[self.webCompent.webView evaluateJavaScript:js completionHandler:nil];
return userParam;
}
- (void)jsShowActionSheet:(NSString *)jsonString {
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] options: NSJSONReadingAllowFragments error:nil];
if (jsonArray.count <= 0) {
return;
}
GMActionSheet *alertView = [[GMActionSheet alloc] init];
// 回复弹窗内容和回调方法
for (NSDictionary *dic in jsonArray) {
GMActionSheetItemType type;
if ([dic[@"title"] isEqualToString:@"取消"]) {
type = GMActionSheetItemTypeCancel;
[alertView addItemWithTitle:dic[@"title"] style:type color:UIColor.headlineText handle:nil];
} else {
__weak __typeof(self)weakSelf = self;
type = GMActionSheetItemTypeDefault;
[alertView addItemWithTitle:dic[@"title"] style:type color:UIColor.headlineText handle:^(NSInteger index) {
NSDictionary *className = jsonArray[index];
NSString *js = [NSString stringWithFormat:@"window.gm.pack.run('%@')", SafeString(className[@"callback"])];
[weakSelf.webCompent.webView evaluateJavaScript:js completionHandler:nil];
}];
}
}
[alertView show];
}
- (void)jsRightbuttonCallBack:(NSString *)json {
NSData *jsonData = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
self.navigationBar.rightIconURL = dict[@"icon_url"];
}
- (int)jsNavigationbarHeight {
float barH = OCNavigationBar.barHeight;
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('navigationbarHeightCallback',%f)",barH];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
return OCNavigationBar.barHeight;
}
- (void)jsCheckAuthority:(NSString *)jsonString {
[AppDelegate.shareInstance userIsAllowPush:^(BOOL status) {
if (!status) {
_isSettingCallback = YES;
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
GMCommonAlertView *alertView = [[GMCommonAlertView alloc] init];
alertView.titleLabel.text = dict[@"title"];
alertView.subLabel.text = dict[@"tip"];
[alertView.button1 setTitle:dict[@"openName"] forState:UIControlStateNormal];
[alertView.button2 setTitle:dict[@"cancelName"] forState:UIControlStateNormal];
alertView.button3.hidden = YES;
self.settingType = [dict[@"type"] integerValue];
alertView.delegate = self;
[alertView show];
} else {
[self excuteSettingCallback:YES];
}
}];
}
- (void)didClickCommonAlertWithButtonIndex:(NSInteger)buttonIndex alertView:(GMCommonAlertView *)alertView {
[alertView dismiss];
if (buttonIndex == 1) {
//打开
[self goToAppSystemSettings];
self.goToAppSettingsPage = YES;
} else if (buttonIndex == 2) {
[self excuteSettingCallback:NO];
}
}
- (void)excuteSettingCallback:(BOOL)setting {
NSString *javaScriptStr = [NSString stringWithFormat:@"window.gm.pack.run('settingCallback',%d)",setting];
[self.webCompent.webView evaluateJavaScript:javaScriptStr completionHandler:nil];
}
#pragma mark - Native Call JS
/// Native 告知 H5页面展现
- (void)nativeAppearToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm&&window.gm.pack&&window.gm.pack.run('appear')" completionHandler:nil];
}
/// Native 告知 H5页面不可见
- (void)nativeDisAppearToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm&&window.gm.pack&&window.gm.pack.run('disappear')" completionHandler:nil];
}
/// Native 告知 H5返回执行
- (void)nativeBackToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm.pack.run('backAction')" completionHandler:nil];
}
/// Native 告知 H5取消登录
- (void)nativeLoginCancelToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm.pack.run('loginCancel')" completionHandler:nil];
}
/// Native 告知 H5进入后台
- (void)nativeEnterBackgroundToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm.pack.run('enterBackground')" completionHandler:nil];
}
/// Native 告知 H5进入前台
- (void)nativeEnterForgroundToCallJS {
[self.webCompent.webView evaluateJavaScript:@"window.gm.pack.run('enterForground')" completionHandler:nil];
}
#pragma mark - 埋点
/*** type由h5负责,所有h5埋点的方法都走这里 */
- (void)jsTrackEvent:(NSString *)JSONString {
@try {
NSData *data = [JSONString dataUsingEncoding:NSUnicodeStringEncoding];
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
id pa = dict[@"params"];
BOOL sendNow = [dict[@"nowSend"] boolValue];
NSDictionary *json;
if (pa != nil) {
if ([pa isKindOfClass:[NSString class]]) {
NSError *jsonError;
NSData *objectData = [pa dataUsingEncoding:NSUTF8StringEncoding];
json = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
[Phobos track:dict[@"type"] attributes:json sendNow:sendNow];
}else{
[Phobos track:dict[@"type"] attributes:dict[@"params"] sendNow:sendNow];
}
} else {
[Phobos track:dict[@"type"] attributes:@{} sendNow:sendNow];
}
}
@catch (NSException *exception) {
debugLog(@"exception:%@",exception);
}
}
/*** 精准曝光 */
- (void)jsHybridExposure:(NSString *)JSONString {
@try {
NSData *data = [JSONString dataUsingEncoding:NSUnicodeStringEncoding];
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
if (dict) {
[Phobos track:@"page_precise_exposure" attributes:dict sendNow:YES currentAPI:GMExactExposureApi];
}
}
@catch (NSException *exception) {
debugLog(@"exception:%@",exception);
}
}
#pragma mark - notification
- (void)addActiveObserver {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didBecomeActive)
name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willResignActive)
name:UIApplicationWillResignActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loginCancelNotification)
name:LOGIN_CANCEL_NOTIFICATION object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(enterBackground)
name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(enterForground)
name:UIApplicationWillEnterForegroundNotification object:nil];
}
- (void)enterBackground {
[self nativeEnterBackgroundToCallJS];
}
- (void)enterForground {
[self nativeEnterForgroundToCallJS];
}
- (void)willResignActive {
// 活动页面
if ([_jsGlobalObject[@"page_name"] isEqualToString:@"activity_list"]) {
[self nativeDisAppearToCallJS];
}
}
- (void)didBecomeActive {
if ([_jsGlobalObject[@"page_name"] isEqualToString:@"activity_list"]) {
[self nativeAppearToCallJS];
}
// 前往设置页面后 回到当前页面需要告知前端状态,前端会直接弹出“开抢提醒”弹框
if (self.goToAppSettingsPage) {
[AppDelegate.shareInstance userIsAllowPush:^(BOOL status) {
[self excuteSettingCallback:status];
// 返回app的时候把数据清空了,所以延迟3秒执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 获取通知权限浮层页授权按钮点击(需要获取授权状态)
[Phobos track:@"authority_page_click" attributes:@{@"user_id":@([GMLoginManager shareInstance].user.userId), @"authority_type":@(status)}];
});
}];
}
// 由于秒杀专场使用了common_webivew协议,所以这段逻辑不得不放到这个controller里,并且添加相关页面的判断
// 秒杀专场的url activity/promotion/1024/seckill
// 美购专题的url special_promotion
if ([_jsGlobalObject[@"is_seckill"] boolValue] && [GMLocationManager hasOpenLocationService] &&
[GMLocationManager shareInstance].statusWhenAppBackground != [CLLocationManager authorizationStatus]) {
/*
当系统地理位置权限改变后再回到app时,需要刷新webview,也就是说要重新确认 is_location_enable 参数的状态
由于先前使用的是query的方式来取得该参数,导致在webView.refresh时,该参数状态还是原来的状态,并没有改变
所以采取了下面强制webview重新loadRequest
由于是又加载了一个页面,在后退时webView是内部后退,而不是controller后退,所以又得重写 backAction 方法
如果h5方便的时候,将 is_location_enable 改为js主动获取,而不是使用query参数,这样更灵活。
*/
[self webViewLoadRequest];
}
}
// 用户取消登录通知
- (void)loginCancelNotification {
[self nativeLoginCancelToCallJS];
}
#pragma mark - lazy loading
- (GMWebViewComponent *)webCompent {
if (!_webCompent) {
_webCompent = [GMWebViewComponent new];
_webCompent.delegate = self;
_webCompent.clientH5Object.delegate = self;
}
if (!_webCompent.superview) {
[self.view addSubview:_webCompent];
}
return _webCompent;
}
- (GMShareView *)shareView{
if (!_shareView) {
_shareView = [[GMShareView alloc] init];
_shareView.delegate = self;
}
return _shareView;
}
- (GMDiaryShareView *)diaryShareView {
if (!_diaryShareView) {
_diaryShareView = [[GMDiaryShareView alloc] init];
_diaryShareView.delegate = self;
}
return _diaryShareView;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
// 在某些情况下,如果controller先dealloc了,会导致webView找不到delegate而crash。例如修复jspatch与webview冲突时就会遇到。
// 复现步骤:先注释以下代码,再push到一个webController,加载时立即后退,等待,然后crash,提示 “webView:identifierForInitialRequest:fromDataSource”
_webCompent.delegate = nil;
[_webCompent.webView stopLoading];
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment