From a3121c4f6e7b918b44cba9d6c64f1b8b9a2569f2 Mon Sep 17 00:00:00 2001 From: nesalang Date: Mon, 20 Sep 2021 15:49:42 -0700 Subject: [PATCH 1/3] [iOS] Password implementation --- .../AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm index ffef0b9eeb..96b7d24029 100644 --- a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm +++ b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm @@ -65,6 +65,11 @@ + (ACRTextField *)configTextFiled:(std::shared_ptr const &)inputBlock txtInput = [bundle loadNibNamed:@"ACRTextUrlField" owner:rootView options:nil][0]; break; } + case TextInputStyle::Password: { + txtInput = [bundle loadNibNamed:@"ACRTextField" owner:rootView options:nil][0]; + txtInput.secureTextEntry = YES; + break; + } case TextInputStyle::Text: default: { txtInput = [bundle loadNibNamed:@"ACRTextField" owner:rootView options:nil][0]; @@ -74,6 +79,7 @@ + (ACRTextField *)configTextFiled:(std::shared_ptr const &)inputBlock txtInput.placeholder = [NSString stringWithCString:inputBlock->GetPlaceholder().c_str() encoding:NSUTF8StringEncoding]; txtInput.text = [NSString stringWithCString:inputBlock->GetValue().c_str() encoding:NSUTF8StringEncoding]; + txtInput.allowsEditingTextAttributes = YES; return txtInput; } From cb82de42c293f4ea94cc20a6748f961fe5807d2e Mon Sep 17 00:00:00 2001 From: nesalang Date: Fri, 24 Sep 2021 19:28:06 -0700 Subject: [PATCH 2/3] [iOS] Updated unit tests and added sample json --- .../Elements/Input.Text.PasswordStyle.json | 18 +++++ .../AdaptiveCards/ACRInputRenderer.mm | 8 +- .../AdaptiveCardsTests/AdaptiveCardsTests.mm | 76 +++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 samples/v1.5/Elements/Input.Text.PasswordStyle.json diff --git a/samples/v1.5/Elements/Input.Text.PasswordStyle.json b/samples/v1.5/Elements/Input.Text.PasswordStyle.json new file mode 100644 index 0000000000..c8acabdf0f --- /dev/null +++ b/samples/v1.5/Elements/Input.Text.PasswordStyle.json @@ -0,0 +1,18 @@ +{ + "type": "AdaptiveCard", + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.5", + "body": [ + { + "type": "TextBlock", + "text": "Input.Text With Password Style", + "wrap": true + }, + { + "type": "Input.Text", + "id": "id0", + "placeholder": "password", + "style": "password" + } + ] +} diff --git a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm index 96b7d24029..ab662d60ab 100644 --- a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm +++ b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCards/ACRInputRenderer.mm @@ -113,7 +113,9 @@ - (UIView *)render:(UIView *)viewGroup } ACRTextInputHandler *textInputHandler = [[ACRTextInputHandler alloc] init:acoElem]; - if (inputBlck->GetIsMultiline()) { + + BOOL isMultiline = (inputBlck->GetTextInputStyle() != TextInputStyle::Password) && inputBlck->GetIsMultiline(); + if (isMultiline) { if (renderAction) { // if action is defined, load ACRQuickReplyMultilineView nib for customizable UI multilineview = [[ACRQuickReplyMultilineView alloc] initWithFrame:CGRectMake(0, 0, viewGroup.frame.size.width, 0)]; @@ -171,7 +173,7 @@ - (UIView *)render:(UIView *)viewGroup [inputview setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; } - if (elem->GetHeight() == HeightType::Stretch && !inputBlck->GetIsMultiline()) { + if (elem->GetHeight() == HeightType::Stretch && !isMultiline) { ACRColumnView *textInputContainer = [[ACRColumnView alloc] init]; [textInputContainer addArrangedSubview:inputview]; @@ -189,7 +191,7 @@ - (UIView *)render:(UIView *)viewGroup // configures for action if (renderAction) { - if (inputBlck->GetIsMultiline()) { + if (isMultiline) { [inputs addObject:txtview]; } else { [inputs addObject:inputview]; diff --git a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCardsTests/AdaptiveCardsTests.mm b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCardsTests/AdaptiveCardsTests.mm index 726be92766..14e9ac9892 100644 --- a/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCardsTests/AdaptiveCardsTests.mm +++ b/source/ios/AdaptiveCards/AdaptiveCards/AdaptiveCardsTests/AdaptiveCardsTests.mm @@ -7,10 +7,18 @@ // #import "ACRContentHoldingUIView.h" +#import "ACOBaseCardElementPrivate.h" +#import "ACRRegistration.h" +#import "ACRBaseCardElementRenderer.h" #import "TextBlock.h" +#import "TextInput.h" +#import "ACRInputLabelView.h" +#import "ACRTextView.h" #import #import +using namespace AdaptiveCards; + @interface AdaptiveCardsTests : XCTestCase @end @@ -47,5 +55,73 @@ - (void)testContentHoldingUIViewWithImage XCTAssertEqualObjects(wrapperView.contentView, imageView); } +- (void)testPasswordStyleIsCorrectSet +{ + std::shared_ptr textInput = std::make_shared(); + textInput->SetTextInputStyle(TextInputStyle::Password); + ACOBaseCardElement *baseCardElement = [[ACOBaseCardElement alloc] initWithBaseCardElement:textInput]; + ACRRegistration *registration = [ACRRegistration getInstance]; + ACRBaseCardElementRenderer *renderer = [registration getRenderer:[NSNumber numberWithInt:ACRTextInput]]; + ACRColumnView *viewGroup = [[ACRColumnView alloc] init]; + ACRView *rootView = [[ACRView alloc] init]; + NSMutableArray *inputs = [[NSMutableArray alloc] init]; + ACOHostConfig *config = [[ACOHostConfig alloc] init]; + UIView *inputView = [renderer render:viewGroup rootView:rootView inputs:inputs + baseCardElement:baseCardElement + hostConfig:config]; + XCTAssertNotNil(inputView); + XCTAssertTrue([inputView isKindOfClass:[ACRInputLabelView class]]); + ACRInputLabelView *labelview = (ACRInputLabelView *)inputView; + XCTAssertNotNil(labelview.inputView); + XCTAssertTrue([labelview.inputView isKindOfClass:[UITextField class]]); + UITextField *textField = (UITextField *)labelview.inputView; + XCTAssertTrue(textField.isSecureTextEntry); +} + +- (void)testInputIsSetToACRTextViewWhenMultiline +{ + std::shared_ptr textInput = std::make_shared(); + textInput->SetIsMultiline(true); + ACOBaseCardElement *baseCardElement = [[ACOBaseCardElement alloc] initWithBaseCardElement:textInput]; + ACRRegistration *registration = [ACRRegistration getInstance]; + ACRBaseCardElementRenderer *renderer = [registration getRenderer:[NSNumber numberWithInt:ACRTextInput]]; + ACRColumnView *viewGroup = [[ACRColumnView alloc] init]; + ACRView *rootView = [[ACRView alloc] init]; + NSMutableArray *inputs = [[NSMutableArray alloc] init]; + ACOHostConfig *config = [[ACOHostConfig alloc] init]; + UIView *inputView = [renderer render:viewGroup rootView:rootView inputs:inputs + baseCardElement:baseCardElement + hostConfig:config]; + XCTAssertNotNil(inputView); + XCTAssertTrue([inputView isKindOfClass:[ACRInputLabelView class]]); + ACRInputLabelView *labelview = (ACRInputLabelView *)inputView; + XCTAssertNotNil(labelview.inputView); + XCTAssertTrue([labelview.inputView isKindOfClass:[ACRTextView class]]); +} + +- (void)testInputIsSetToACRTextFieldWhenMultilineAndPasswordStyleAreSet +{ + std::shared_ptr textInput = std::make_shared(); + textInput->SetIsMultiline(true); + textInput->SetTextInputStyle(TextInputStyle::Password); + ACOBaseCardElement *baseCardElement = [[ACOBaseCardElement alloc] initWithBaseCardElement:textInput]; + ACRRegistration *registration = [ACRRegistration getInstance]; + ACRBaseCardElementRenderer *renderer = [registration getRenderer:[NSNumber numberWithInt:ACRTextInput]]; + ACRColumnView *viewGroup = [[ACRColumnView alloc] init]; + ACRView *rootView = [[ACRView alloc] init]; + NSMutableArray *inputs = [[NSMutableArray alloc] init]; + ACOHostConfig *config = [[ACOHostConfig alloc] init]; + UIView *inputView = [renderer render:viewGroup rootView:rootView inputs:inputs + baseCardElement:baseCardElement + hostConfig:config]; + XCTAssertNotNil(inputView); + XCTAssertTrue([inputView isKindOfClass:[ACRInputLabelView class]]); + ACRInputLabelView *labelview = (ACRInputLabelView *)inputView; + XCTAssertNotNil(labelview.inputView); + XCTAssertTrue([labelview.inputView isKindOfClass:[UITextField class]]); + UITextField *textField = (UITextField *)labelview.inputView; + XCTAssertTrue(textField.isSecureTextEntry); +} + @end From de2b38bb0d87c3e4b0c076c83a116d091581b94e Mon Sep 17 00:00:00 2001 From: almedina-ms <35784165+almedina-ms@users.noreply.github.com> Date: Mon, 27 Sep 2021 14:39:44 -0700 Subject: [PATCH 3/3] Update Input.Text.PasswordStyle.json --- .../v1.5/Elements/Input.Text.PasswordStyle.json | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/samples/v1.5/Elements/Input.Text.PasswordStyle.json b/samples/v1.5/Elements/Input.Text.PasswordStyle.json index c8acabdf0f..d39f6e3d3d 100644 --- a/samples/v1.5/Elements/Input.Text.PasswordStyle.json +++ b/samples/v1.5/Elements/Input.Text.PasswordStyle.json @@ -3,16 +3,18 @@ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "version": "1.5", "body": [ - { - "type": "TextBlock", - "text": "Input.Text With Password Style", - "wrap": true - }, { "type": "Input.Text", "id": "id0", "placeholder": "password", - "style": "password" + "style": "password", + "label": "Input.Text With Password Style" + } + ], + "actions": [ + { + "type": "Action.Submit", + "title": "OK" } ] }