Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Update submit validation API #4876

Merged
merged 22 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a5476fd
Save Container Card Id in RenderArgs constructor
almedina-ms Sep 30, 2020
1716765
Merge branch 'main' of https://github.com/microsoft/AdaptiveCards int…
almedina-ms Oct 1, 2020
8240fa9
Merge branch 'main' of https://github.com/microsoft/AdaptiveCards int…
almedina-ms Oct 2, 2020
39eaef7
Update Submit API
almedina-ms Oct 2, 2020
3010479
Updates samples to mimic bug scenario
almedina-ms Oct 2, 2020
0f3a915
Update documentation on the introduced APIs
almedina-ms Oct 2, 2020
3908298
Fix casting bug
almedina-ms Oct 2, 2020
5536386
Update API to be more similar to iOS
almedina-ms Oct 5, 2020
e868250
Clear prevalidated inputs to avoid caching results
almedina-ms Oct 5, 2020
9aa32ab
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
shalinijoshi19 Oct 9, 2020
7086795
Update the sample to add disabling
almedina-ms Oct 9, 2020
95ead56
Merge branch 'user/almedina-ms/Android_UpdateSubmitValidationAPI' of …
almedina-ms Oct 9, 2020
ef363c1
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
shalinijoshi19 Oct 12, 2020
4cef858
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
shalinijoshi19 Oct 26, 2020
3a405a3
Add first changes
almedina-ms Oct 26, 2020
4d9c625
Merge branch 'main' of https://github.com/microsoft/AdaptiveCards int…
almedina-ms Oct 27, 2020
29e9706
Add unit test and fix bug
almedina-ms Oct 27, 2020
450c73b
Merge branch 'main' of https://github.com/microsoft/AdaptiveCards int…
almedina-ms Oct 27, 2020
3aa4c19
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
almedina-ms Oct 27, 2020
a62269e
Add warning for test as focus makes it unusable
almedina-ms Oct 27, 2020
83fde5b
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
shalinijoshi19 Oct 27, 2020
656d16c
Merge branch 'main' into user/almedina-ms/Android_UpdateSubmitValidat…
golddove Oct 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
package io.adaptivecards.objectmodel;

import android.content.Context;
import android.os.AsyncTask;
import android.support.test.InstrumentationRegistry;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you are on here @almedina-ms can you add in the msft copyright header pls

import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

import junit.framework.Assert;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Map;

import io.adaptivecards.renderer.AdaptiveCardRenderer;
import io.adaptivecards.renderer.AdaptiveFallbackException;
import io.adaptivecards.renderer.BaseActionElementRenderer;
import io.adaptivecards.renderer.RenderArgs;
import io.adaptivecards.renderer.RenderedAdaptiveCard;
import io.adaptivecards.renderer.Util;
import io.adaptivecards.renderer.action.ActionElementRenderer;
import io.adaptivecards.renderer.actionhandler.ICardActionHandler;
import io.adaptivecards.renderer.inputhandler.IInputWatcher;
import io.adaptivecards.renderer.registration.CardRendererRegistration;

public class APITest
{
Expand Down Expand Up @@ -67,5 +84,156 @@ public void TestGetResourceInformationAPI() throws Exception
}
}

public static class CustomActionListener extends BaseActionElementRenderer.ActionOnClickListener
{
public CustomActionListener(RenderedAdaptiveCard renderedCard,
Context context,
FragmentManager fragmentManager,
ViewGroup viewGroup,
BaseActionElement baseActionElement,
ICardActionHandler cardActionHandler,
HostConfig hostConfig,
RenderArgs renderArgs)
{
super(renderedCard, context, fragmentManager, viewGroup, baseActionElement, cardActionHandler, hostConfig, renderArgs);
}

public CustomActionListener(RenderedAdaptiveCard renderedCard,
BaseActionElement baseActionElement,
ICardActionHandler cardActionHandler)
{
super(renderedCard, baseActionElement, cardActionHandler);
}

@Override
public void onClick(View view)
{
super.onClick(view);

if (m_renderedAdaptiveCard.areInputsValid())
{
}
}
}

