2019-11-28 17:41:12 +08:00
|
|
|
/*
|
|
|
|
* Copyright [2019] [Doric.Pub]
|
|
|
|
*
|
|
|
|
* Licensed 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.
|
|
|
|
*/
|
2019-11-26 20:15:16 +08:00
|
|
|
//
|
|
|
|
// Created by pengfei.zhou on 2019/11/26.
|
|
|
|
//
|
|
|
|
|
|
|
|
#import "DoricRefreshableNode.h"
|
|
|
|
#import "Doric.h"
|
|
|
|
|
2019-11-27 11:55:49 +08:00
|
|
|
@interface DoricRefreshableNode () <DoricSwipePullingDelegate>
|
2019-11-26 20:15:16 +08:00
|
|
|
@property(nonatomic, strong) DoricViewNode *contentNode;
|
|
|
|
@property(nonatomic, copy) NSString *contentViewId;
|
|
|
|
@property(nonatomic, strong) DoricViewNode *headerNode;
|
|
|
|
@property(nonatomic, copy) NSString *headerViewId;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation DoricRefreshableNode
|
|
|
|
- (DoricSwipeRefreshLayout *)build {
|
2019-11-27 11:55:49 +08:00
|
|
|
return [[DoricSwipeRefreshLayout new] also:^(DoricSwipeRefreshLayout *it) {
|
|
|
|
it.swipePullingDelegate = self;
|
|
|
|
}];
|
2019-11-26 20:15:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendView:(DoricSwipeRefreshLayout *)view forPropName:(NSString *)name propValue:(id)prop {
|
|
|
|
if ([@"content" isEqualToString:name]) {
|
|
|
|
self.contentViewId = prop;
|
|
|
|
} else if ([@"header" isEqualToString:name]) {
|
|
|
|
self.headerViewId = prop;
|
|
|
|
} else if ([@"onRefresh" isEqualToString:name]) {
|
|
|
|
__weak typeof(self) _self = self;
|
|
|
|
NSString *funcId = prop;
|
|
|
|
self.view.onRefreshBlock = ^{
|
|
|
|
__strong typeof(_self) self = _self;
|
|
|
|
[self callJSResponse:funcId, nil];
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
[super blendView:view forPropName:name propValue:prop];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (DoricViewNode *)subNodeWithViewId:(NSString *)viewId {
|
|
|
|
if ([viewId isEqualToString:self.contentViewId]) {
|
|
|
|
return self.contentNode;
|
|
|
|
} else if ([viewId isEqualToString:self.headerViewId]) {
|
|
|
|
return self.headerNode;
|
|
|
|
} else {
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-08 11:57:38 +08:00
|
|
|
- (void)afterBlended:(NSDictionary *)props {
|
2019-11-26 20:15:16 +08:00
|
|
|
[self blendContent];
|
2019-11-28 10:28:24 +08:00
|
|
|
[self blendHeader];
|
2019-11-26 20:15:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendContent {
|
|
|
|
NSDictionary *contentModel = [self subModelOf:self.contentViewId];
|
|
|
|
if (!contentModel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NSString *viewId = contentModel[@"id"];
|
|
|
|
NSString *type = contentModel[@"type"];
|
|
|
|
NSDictionary *childProps = contentModel[@"props"];
|
|
|
|
if (self.contentNode) {
|
|
|
|
if ([self.contentNode.viewId isEqualToString:viewId]) {
|
|
|
|
//skip
|
|
|
|
} else {
|
|
|
|
if (self.reusable && [type isEqualToString:self.contentNode.type]) {
|
|
|
|
[self.contentNode also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it blend:childProps];
|
|
|
|
}];
|
|
|
|
} else {
|
|
|
|
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it initWithSuperNode:self];
|
|
|
|
[it blend:childProps];
|
|
|
|
self.view.contentView = it.view;
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.contentNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it initWithSuperNode:self];
|
|
|
|
[it blend:childProps];
|
|
|
|
self.view.contentView = it.view;
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendHeader {
|
|
|
|
NSDictionary *headerModel = [self subModelOf:self.headerViewId];
|
|
|
|
if (!headerModel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NSString *viewId = headerModel[@"id"];
|
|
|
|
NSString *type = headerModel[@"type"];
|
|
|
|
NSDictionary *childProps = headerModel[@"props"];
|
|
|
|
if (self.headerNode) {
|
|
|
|
if ([self.headerNode.viewId isEqualToString:viewId]) {
|
|
|
|
//skip
|
|
|
|
} else {
|
|
|
|
if (self.reusable && [type isEqualToString:self.headerNode.type]) {
|
|
|
|
[self.headerNode also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it blend:childProps];
|
|
|
|
}];
|
|
|
|
} else {
|
|
|
|
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it initWithSuperNode:self];
|
|
|
|
[it blend:childProps];
|
|
|
|
self.view.headerView = it.view;
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.headerNode = [[DoricViewNode create:self.doricContext withType:type] also:^(DoricViewNode *it) {
|
|
|
|
it.viewId = viewId;
|
|
|
|
[it initWithSuperNode:self];
|
|
|
|
[it blend:childProps];
|
|
|
|
self.view.headerView = it.view;
|
|
|
|
}];
|
|
|
|
}
|
2020-04-08 15:20:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)requestLayout {
|
2020-04-08 11:57:38 +08:00
|
|
|
[self.view.headerView.doricLayout apply:self.view.frame.size];
|
2020-04-08 15:20:38 +08:00
|
|
|
self.view.headerView.bottom = 0;
|
|
|
|
self.view.headerView.centerX = self.view.width / 2;
|
|
|
|
[self.view.contentView.doricLayout apply:self.view.frame.size];
|
2019-11-26 20:15:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)blendSubNode:(NSDictionary *)subModel {
|
|
|
|
[[self subNodeWithViewId:subModel[@"id"]] blend:subModel[@"props"]];
|
|
|
|
}
|
2019-11-27 11:55:49 +08:00
|
|
|
|
|
|
|
- (void)startAnimation {
|
|
|
|
[self.headerNode callJSResponse:@"startAnimation", nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)stopAnimation {
|
|
|
|
[self.headerNode callJSResponse:@"stopAnimation", nil];
|
|
|
|
}
|
|
|
|
|
2019-12-02 21:01:34 +08:00
|
|
|
- (void)setPullingDistance:(CGFloat)distance {
|
|
|
|
[self.headerNode callJSResponse:@"setPullingDistance", @(distance), nil];
|
2019-11-27 11:55:49 +08:00
|
|
|
}
|
|
|
|
|
2019-11-27 13:30:31 +08:00
|
|
|
- (void)setRefreshing:(NSNumber *)refreshable withPromise:(DoricPromise *)promise {
|
|
|
|
self.view.refreshing = [refreshable boolValue];
|
2019-12-02 21:01:34 +08:00
|
|
|
[promise resolve:nil];
|
2019-11-27 13:30:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setRefreshable:(NSNumber *)refreshing withPromise:(DoricPromise *)promise {
|
|
|
|
self.view.refreshable = [refreshing boolValue];
|
|
|
|
[promise resolve:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSNumber *)isRefreshing {
|
|
|
|
return @(self.view.refreshing);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSNumber *)isRefreshable {
|
|
|
|
return @(self.view.refreshable);
|
|
|
|
}
|
2019-11-26 20:15:16 +08:00
|
|
|
@end
|