Skip to content

Commit

Permalink
Jwoo/ios render sync (microsoft#1547)
Browse files Browse the repository at this point in the history
* make rendering to be syncronoush by default

* updated custom textblock renderer

* changes before CR

* CR update

* CR update
  • Loading branch information
jwoo-msft committed Jun 7, 2018
1 parent 16f937b commit 07ba5eb
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 355 deletions.
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
6B7B1A9B20C21CA900260731 /* SportingEvent.json in Resources */ = {isa = PBXBuildFile; fileRef = 6B7B1A9920C21CA800260731 /* SportingEvent.json */; };
6B7B1A9C20C21CA900260731 /* NotificationCard.json in Resources */ = {isa = PBXBuildFile; fileRef = 6B7B1A9A20C21CA900260731 /* NotificationCard.json */; };
6BF339D620A665E600DA5973 /* CustomTextBlockRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6BF339D420A665E600DA5973 /* CustomTextBlockRenderer.mm */; };
6BF339E320A66A3F00DA5973 /* AdaptiveCards.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */; };
6BF339E420A66A4D00DA5973 /* AdaptiveCards.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
Expand Down Expand Up @@ -111,6 +113,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
6B7B1A9920C21CA800260731 /* SportingEvent.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = SportingEvent.json; path = ../../../../samples/v1.0/Scenarios/SportingEvent.json; sourceTree = "<group>"; };
6B7B1A9A20C21CA900260731 /* NotificationCard.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = NotificationCard.json; path = ../../../../samples/v1.0/Scenarios/NotificationCard.json; sourceTree = "<group>"; };
6BF339D420A665E600DA5973 /* CustomTextBlockRenderer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CustomTextBlockRenderer.mm; sourceTree = "<group>"; };
6BF339D520A665E600DA5973 /* CustomTextBlockRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomTextBlockRenderer.h; sourceTree = "<group>"; };
6BF339E220A66A3F00DA5973 /* AdaptiveCards.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = AdaptiveCards.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -309,6 +313,8 @@
F4D33E341F045B6E00941E44 /* Jsons */ = {
isa = PBXGroup;
children = (
6B7B1A9A20C21CA900260731 /* NotificationCard.json */,
6B7B1A9920C21CA800260731 /* SportingEvent.json */,
F4F44BA6204CF97100A2F24C /* CustomParsingTestUsingProgressBar.json */,
F4F44B842048CDB300A2F24C /* AdditionalProperty.json */,
F4F44B8220478E1100A2F24C /* DateTimeTestTranslation.json */,
Expand Down Expand Up @@ -481,10 +487,12 @@
F4933CC51F79852C00F6EBFD /* Action.Submit.json in Resources */,
F4933CED1F79852C00F6EBFD /* TextBlock.Weight.json in Resources */,
F4933D061F79853B00F6EBFD /* StockUpdate.json in Resources */,
6B7B1A9C20C21CA900260731 /* NotificationCard.json in Resources */,
F4933D081F79853B00F6EBFD /* WeatherLarge.json in Resources */,
F4933CCD1F79852C00F6EBFD /* ColumnSet.Spacing.json in Resources */,
F4933CC21F79852C00F6EBFD /* Action.OpenUrl.json in Resources */,
F4933CFE1F79853B00F6EBFD /* FlightItinerary.json in Resources */,
6B7B1A9B20C21CA900260731 /* SportingEvent.json in Resources */,
F4933CC81F79852C00F6EBFD /* Column.Style.json in Resources */,
F4F44B8320478E1100A2F24C /* DateTimeTestTranslation.json in Resources */,
F4933CE81F79852C00F6EBFD /* TextBlock.Markdown.json in Resources */,
Expand Down
Expand Up @@ -86,20 +86,12 @@ - (UIView *)render:(UIView<ACRIContentHoldingView> *)viewGroup
lab.numberOfLines = 1;
}

ACRContentHoldingUIView *wrappingview = [[ACRContentHoldingUIView alloc] init];

[wrappingview addSubview:lab];

[wrappingview setAlignmentForSubview:textBlockElement->GetHorizontalAlignment()];

[viewGroup addArrangedSubview:wrappingview];

wrappingview.translatesAutoresizingMaskIntoConstraints = false;
[viewGroup addArrangedSubview:lab];

wrappingview.backgroundColor = UIColor.lightGrayColor;
lab.backgroundColor = UIColor.lightGrayColor;

lab.translatesAutoresizingMaskIntoConstraints = false;

return wrappingview;
return lab;
}
@end
Expand Up @@ -218,16 +218,16 @@ - (void)update:(NSString *) jsonStr
[self.curView removeFromSuperview];