public static class CustomBlueAction extends BaseActionElement
{
public CustomBlueAction(ActionType type) {
super(type);
}
public static final String CustomActionId = "blueAction";

public static class CustomBlueActionParser extends ActionElementParser
{
@Override
public BaseActionElement Deserialize(ParseContext context, JsonValue value)
{
CustomBlueAction blueAction = new CustomBlueAction(ActionType.Custom);
Util.deserializeBaseActionProperties(context, value, blueAction);
blueAction.SetElementTypeString(CustomActionId);
return blueAction;
}

@Override
public BaseActionElement DeserializeFromString(ParseContext context, String jsonString)
{
CustomBlueAction blueAction = new CustomBlueAction(ActionType.Custom);
Util.deserializeBaseActionPropertiesFromString(context, jsonString, blueAction);
blueAction.SetElementTypeString(CustomActionId);
return blueAction;
}
}

public static class CustomBlueActionRenderer extends BaseActionElementRenderer
{
@Override
public Button render(RenderedAdaptiveCard renderedCard,
Context context,
FragmentManager fragmentManager,
ViewGroup viewGroup,
BaseActionElement baseActionElement,
ICardActionHandler cardActionHandler,
HostConfig hostConfig,
RenderArgs renderArgs) throws AdaptiveFallbackException
{
Button blueAction = ActionElementRenderer.getInstance().render(renderedCard,
context,
fragmentManager,
viewGroup,
baseActionElement,
cardActionHandler,
hostConfig,
renderArgs);

blueAction.setOnClickListener(new CustomActionListener(renderedCard, baseActionElement, cardActionHandler));
renderedCard.registerSubmitableAction(blueAction, renderArgs);

renderedButton = blueAction;

return blueAction;
}

public static Button renderedButton = null;
}

}

public static class ActionHandler implements ICardActionHandler
{

@Override
public void onAction(BaseActionElement actionElement, RenderedAdaptiveCard renderedAdaptiveCard)
{
Map<String, String> inputs = renderedAdaptiveCard.getInputs();
Assert.assertEquals(1, inputs.size());
Assert.assertTrue("Input list doesn't contain expected input id", inputs.keySet().contains("id1"));
Assert.assertEquals("A Value", inputs.get("id1"));
}

@Override
public void onMediaPlay(BaseCardElement mediaElement, RenderedAdaptiveCard renderedAdaptiveCard)
{
}

@Override
public void onMediaStop(BaseCardElement mediaElement, RenderedAdaptiveCard renderedAdaptiveCard)
{
}
}

