Skip to content

Commit 5061ba8

Browse files
author
RahulAmlekar
committed
Updating schema explorer properties
1 parent 93d2803 commit 5061ba8

File tree

12 files changed

+343
-8
lines changed

12 files changed

+343
-8
lines changed

schemas/1.5.0/adaptive-card.json

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,18 @@
314314
2293
315315
]
316316
},
317+
"rtl": {
318+
"anyOf": [
319+
{
320+
"type": "boolean"
321+
},
322+
{
323+
"type": "null"
324+
}
325+
],
326+
"description": "When `true` content in this Adaptive Card should be presented right to left. When 'false' content in this Adaptive Card should be presented left to right. If unset, the default platform behavior will apply.",
327+
"version": "1.5"
328+
},
317329
"speak": {
318330
"type": "string",
319331
"description": "Specifies what should be spoken for this entire card. This is simple text or SSML fragment."
@@ -447,7 +459,7 @@
447459
"type": "null"
448460
}
449461
],
450-
"description": "When `true` content in this container should be presented right to left. When 'false' content in this container should be presented left to right. When unset layout direction will inherit from parent container or column. If unset in all ancestors, the default platform behavior will apply.",
462+
"description": "When `true` content in this column should be presented right to left. When 'false' content in this column should be presented left to right. When unset layout direction will inherit from parent container or column. If unset in all ancestors, the default platform behavior will apply.",
451463
"version": "1.5"
452464
},
453465
"separator": {
@@ -665,7 +677,7 @@
665677
2293
666678
]
667679
},
668-
"rtl?": {
680+
"rtl?": {
669681
"anyOf": [
670682
{
671683
"type": "boolean"
@@ -1947,7 +1959,8 @@
19471959
{
19481960
"enum": [
19491961
"compact",
1950-
"expanded"
1962+
"expanded",
1963+
"filtered"
19511964
]
19521965
},
19531966
{

schemas/src/AdaptiveCard.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@
6161
2293
6262
]
6363
},
64+
"rtl": {
65+
"type": "boolean?",
66+
"description": "When `true` content in this Adaptive Card should be presented right to left. When 'false' content in this Adaptive Card should be presented left to right. If unset, the default platform behavior will apply.",
67+
"version": "1.5"
68+
},
6469
"speak": {
6570
"type": "string",
6671
"description": "Specifies what should be spoken for this entire card. This is simple text or SSML fragment."

schemas/src/elements/Column.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
},
4545
"rtl": {
4646
"type": "boolean?",
47-
"description": "When `true` content in this container should be presented right to left. When 'false' content in this container should be presented left to right. When unset layout direction will inherit from parent container or column. If unset in all ancestors, the default platform behavior will apply.",
47+
"description": "When `true` content in this column should be presented right to left. When 'false' content in this column should be presented left to right. When unset layout direction will inherit from parent container or column. If unset in all ancestors, the default platform behavior will apply.",
4848
"version": "1.5"
4949
},
5050
"separator": {

schemas/src/enums/ChoiceInputStyle.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
"description": "Style hint for `Input.ChoiceSet`.",
55
"values": [
66
"compact",
7-
"expanded"
7+
"expanded",
8+
{
9+
"value": "filtered",
10+
"description": "Allows users to filter choices in a choice set.",
11+
"version": "1.5"
12+
}
813
]
914
}

source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/ChoiceSetInputRenderer.java

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import androidx.annotation.NonNull;
88
import androidx.annotation.Nullable;
99
import androidx.fragment.app.FragmentManager;
10+
11+
import android.os.Build;
1012
import android.text.TextUtils;
1113
import android.util.TypedValue;
14+
import android.view.KeyEvent;
1215
import android.view.MotionEvent;
1316
import android.view.View;
1417
import android.view.ViewGroup;
@@ -17,6 +20,7 @@
1720
import android.widget.AutoCompleteTextView;
1821
import android.widget.CheckBox;
1922
import android.widget.CompoundButton;
23+
import android.widget.Filter;
2024
import android.widget.RadioButton;
2125
import android.widget.RadioGroup;
2226
import android.widget.Spinner;
@@ -50,9 +54,12 @@
5054
import io.adaptivecards.renderer.inputhandler.RadioGroupInputHandler;
5155
import io.adaptivecards.renderer.registration.CardRendererRegistration;
5256

57+
import java.util.ArrayList;
5358
import java.util.Arrays;
5459
import java.util.List;
5560
import java.util.Vector;
61+
import java.util.function.Predicate;
62+
import java.util.stream.Collectors;
5663

5764
public class ChoiceSetInputRenderer extends BaseCardElementRenderer
5865
{
@@ -440,11 +447,29 @@ class FilteredChoiceSetAdapter extends ArrayAdapter<String>
440447
{
441448
boolean m_mustWrap = false;
442449

450+
// m_items contains the items currently being displayed as suggestions
451+
// m_originalItemsList contains the items provided by the card author when the element was created
452+
List<String> m_items, m_originalItemsList;
453+
443454
FilteredChoiceSetAdapter(Context context, int resource,
444455
Vector<String> items, boolean mustWrap)
445456
{
446457
super(context, resource, items);
447458
m_mustWrap = mustWrap;
459+
m_items = items;
460+
m_originalItemsList = new ArrayList<>(items);
461+
}
462+
463+
@Override
464+
public int getCount()
465+
{
466+
return m_items.size();
467+
}
468+
469+
@Override
470+
public String getItem(int pos)
471+
{
472+
return m_items.get(pos);
448473
}
449474

450475
@NonNull
@@ -463,6 +488,75 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
463488

464489
return view;
465490
}
491+
492+
@NonNull
493+
@Override
494+
public Filter getFilter() {
495+
return m_substringFilter;
496+
}
497+
498+
Filter m_substringFilter = new Filter() {
499+
500+
@Override
501+
protected FilterResults performFiltering(CharSequence constraint) {
502+
503+
FilterResults filterResults = new FilterResults();
504+
505+
// Due to the time it takes for evaluating all options, this part of the code has
506+
// to be synchronized, otherwise the worker thread that calls the publishResults
507+
// function will throw an illegalstateexception or a concurrentmodificationexception
508+
synchronized (filterResults)
509+
{
510+
List<String> filteredSuggestions = new ArrayList<>();
511+
512+
// isEmpty compares against null and 0-length strings
513+
if (!TextUtils.isEmpty(constraint))
514+
{
515+
String lowerCaseConstraint = constraint.toString().toLowerCase();
516+
517+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
518+
{
519+
Predicate<String> bySubstring = choice -> choice.toLowerCase().contains(lowerCaseConstraint);
520+
filteredSuggestions = m_originalItemsList.stream().filter(bySubstring).collect(Collectors.toList());
521+
}
522+
else
523+
{
524+
for (String choice : m_originalItemsList)
525+
{
526+
if (choice.toLowerCase().contains(lowerCaseConstraint))
527+
{
528+
filteredSuggestions.add(choice);
529+
}
530+
}
531+
}
532+
}
533+
else
534+
{
535+
filteredSuggestions = m_originalItemsList;
536+
}
537+
538+
filterResults.values = filteredSuggestions;
539+
filterResults.count = filteredSuggestions.size();
540+
541+
return filterResults;
542+
}
543+
}
544+
545+
@Override
546+
protected void publishResults(CharSequence constraint, FilterResults filterResults)
547+
{
548+
if (filterResults != null && filterResults.count > 0)
549+
{
550+
m_items = (ArrayList<String>) filterResults.values;
551+
notifyDataSetChanged();
552+
}
553+
else
554+
{
555+
notifyDataSetInvalidated();
556+
}
557+
}
558+
};
559+
466560
}
467561

468562
autoCompleteTextView.setAdapter(new FilteredChoiceSetAdapter(context,
@@ -475,6 +569,22 @@ public View getView(int position, @Nullable View convertView, @NonNull ViewGroup
475569
autoCompleteTextView.setText(titleList.get(valueIndex));
476570
}
477571

572+
autoCompleteTextView.setOnTouchListener(new View.OnTouchListener(){
573+
@Override
574+
public boolean onTouch(View v, MotionEvent event){
575+
autoCompleteTextView.showDropDown();
576+
return false;
577+
}
578+
});
579+
580+
autoCompleteTextView.setOnKeyListener(new View.OnKeyListener() {
581+
@Override
582+
public boolean onKey(View view, int i, KeyEvent keyEvent) {
583+
autoCompleteTextView.showDropDown();
584+
return false;
585+
}
586+
});
587+
478588
autoCompleteTextView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
479589
{
480590
@Override

source/android/adaptivecards/src/main/java/io/adaptivecards/renderer/input/customcontrols/ValidatedAutoCompleteTextView.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import android.content.Context;
66
import android.content.res.Resources;
7+
import android.graphics.Rect;
78
import android.util.TypedValue;
89
import android.widget.LinearLayout;
910

@@ -45,6 +46,23 @@ public ValidatedAutoCompleteTextView(Context context, boolean usingCustomInputs)
4546
}
4647
}
4748

49+
@Override
50+
public boolean enoughToFilter()
51+
{
52+
return true;
53+
}
54+
55+
@Override
56+
protected void onFocusChanged(boolean focused, int direction,
57+
Rect previouslyFocusedRect)
58+
{
59+
super.onFocusChanged(focused, direction, previouslyFocusedRect);
60+
if (focused)
61+
{
62+
performFiltering(getText(), 0);
63+
}
64+
}
65+
4866
/**
4967
* Peeks the usingCustomInputs attribute in the style to verify if custom inputs are being used
5068
* @param context Context to retrieve the value from

source/android/uitestapp/build.gradle

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ android {
3030
assets {
3131
srcDirs {
3232
["../../../samples/v1.3/Scenarios/",
33-
"../../../samples/v1.5/Test/"]
33+
"../../../samples/v1.5/Test/",
34+
"../../../samples/v1.5/Elements/"]
3435
}
3536
}
3637
}
@@ -45,6 +46,7 @@ dependencies {
4546
implementation 'androidx.navigation:navigation-ui:2.2.2'
4647
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
4748
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
49+
implementation 'androidx.test.uiautomator:uiautomator:2.2.0'
4850

4951
androidTestImplementation 'androidx.test:core:1.3.0'
5052
androidTestImplementation 'androidx.test:runner:1.3.0'
@@ -53,6 +55,7 @@ dependencies {
5355

5456
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
5557
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.0'
58+
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
5659
// androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
5760
// androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0''
5861

source/android/uitestapp/src/androidTest/java/io.adaptivecards.uitestapp/TestHelpers.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@
33
package io.adaptivecards.uitestapp
44

55
import androidx.test.espresso.Espresso
6+
import androidx.test.espresso.ViewInteraction
67
import androidx.test.espresso.action.ViewActions
8+
import androidx.test.espresso.assertion.ViewAssertions
9+
import androidx.test.espresso.matcher.RootMatchers
710
import androidx.test.espresso.matcher.ViewMatchers
11+
import io.adaptivecards.renderer.TagContent
12+
import io.adaptivecards.uitestapp.ui.inputs.RetrievedInput
13+
import org.hamcrest.Matchers
814

915
object TestHelpers {
1016
internal fun goToTestCasesScreen() {
@@ -18,4 +24,28 @@ object TestHelpers {
1824
internal fun goToInputsScreen() {
1925
Espresso.onView(ViewMatchers.withId(R.id.navigation_inputs)).perform(ViewActions.click())
2026
}
27+
28+
internal fun findInputInValidatedContainer(validatedContainerTagId : String) : ViewInteraction {
29+
return Espresso.onView(ViewMatchers.withParent(ViewMatchers.withTagValue(Matchers.`is`(TagContent(validatedContainerTagId)))));
30+
}
31+
32+
internal fun clearTextInInput(input : ViewInteraction) {
33+
input.perform(ViewActions.scrollTo(), ViewActions.click(), ViewActions.clearText());
34+
}
35+
36+
internal fun setTextInInput(input : ViewInteraction, text : String) {
37+
input.perform(ViewActions.scrollTo(), ViewActions.click(), ViewActions.clearText(), ViewActions.typeText(text));
38+
}
39+
40+
internal fun selectPopupOption(optionText : String) {
41+
Espresso.onData(Matchers.`is`(optionText)).inRoot(RootMatchers.isPlatformPopup()).perform(ViewActions.scrollTo(), ViewActions.click());
42+
}
43+
44+
internal fun clickOnElementWithText(text : String) {
45+
Espresso.onView(ViewMatchers.withText(text)).perform(ViewActions.click())
46+
}
47+
48+
internal fun assertInputValuePairExists(inputId : String, value : String) {
49+
Espresso.onData(Matchers.`is`(RetrievedInput(inputId, value))).check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
50+
}
2151
}

0 commit comments

Comments
 (0)