self.curView = ad;
if(_enableCustomRenderer){
[_scrView addSubview:self.curView];
UIView *view = self.curView;
view.translatesAutoresizingMaskIntoConstraints = NO;

[_scrView addSubview:self.curView];
UIView *view = self.curView;
view.translatesAutoresizingMaskIntoConstraints = NO;

[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0].active = YES;
}
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0].active = YES;

}
}

Expand Down Expand Up @@ -291,18 +291,6 @@ - (void)didFetchHttpRequest:(NSURLRequest *)request
NSLog(@"Http Request fetched: %@", request);
}

- (void)didLoadElements
{
[_scrView addSubview:self.curView];
UIView *view = self.curView;
view.translatesAutoresizingMaskIntoConstraints = NO;

[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0].active = YES;
[NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_scrView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0].active = YES;
}

- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
Expand Down
Expand Up @@ -27,7 +27,7 @@ + (UIButton* )rootView:(ACRView *)rootView
CGSize contentSize = [button.titleLabel intrinsicContentSize];
[button setFrame:CGRectMake(0, 0, contentSize.width, contentSize.height)];
[button setContentEdgeInsets:UIEdgeInsetsMake(5,5,5,5)];

std::shared_ptr<AdaptiveCards::BaseActionElement> action = [acoAction element];
if([iconUrl length] != 0)
{
Expand All @@ -47,18 +47,18 @@ + (UIButton* )rootView:(ACRView *)rootView
actionsViewMap[key] = button;
}
});

if(imgView)
{
{
[ACRView setImageView:imgView inButton:button withConfig:config];

// remove postfix added for imageMap access
std::string id = action->GetId();
std::size_t idx = id.find_last_of('_');
action->SetId(id.substr(0, idx));
}
}

return button;
}
@end
Expand Up @@ -39,22 +39,19 @@ + (ACRUILabel *)buildLabel:(NSString *)text
lab.isFactSetLabel = YES;
lab.translatesAutoresizingMaskIntoConstraints = NO;
lab.style = style;
__block NSMutableAttributedString *content = nil;
NSMutableAttributedString *content = nil;
if(rootView){
std::shared_ptr<FactSet> fctSet = std::dynamic_pointer_cast<FactSet>(element);
NSMutableDictionary *textMap = [rootView getTextMap];
// Syncronize access to imageViewMap
dispatch_sync([rootView getSerialTextQueue], ^{
if(textMap[elementId]) { // if content is available, get it, otherwise cache label, so it can be used used later
content = textMap[elementId];
} else {
textMap[elementId] = lab;
}
});
}

if(content){
NSDictionary* data = textMap[elementId];
NSData *htmlData = data[@"html"];
NSDictionary *options = data[@"options"];

std::shared_ptr<HostConfig> config = [acoConfig getHostConfig];
// Initializing NSMutableAttributedString for HTML rendering is very slow
content = [[NSMutableAttributedString alloc] initWithData:htmlData options:options documentAttributes:nil error:nil];
// Drop newline char
[content deleteCharactersInRange:NSMakeRange([content length] -1, 1)];
// Set paragraph style such as line break mode and alignment
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = textConfig.wrap ? NSLineBreakByWordWrapping:NSLineBreakByTruncatingTail;
Expand All @@ -70,7 +67,6 @@ + (ACRUILabel *)buildLabel:(NSString *)text
NSStrokeWidthAttributeName:[ACOHostConfig getTextStrokeWidthForWeight:textConfig.weight]}
range:NSMakeRange(0, content.length)];
lab.attributedText = content;