@Test
public void TestCustomActionWithSubmitFunctionality() throws Exception
{
// To run this test please comment this line in BaseActionElementRenderer Util.clearFocus(view);
// The aforementioned line produces an exception as this elements in theory don't exist in any view, so in turn
// it can't set focus or remove it, thus throwing an exception
try
{
String jsonText = "{\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\"," +
"\"type\": \"AdaptiveCard\", \"version\": \"1.2\", \"body\": [ {" +
"\"type\": \"Input.Text\", \"id\": \"id1\", \"value\": \"A Value\" } ]," +
"\"actions\": [ { \"type\": \"blueAction\", \"title\": \"Custom Blue\" } ] }";

ElementParserRegistration elementParserRegistration = new ElementParserRegistration();
ActionParserRegistration actionParserRegistration = new ActionParserRegistration();
actionParserRegistration.AddParser(CustomBlueAction.CustomActionId, new CustomBlueAction.CustomBlueActionParser());

ParseContext parseContext = new ParseContext(elementParserRegistration, actionParserRegistration);

ParseResult parseResult = AdaptiveCard.DeserializeFromString(jsonText, AdaptiveCardRenderer.VERSION, parseContext);

CardRendererRegistration.getInstance().registerActionRenderer(CustomBlueAction.CustomActionId, new CustomBlueAction.CustomBlueActionRenderer());

Context context = InstrumentationRegistry.getTargetContext();
RenderedAdaptiveCard renderedCard = AdaptiveCardRenderer.getInstance().render(context, null, parseResult.GetAdaptiveCard(), new ActionHandler(), new HostConfig());

CustomBlueAction.CustomBlueActionRenderer.renderedButton.performClick();
}
catch (Exception ex)
{
// Assert.fail();
}
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public RenderedAdaptiveCard render(
HostConfig hostConfig)
{
RenderedAdaptiveCard result = new RenderedAdaptiveCard(adaptiveCard);
View cardView = internalRender(result, context, fragmentManager, adaptiveCard, cardActionHandler, hostConfig, false, new InternalId());
View cardView = internalRender(result, context, fragmentManager, adaptiveCard, cardActionHandler, hostConfig, false, View.NO_ID);
result.setView(cardView);
return result;
}
Expand Down Expand Up @@ -99,7 +99,7 @@ public View internalRender(RenderedAdaptiveCard renderedCard,
ICardActionHandler cardActionHandler,
HostConfig hostConfig,
boolean isInlineShowCard,
InternalId containerCardId)
long containerCardId)
{
if (hostConfig == null)
{
Expand Down Expand Up @@ -152,8 +152,10 @@ public View internalRender(RenderedAdaptiveCard renderedCard,

RenderArgs renderArgs = new RenderArgs();
renderArgs.setContainerStyle(style);
renderArgs.setContainerCardId(adaptiveCard.GetInternalId());
renderedCard.setParentToCard(adaptiveCard.GetInternalId(), containerCardId);

long cardId = Util.getViewId(rootLayout);
renderArgs.setContainerCardId(cardId);
renderedCard.setParentToCard(cardId, containerCardId);

// Render the body section of the Adaptive Card
String color = hostConfig.GetBackgroundColor(style);
Expand Down Expand Up @@ -190,7 +192,7 @@ public View internalRender(RenderedAdaptiveCard renderedCard,
}

ContainerRenderer.setBackgroundImage(renderedCard, context, adaptiveCard.GetBackgroundImage(), hostConfig, cardLayout);
ContainerRenderer.setSelectAction(renderedCard, renderedCard.getAdaptiveCard().GetSelectAction(), rootLayout, cardActionHandler);
ContainerRenderer.setSelectAction(renderedCard, renderedCard.getAdaptiveCard().GetSelectAction(), rootLayout, cardActionHandler, renderArgs);

return rootLayout;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,27 +316,27 @@ private void handleToggleVisibilityAction(View v)
}

@Override
public void onClick(View v)
public void onClick(View view)
{
m_renderedAdaptiveCard.clearValidatedInputs();

if (m_isInlineShowCardAction)
{
handleInlineShowCardAction(v);
handleInlineShowCardAction(view);
}
else if (m_action.GetElementType() == ActionType.ToggleVisibility)
{
handleToggleVisibilityAction(v);
handleToggleVisibilityAction(view);
}
else
{
if (m_action.GetElementType() == ActionType.Submit)
if (m_action.GetElementType() == ActionType.Submit || m_renderedAdaptiveCard.isActionSubmitable(view))
{
SubmitAction submitAction = Util.castTo(m_action, SubmitAction.class);

// If an input is in focus before submit, and the same input is focused on error,
// the input would not be scrolled into view. Instead, clearing focus first ensures scroll.
Util.clearFocus(v);
Util.clearFocus(view);

if (!m_renderedAdaptiveCard.areInputsValid(submitAction))
if (!m_renderedAdaptiveCard.areInputsValid(Util.getViewId(view)))
{
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,18 @@ public void setAllowAboveTitleIconPlacement(boolean allowAboveTitleIconPlacement
m_allowAboveTitleIconPlacement = allowAboveTitleIconPlacement;
}

public void setContainerCardId(InternalId id)
public void setContainerCardId(long id)
{
m_containerCardId = id;
}

public InternalId getContainerCardId()
public long getContainerCardId()
{
return m_containerCardId;
}

private boolean m_ancestorHasFallback;
private ContainerStyle m_containerStyle;
private boolean m_allowAboveTitleIconPlacement;
private InternalId m_containerCardId;
private long m_containerCardId;
}
Loading