Distinguish devices with same name in chooser on Android
For devices with different names, the chooser just shows their names;
for devices with the same name, the chooser shows their name with
its unique device identifier.
So the chooser will look like:
device_different_name
device_same_name (device_1)
device_same_name (device_2)
device_same_name (device_3)
BUG=544121
Review-Url: https://codereview.chromium.org/2098983002
Cr-Commit-Position: refs/heads/master@{#403295}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
index 3858ec8..f1659d1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ItemChooserDialog.java
@@ -33,7 +33,9 @@
import org.chromium.ui.base.DeviceFormFactor;
import org.chromium.ui.widget.TextViewWithClickableSpans;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
/**
@@ -119,7 +121,7 @@
/**
* An adapter for keeping track of which items to show in the dialog.
*/
- private class ItemAdapter extends ArrayAdapter<ItemChooserRow>
+ public class ItemAdapter extends ArrayAdapter<ItemChooserRow>
implements AdapterView.OnItemClickListener {
private final LayoutInflater mInflater;
@@ -136,6 +138,9 @@
// A set of keys that are marked as disabled in the dialog.
private Set<String> mDisabledEntries = new HashSet<String>();
+ // Item descriptions are counted in a map.
+ private Map<String, Integer> mItemDescriptionMap = new HashMap<>();
+
public ItemAdapter(Context context, int resource) {
super(context, resource);
@@ -148,6 +153,29 @@
}
@Override
+ public void add(ItemChooserRow item) {
+ String description = item.mDescription;
+ int count = mItemDescriptionMap.containsKey(description)
+ ? mItemDescriptionMap.get(description) : 0;
+ mItemDescriptionMap.put(description, count + 1);
+ super.add(item);
+ }
+
+ @Override
+ public void remove(ItemChooserRow item) {
+ String description = item.mDescription;
+ if (mItemDescriptionMap.containsKey(description)) {
+ int count = mItemDescriptionMap.get(description);
+ if (count == 1) {
+ mItemDescriptionMap.remove(description);
+ } else {
+ mItemDescriptionMap.put(description, count - 1);
+ }
+ }
+ super.remove(item);
+ }
+
+ @Override
public void clear() {
mSelectedItem = ListView.INVALID_POSITION;
mConfirmButton.setEnabled(false);
@@ -165,6 +193,20 @@
}
/**
+ * Returns the text to be displayed on the chooser for an item. For items with the same
+ * description, their unique keys are appended to distinguish them.
+ * @param position The index of the item.
+ */
+ public String getDisplayText(int position) {
+ ItemChooserRow item = getItem(position);
+ String description = item.mDescription;
+ int counter = mItemDescriptionMap.get(description);
+ return counter == 1 ? description
+ : mActivity.getString(R.string.item_chooser_item_name_with_id, description,
+ item.mKey);
+ }
+
+ /**
* Sets whether the itam is enabled. Disabled items are grayed out.
* @param id The id of the item to affect.
* @param enabled Whether the item should be enabled or not.
@@ -218,8 +260,7 @@
}
}
- ItemChooserRow item = getItem(position);
- view.setText(item.mDescription);
+ view.setText(getDisplayText(position));
return view;
}
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 0130446..381de34 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2694,6 +2694,11 @@
<message name="IDS_TAB_SWITCHER_CALLOUT_BODY" desc="Indicates that clicking the tab switcher button gives you quick access to your tabs.">
Tap this button for quick access to your tabs.
</message>
+
+ <!-- Item Chooser UI strings -->
+ <message name="IDS_ITEM_CHOOSER_ITEM_NAME_WITH_ID" desc="To distinguish items with the same name, the item chooser shows the item name with id.">
+ <ph name="ITEM_NAME">%1$s<ex>item_name</ex></ph> (<ph name="ITEM_ID">%2$s<ex>item id</ex></ph>)
+ </message>
</messages>
</release>
</grit>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
index ef2cd24..da4b28b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ItemChooserDialogTest.java
@@ -262,6 +262,64 @@
}
@SmallTest
+ public void testAddItemWithSameNameToListAndRemoveItemFromList() throws InterruptedException {
+ Dialog dialog = mChooserDialog.getDialogForTesting();
+ assertTrue(dialog.isShowing());
+
+ ItemChooserDialog.ItemAdapter itemAdapter = mChooserDialog.getItemAdapterForTesting();
+
+ // Add item 1.
+ ItemChooserDialog.ItemChooserRow item1 =
+ new ItemChooserDialog.ItemChooserRow("device_id_1", "same_device_name");
+ mChooserDialog.addItemToList(item1);
+ assertEquals(1, itemAdapter.getCount());
+ assertEquals(itemAdapter.getItem(0), item1);
+
+ // Add item 2.
+ ItemChooserDialog.ItemChooserRow item2 =
+ new ItemChooserDialog.ItemChooserRow("device_id_2", "different_device_name");
+ mChooserDialog.addItemToList(item2);
+ assertEquals(2, itemAdapter.getCount());
+ assertEquals(itemAdapter.getItem(0), item1);
+ assertEquals(itemAdapter.getItem(1), item2);
+
+ // Add item 3.
+ ItemChooserDialog.ItemChooserRow item3 =
+ new ItemChooserDialog.ItemChooserRow("device_id_3", "same_device_name");
+ mChooserDialog.addItemToList(item3);
+ assertEquals(3, itemAdapter.getCount());
+ assertEquals(itemAdapter.getItem(0), item1);
+ assertEquals(itemAdapter.getItem(1), item2);
+ assertEquals(itemAdapter.getItem(2), item3);
+
+ // Since two items have the same name, their display text should have their unique
+ // keys appended.
+ assertEquals("same_device_name (device_id_1)", itemAdapter.getDisplayText(0));
+ assertEquals("different_device_name", itemAdapter.getDisplayText(1));
+ assertEquals("same_device_name (device_id_3)", itemAdapter.getDisplayText(2));
+
+ // Remove item 2.
+ mChooserDialog.removeItemFromList(item2);
+ assertEquals(2, itemAdapter.getCount());
+ // Make sure the remaining items are item 1 and item 3.
+ assertEquals(itemAdapter.getItem(0), item1);
+ assertEquals(itemAdapter.getItem(1), item3);
+ assertEquals("same_device_name (device_id_1)", itemAdapter.getDisplayText(0));
+ assertEquals("same_device_name (device_id_3)", itemAdapter.getDisplayText(1));
+
+ // Remove item 1.
+ mChooserDialog.removeItemFromList(item1);
+ assertEquals(1, itemAdapter.getCount());
+ // Make sure the remaining item is item 3.
+ assertEquals(itemAdapter.getItem(0), item3);
+ // After removing item 1, item 3 is the only remaining item, so its display text
+ // also changed to its original description.
+ assertEquals("same_device_name", itemAdapter.getDisplayText(0));
+
+ mChooserDialog.dismiss();
+ }
+
+ @SmallTest
public void testListHeight() throws InterruptedException {
// 500 * .3 is 150, which is 48 * 3.125. 48 * 3.5 is 168.
assertEquals(168, ItemChooserDialog.getListHeight(500, 1.0f));