std::string ID = element->GetId();
std::size_t idx = ID.find_last_of('_');
if(std::string::npos != idx){
Expand Down
Expand Up @@ -58,51 +58,37 @@ - (UIView *)render:(UIView<ACRIContentHoldingView> *)viewGroup
constant:cgsize.height]]];
}
NSMutableDictionary *imageViewMap = [rootView getImageMap];
__block UIImage *img = nil;
// Generate key for ImageViewMap
NSString *key = [NSString stringWithCString:imgElem->GetId().c_str() encoding:[NSString defaultCStringEncoding]];
UIImage *img = nil;
// Syncronize access to imageViewMap
dispatch_sync([rootView getSerialQueue], ^{
// if image is available, get it, otherwise cache UIImageView, so it can be used once images are ready
if(imageViewMap[key] && [imageViewMap[key] isKindOfClass:[UIImage class]]) {
img = imageViewMap[key];
}
else {
imageViewMap[key] = view;
}
});
NSNumber *number = [NSNumber numberWithUnsignedLongLong:(unsigned long long)imgElem.get()];
NSString *key = [number stringValue];
img = imageViewMap[key];
view.image = img;
if(img && (img.size.width > 0) && (imgElem->GetImageSize() == ImageSize::Auto || imgElem->GetImageSize() == ImageSize::Stretch || imgElem->GetImageSize() == ImageSize::None)){
CGFloat heightToWidthRatio = img.size.height / img.size.width;
[view addConstraints:@[[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeWidth
multiplier:heightToWidthRatio
constant:0]]];
CGFloat widthToHeightRatio = img.size.width/ img.size.height;
[view addConstraints:@[[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeHeight
multiplier:widthToHeightRatio
constant:0]]];
}

if(img) {// if image is ready, proceed to add it
view.image = img;
if(imgElem->GetImageSize() == ImageSize::Auto || imgElem->GetImageSize() == ImageSize::Stretch || imgElem->GetImageSize() == ImageSize::None){
CGFloat heightToWidthRatio = img.size.height / img.size.width;
[view addConstraints:@[[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeWidth
multiplier:heightToWidthRatio
constant:0]]];
CGFloat widthToHeightRatio = img.size.width/ img.size.height;
[view addConstraints:@[[NSLayoutConstraint constraintWithItem:view
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:view
attribute:NSLayoutAttributeHeight
multiplier:widthToHeightRatio
constant:0]]];
}
view.contentMode = UIViewContentModeScaleAspectFit;
view.clipsToBounds = NO;
if(imgElem->GetImageStyle() == ImageStyle::Person) {
CALayer *imgLayer = view.layer;
[imgLayer setCornerRadius:cgsize.width/2];
[imgLayer setMasksToBounds:YES];
}
// remove postfix added for imageMap access
std::string id = imgElem->GetId();
std::size_t idx = id.find_last_of('_');
imgElem->SetId(id.substr(0, idx));
view.contentMode = UIViewContentModeScaleAspectFit;
view.clipsToBounds = NO;
if(imgElem->GetImageStyle() == ImageStyle::Person) {
CALayer *imgLayer = view.layer;
[imgLayer setCornerRadius:cgsize.width/2];
[imgLayer setMasksToBounds:YES];
}

ACRContentHoldingUIView *wrappingview = [[ACRContentHoldingUIView alloc] initWithFrame:view.frame];
Expand Down
Expand Up @@ -63,31 +63,29 @@ + (UIView *)renderWithAdaptiveCards:(std::shared_ptr<AdaptiveCard> const &)adapt
{
std::vector<std::shared_ptr<BaseCardElement>> body = adaptiveCard->GetBody();
ACRColumnView *verticalView = containingView;

if(!body.empty()) {
[rootView addTasksToConcurrentQueue:body];
// addTasksToConcurrentQueue spawns concurrent tasks, this flag indicates that
// all tasks have been added to work queues, and is needed for complete notification to work properly
rootView.seenAllElements = YES;

if(!body.empty()) {
ACRContainerStyle style = ([config getHostConfig]->adaptiveCard.allowCustomStyle)? (ACRContainerStyle)adaptiveCard->GetStyle() : ACRDefault;
style = (style == ACRNone)? ACRDefault : style;
[verticalView setStyle:style];

[rootView addTasksToConcurrentQueue:body];

[rootView waitForAsyncTasksToFinish];

[ACRRenderer render:verticalView rootView:rootView inputs:inputs withCardElems:body andHostConfig:config];

[[rootView card] setInputs:inputs];
[[rootView card] setInputs:inputs];

std::vector<std::shared_ptr<BaseActionElement>> actions = adaptiveCard->GetActions();
if(!actions.empty()) {
[rootView addActionsToConcurrentQueue:actions];
[ACRSeparator renderActionsSeparator:verticalView hostConfig:[config getHostConfig]];
// renders buttons and their associated actions
[ACRRenderer renderButton:rootView inputs:inputs superview:verticalView actionElems:actions hostConfig:config];
}
[verticalView adjustHuggingForLastElement];
}

return verticalView;
}

Expand Down

0 comments on commit 07ba5eb

Please sign in to comment.