blob: 4c95e511ce319ebae0d4c9478a2f74f298357838 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#import "WXEmbedComponent.h"
#import "WXComponent_internal.h"
#import "WXSDKInstance_private.h"
#import "WXComponent+Navigation.h"
#import "WXSDKInstance.h"
#import "WXSDKManager.h"
#import "WXConvert.h"
#import "WXUtility.h"
#import "WXApmForInstance.h"
@interface WXEmbedComponent ()
@property (nonatomic, strong) WXSDKInstance *embedInstance;
@property (nonatomic, strong) UIView *embedView;
@property (nonatomic, assign) BOOL createFinished;
@property (nonatomic, assign) BOOL renderFinished;
@property (nonatomic, assign) WXVisibility visible;
@property (nonatomic, strong) NSURL *sourceURL;
@property (nonatomic, strong) WXErrorView *errorView;
@end
@implementation WXEmbedComponent
#pragma mark Life Cycle
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
if (self.embedInstance) {
[self.embedInstance destroyInstance];
}
}
- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance
{
if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) {
_createFinished = NO;
_renderFinished = NO;
_sourceURL = [NSURL URLWithString: attributes[@"src"]];
_visible = [WXConvert WXVisibility:styles[@"visibility"]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(observeInstanceState:) name:WX_INSTANCE_NOTIFICATION_UPDATE_STATE object:nil];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self _layoutEmbedView];
}
- (void)updateStyles:(NSDictionary *)styles
{
[super updateStyles:styles];
if (styles[@"visibility"]) {
WXVisibility visible = [WXConvert WXVisibility:styles[@"visibility"]];
if (_visible != visible) {
_visible = visible;
[self _layoutEmbedView];
}
}
}
- (void)updateAttributes:(NSDictionary *)attributes
{
[super updateAttributes:attributes];
if (attributes[@"src"]) {
NSURL *sourceURL = [NSURL URLWithString:attributes[@"src"]];
if (!sourceURL|| ![[sourceURL absoluteString] isEqualToString:[_sourceURL absoluteString]]) {
_sourceURL = sourceURL;
_createFinished = NO;
[self _layoutEmbedView];
}
}
}
- (void)refreshWeex
{
[self _renderWithURL:_sourceURL];
}
- (void)_layoutEmbedView
{
if (_visible == WXVisibilityShow) {
[self _updateState:WeexInstanceAppear];
if (!_createFinished && !CGRectEqualToRect(CGRectZero, self.calculatedFrame)) {
[self _renderWithURL:_sourceURL];
}
}
else {
[self _updateState:WeexInstanceDisappear];
}
}
- (void)_renderWithURL:(NSURL *)sourceURL
{
if (!sourceURL || [[sourceURL absoluteString] length] == 0) {
return;
}
[_embedInstance destroyInstance];
_embedInstance = [[WXSDKInstance alloc] init];
_embedInstance.parentInstance = self.weexInstance;
_embedInstance.parentNodeRef = self.ref;
_embedInstance.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.width, self.view.frame.size.height);
_embedInstance.pageName = sourceURL.absoluteString;
_embedInstance.pageObject = self.weexInstance.viewController;
_embedInstance.viewController = self.weexInstance.viewController;
NSString *newURL = nil;
if ([sourceURL.absoluteString rangeOfString:@"?"].location != NSNotFound) {
newURL = [NSString stringWithFormat:@"%@&random=%d", sourceURL.absoluteString, arc4random()];
}
else {
newURL = [NSString stringWithFormat:@"%@?random=%d", sourceURL.absoluteString, arc4random()];
}
[_embedInstance renderWithURL:[NSURL URLWithString:newURL] options:@{@"bundleUrl":[sourceURL absoluteString]} data:nil];
[_embedInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_INSTANCE_TYPE withValue:@"embed"];
[_embedInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_PARENT_PAGE withValue:_embedInstance.parentInstance.pageName];
[self.weexInstance.apmInstance updateDiffStats:KEY_PAGE_STATS_EMBED_COUNT withDiffValue:1];
__weak typeof(self) weakSelf = self;
_embedInstance.onCreate = ^(UIView *view) {
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.errorView) {
[weakSelf.errorView removeFromSuperview];
weakSelf.errorView = nil;
}
[weakSelf.embedView removeFromSuperview];
weakSelf.embedView = view;
[weakSelf.view addSubview:weakSelf.embedView];
weakSelf.createFinished = YES;
});
};
_embedInstance.onFailed = ^(NSError *error) {
weakSelf.weexInstance.apmInstance.isDegrade = YES;
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.errorView) {
return ;
}
WXErrorView *errorView = [[WXErrorView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 135.0f, 130.0f)];
errorView.center = CGPointMake(weakSelf.view.bounds.size.width / 2.0f, weakSelf.view.bounds.size.height / 2.0f);
errorView.delegate = weakSelf;
[weakSelf.view addSubview:errorView];
weakSelf.errorView = errorView;
});
};
_embedInstance.renderFinish = ^(UIView *view) {
weakSelf.renderFinished = YES;
[weakSelf _updateState:WeexInstanceAppear];
};
}
- (void)_updateState:(WXState)state
{
if (_renderFinished && _embedInstance && _embedInstance.state != state) {
_embedInstance.state = state;
if (state == WeexInstanceAppear) {
[self setNavigationWithStyles:self.embedInstance.naviBarStyles];
[[WXSDKManager bridgeMgr] fireEvent:self.embedInstance.instanceId ref:WX_SDK_ROOT_REF type:@"viewappear" params:nil domChanges:nil];
}
else if (state == WeexInstanceDisappear) {
[[WXSDKManager bridgeMgr] fireEvent:self.embedInstance.instanceId ref:WX_SDK_ROOT_REF type:@"viewdisappear" params:nil domChanges:nil];
}
}
}
- (void)_frameDidCalculated:(BOOL)isChanged
{
[super _frameDidCalculated:isChanged];
self.embedInstance.frame = self.calculatedFrame;
}
- (void)onclickErrorView
{
if (self.errorView) {
[self.errorView removeFromSuperview];
self.errorView = nil;
}
[self _renderWithURL:self.sourceURL];
}
- (void)observeInstanceState:(NSNotification *)notification
{
WXSDKInstance *instance = notification.object;
if (instance == self.weexInstance) {
NSDictionary *userInfo = notification.userInfo;
WXState state = [userInfo[@"state"] integerValue];
if (_visible == WXVisibilityHidden) {
switch (state) {
case WeexInstanceBackground:
[self _updateState:WeexInstanceBackground];
break;
default:
[self _updateState:WeexInstanceDisappear];
break;
}
}
else {
[self _updateState:state];
}
}
}
@end