ui: prevent SmartList from blinking

We only refresh the Smartlist if its new data are different
from the ones that are currently displayed

Change-Id: I149205923d59c311e11d23cfd233a1407b879695
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/SmartListAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/SmartListAdapter.java
index b50ef13..75475f0 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/SmartListAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/SmartListAdapter.java
@@ -43,6 +43,7 @@
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
 
 import butterknife.BindView;
@@ -91,6 +92,11 @@
         return Normalizer.normalize(query.toLowerCase(), Normalizer.Form.NFD).replaceAll("[\u0300-\u036F]", "");
     }
 
+    public void emptyDataset () {
+        mConversations.clear();
+        notifyDataSetChanged();
+    }
+
     public void updateDataset(final Collection<Conversation> list, String query) {
         Log.d(TAG, "updateDataset " + list.size() + " with query: " + query);
 
@@ -98,18 +104,19 @@
             return;
         }
 
-        mConversations.clear();
+        List<Conversation> newConversations = new ArrayList<>();
+
         for (Conversation c : list) {
             if (!c.getContact().isUnknown()
                     || !c.getAccountsUsed().isEmpty()
                     || c.getCurrentCall() != null) {
                 if (TextUtils.isEmpty(query) || c.getCurrentCall() != null) {
-                    mConversations.add(c);
+                    newConversations.add(c);
                 } else if (c.getContact() != null) {
                     CallContact contact = c.getContact();
                     if (!TextUtils.isEmpty(contact.getDisplayName()) &&
                             stringFormatting(contact.getDisplayName()).contains(stringFormatting(query))) {
-                        mConversations.add(c);
+                        newConversations.add(c);
                     } else if (contact.getPhones() != null && !contact.getPhones().isEmpty()) {
                         ArrayList<Phone> phones = contact.getPhones();
                         for (Phone phone : phones) {
@@ -117,7 +124,7 @@
                                 String rawUriString = phone.getNumber().getRawUriString();
                                 if (!TextUtils.isEmpty(rawUriString) &&
                                         stringFormatting(rawUriString.toLowerCase()).contains(stringFormatting(query))) {
-                                    mConversations.add(c);
+                                    newConversations.add(c);
                                 }
                             }
                         }
@@ -126,7 +133,58 @@
             }
         }
 
-        notifyDataSetChanged();
+        // only refresh display if there is new data to display
+        if (areConversationListDifferent(mConversations, newConversations)) {
+            mConversations.clear();
+            mConversations.addAll(newConversations);
+            notifyDataSetChanged();
+        }
+
+    }
+
+    /**
+     *
+     * @return true if list are different
+     */
+    private boolean areConversationListDifferent(List<Conversation> leftList, List<Conversation> rightList) {
+        if (leftList == null || rightList == null) {
+            return true;
+        }
+
+        if (leftList.size() != rightList.size()) {
+            return true;
+        }
+
+        for (Conversation rightConversation: rightList) {
+            if (rightConversation.hasCurrentCall() || rightConversation.hasUnreadTextMessages()) {
+                return true;
+            }
+
+            int rightId = rightConversation.getUuid();
+            CallContact rightContact = rightConversation.getContact();
+            boolean found = false;
+            for (Conversation leftConversation: leftList) {
+
+                if (leftConversation.hasCurrentCall() || leftConversation.hasUnreadTextMessages()) {
+                    return true;
+                }
+
+                int leftId = leftConversation.getUuid();
+                CallContact leftContact = leftConversation.getContact();
+                if (leftId == rightId
+                        && leftContact!=null
+                        && leftContact.equals(rightContact)) {
+                    found = true;
+                    break;
+                }
+            }
+
+            if (!found) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
index 9e9139c..0551c93 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/SmartListFragment.java
@@ -158,6 +158,7 @@
                     break;
                 }
             }
+
             refresh();
         }
     };
@@ -239,7 +240,7 @@
         searchForRingIdInBlockchain();
     }
 
-    private void searchForRingIdInBlockchain() {
+    private void  searchForRingIdInBlockchain() {
         LocalService service = mCallbacks.getService();
         if (service == null || !service.isConnected() || !service.areConversationsLoaded()) {
             return;
@@ -301,6 +302,11 @@
         mAccountService.addObserver(mRinguifyObserver);
         Log.d(TAG, "onResume");
         ((HomeActivity) getActivity()).setToolbarState(false, R.string.app_name);
+        if (mSmartListAdapter != null) {
+            // force refresh each time this screen is shown
+            // useful if a contact changes his avatar or his display name
+            mSmartListAdapter.emptyDataset();
+        }
         refresh();
     }