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 c80e014cf42a956430696bf2de35104a223aaade..25f32b8ba8cd2e11722d86fd8956c0b43ba963b8 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
@@ -21,9 +21,9 @@ package cx.ring.adapters;
 
 import android.content.Context;
 import android.graphics.Typeface;
-import android.net.Uri;
-import android.provider.ContactsContract;
+import android.os.Bundle;
 import android.support.v4.content.ContextCompat;
+import android.support.v7.util.DiffUtil;
 import android.support.v7.widget.RecyclerView;
 import android.text.format.DateUtils;
 import android.view.LayoutInflater;
@@ -36,11 +36,9 @@ import com.bumptech.glide.signature.StringSignature;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 import cx.ring.R;
-import cx.ring.model.HistoryCall;
-import cx.ring.model.HistoryEntry;
-import cx.ring.model.TextMessage;
 import cx.ring.smartlist.SmartListViewModel;
 import cx.ring.utils.CircleTransform;
 import cx.ring.viewholders.SmartListViewHolder;
@@ -51,8 +49,9 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
     private SmartListViewHolder.SmartListListeners listener;
 
     public SmartListAdapter(ArrayList<SmartListViewModel> smartListViewModels, SmartListViewHolder.SmartListListeners listener) {
-        this.mSmartListViewModels = new ArrayList<>(smartListViewModels);
         this.listener = listener;
+        this.mSmartListViewModels = new ArrayList<>();
+        this.mSmartListViewModels.addAll(smartListViewModels);
     }
 
     @Override
@@ -85,18 +84,17 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
                 holder.convStatus.setVisibility(View.VISIBLE);
                 holder.convTime.setVisibility(View.VISIBLE);
                 holder.contactRequest.setVisibility(View.GONE);
-                long lastInteraction = smartListViewModel.getLastInteractionTime();
-                holder.convTime.setText(lastInteraction == 0 ? "" :
-                        DateUtils.getRelativeTimeSpanString(lastInteraction, System.currentTimeMillis(), 0L, DateUtils.FORMAT_ABBREV_ALL));
                 break;
         }
 
         holder.convParticipants.setText(smartListViewModel.getContactName());
-
+        holder.convTime.setText(smartListViewModel.getLastInteractionTime());
         if (smartListViewModel.hasOngoingCall()) {
             holder.convStatus.setText(holder.itemView.getContext().getString(R.string.ongoing_call));
         } else if (smartListViewModel.getLastInteraction() != null) {
-            holder.convStatus.setText(getLastInteractionSummary(smartListViewModel.getLastInteraction(), holder.itemView.getContext()));
+            holder.convStatus.setText(getLastInteractionSummary(smartListViewModel.getLastEntryType(),
+                    smartListViewModel.getLastInteraction(),
+                    holder.itemView.getContext()));
         } else {
             holder.convStatus.setVisibility(View.GONE);
         }
@@ -111,20 +109,7 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
             holder.convStatus.setTypeface(null, Typeface.NORMAL);
         }
 
-        String photoUri = smartListViewModel.getPhotoUri();
-
-        if (photoUri != null) {
-            if (isContentUri(photoUri)) {
-                Glide.with(holder.itemView.getContext())
-                        .load(Uri.withAppendedPath(Uri.parse(photoUri), ContactsContract.Contacts.Photo.DISPLAY_PHOTO))
-                        .crossFade()
-                        .signature(new StringSignature(smartListViewModel.getUuid()))
-                        .placeholder(R.drawable.ic_contact_picture)
-                        .transform(new CircleTransform(holder.itemView.getContext()))
-                        .error(R.drawable.ic_contact_picture)
-                        .into(holder.photo);
-            }
-        } else if (smartListViewModel.getPhotoData() != null) {
+        if (smartListViewModel.getPhotoData() != null) {
             Glide.with(holder.itemView.getContext())
                     .fromBytes()
                     .diskCacheStrategy(DiskCacheStrategy.NONE)
@@ -155,36 +140,26 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
         return mSmartListViewModels.size();
     }
 
-    public void replaceAll(ArrayList<SmartListViewModel> list) {
-        mSmartListViewModels.clear();
-        mSmartListViewModels.addAll(list);
-        notifyDataSetChanged();
-    }
+    public void update(ArrayList<SmartListViewModel> smartListViewModels) {
+        final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new SmartListDiffUtil(this.mSmartListViewModels, smartListViewModels));
+        diffResult.dispatchUpdatesTo(this);
 
-    private boolean isContentUri(String uri) {
-        return uri.contains("content://");
+        this.mSmartListViewModels.clear();
+        this.mSmartListViewModels.addAll(smartListViewModels);
     }
 
-    private String getLastInteractionSummary(HistoryEntry e, Context context) {
-        long lastTextTimestamp = e.getTextMessages().isEmpty() ? 0 : e.getTextMessages().lastEntry().getKey();
-        long lastCallTimestamp = e.getCalls().isEmpty() ? 0 : e.getCalls().lastEntry().getKey();
-        if (lastTextTimestamp > 0 && lastTextTimestamp > lastCallTimestamp) {
-            TextMessage msg = e.getTextMessages().lastEntry().getValue();
-            String msgString = msg.getMessage();
-            if (msgString != null && !msgString.isEmpty() && msgString.contains("\n")) {
-                int lastIndexOfChar = msgString.lastIndexOf("\n");
-                if (lastIndexOfChar + 1 < msgString.length()) {
-                    msgString = msgString.substring(msgString.lastIndexOf("\n") + 1);
-                }
-            }
-            return (msg.isIncoming() ? "" : context.getText(R.string.you_txt_prefix) + " ") + msgString;
-        }
-        if (lastCallTimestamp > 0) {
-            HistoryCall lastCall = e.getCalls().lastEntry().getValue();
-            return String.format(context.getString(lastCall.isIncoming()
-                    ? R.string.hist_in_call
-                    : R.string.hist_out_call), lastCall.getDurationString());
+    private String getLastInteractionSummary(int type, String lastInteraction, Context context) {
+        switch (type) {
+            case SmartListViewModel.TYPE_INCOMING_CALL:
+                return String.format(context.getString(R.string.hist_in_call), lastInteraction);
+            case SmartListViewModel.TYPE_OUTGOING_CALL:
+                return String.format(context.getString(R.string.hist_out_call), lastInteraction);
+            case SmartListViewModel.TYPE_INCOMING_MESSAGE:
+                return lastInteraction;
+            case SmartListViewModel.TYPE_OUTGOING_MESSAGE:
+                return context.getText(R.string.you_txt_prefix) + " " + lastInteraction;
+            default:
+                return null;
         }
-        return null;
     }
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/SmartListDiffUtil.java b/ring-android/app/src/main/java/cx/ring/adapters/SmartListDiffUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..44687f94ddb4bb4ad5e4dbf5acbe10ef50e2a0f7
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/adapters/SmartListDiffUtil.java
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (C) 2016 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.adapters;
+
+import android.support.v7.util.DiffUtil;
+
+import java.util.List;
+
+import cx.ring.smartlist.SmartListViewModel;
+
+public class SmartListDiffUtil extends DiffUtil.Callback {
+
+    private List<SmartListViewModel> mOldList;
+    private List<SmartListViewModel> mNewList;
+
+    public SmartListDiffUtil(List<SmartListViewModel> oldList, List<SmartListViewModel> newList) {
+        this.mOldList = oldList;
+        this.mNewList = newList;
+    }
+
+    @Override
+    public int getOldListSize() {
+        return mOldList.size();
+    }
+
+    @Override
+    public int getNewListSize() {
+        return mNewList.size();
+    }
+
+    @Override
+    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
+        return mNewList.get(newItemPosition).getUuid().equals(mOldList.get(oldItemPosition).getUuid());
+    }
+
+    @Override
+    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
+        return mNewList.get(newItemPosition).equals(mOldList.get(oldItemPosition));
+    }
+}
\ No newline at end of file
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 c840d1bb4ec6c0614a55a8a867c72931dd39bc88..66c740c96a28cade6d6b092962710a285f1d1a44 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
@@ -69,7 +69,6 @@ import cx.ring.client.QRCodeScannerActivity;
 import cx.ring.model.CallContact;
 import cx.ring.model.Conversation;
 import cx.ring.mvp.BaseFragment;
-import cx.ring.service.LocalService;
 import cx.ring.smartlist.SmartListPresenter;
 import cx.ring.smartlist.SmartListView;
 import cx.ring.smartlist.SmartListViewModel;
@@ -85,8 +84,7 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
         ClipboardHelper.ClipboardHelperCallback,
         SmartListView {
 
-
-    private static final String TAG = SmartListFragment.class.getSimpleName();
+    public static final String TAG = SmartListFragment.class.getSimpleName();
     private static final String STATE_LOADING = TAG + ".STATE_LOADING";
 
     @Inject
@@ -124,18 +122,6 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
 
     private Boolean isTabletMode = false;
 
-    @Override
-    public void onAttach(Activity activity) {
-        Log.d(TAG, "onAttach");
-        super.onAttach(activity);
-
-        if (!(activity instanceof LocalService.Callbacks)) {
-            throw new IllegalStateException("Activity must implement fragment's callbacks.");
-        }
-
-    }
-
-    @Override
     public void onResume() {
         super.onResume();
 
@@ -220,7 +206,7 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
 
     @Override
     public boolean onQueryTextSubmit(String query) {
-        mNewContact.callOnClick();
+        mSmartListPresenter.newContactClicked();
         return true;
     }
 
@@ -264,22 +250,24 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
         return inflatedView;
     }
 
+    public void refresh() {
+        mSmartListPresenter.refresh(NetworkUtils.isConnectedWifi(getActivity()),
+                NetworkUtils.isConnectedMobile(getActivity()));
+    }
+
     @OnClick(R.id.newcontact_element)
     void newContactClicked(View v) {
-        mSmartListPresenter.newContactClicked((CallContact) v.getTag());
+        mSmartListPresenter.newContactClicked();
     }
 
     @OnClick(R.id.quick_call)
     void quickCallClicked(View v) {
-        CallContact callContact = (CallContact) mNewContact.getTag();
-        mSmartListPresenter.quickCallClicked(callContact);
+        mSmartListPresenter.quickCallClicked();
     }
 
     @OnClick(R.id.newconv_fab)
     void fabButtonClicked(View v) {
-        if (mSearchMenuItem != null) {
-            mSearchMenuItem.expandActionView();
-        }
+        mSmartListPresenter.fabButtonClicked();
     }
 
     @Override
@@ -400,13 +388,12 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
                 });
     }
 
-    public void displayNewContactRowWithName(final String name, final String address) {
+    @Override
+    public void displayNewContactRowWithName(final String name) {
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
                 ((TextView) mNewContact.findViewById(R.id.display_name)).setText(name);
-                CallContact contact = CallContact.buildUnknown(name, address);
-                mNewContact.setTag(contact);
                 mNewContact.setVisibility(View.VISIBLE);
             }
         });
@@ -466,6 +453,13 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
         dialog.show();
     }
 
+    @Override
+    public void displayMenuItem() {
+        if (mSearchMenuItem != null) {
+            mSearchMenuItem.expandActionView();
+        }
+    }
+
     @Override
     public void hideSearchRow() {
         getActivity().runOnUiThread(new Runnable() {
@@ -497,20 +491,20 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
     }
 
     @Override
-    public void updateView(final ArrayList<SmartListViewModel> list) {
+    public void updateList(final ArrayList<SmartListViewModel> smartListViewModels) {
         getActivity().runOnUiThread(new Runnable() {
             @Override
             public void run() {
-                if (mRecyclerView.getAdapter() != null) {
-                    mSmartListAdapter.replaceAll(list);
-                } else {
-                    mSmartListAdapter = new SmartListAdapter(list, SmartListFragment.this);
+                if (mRecyclerView.getAdapter() == null) {
+                    mSmartListAdapter = new SmartListAdapter(smartListViewModels, SmartListFragment.this);
                     mRecyclerView.setAdapter(mSmartListAdapter);
                     mRecyclerView.setHasFixedSize(true);
                     LinearLayoutManager llm = new LinearLayoutManager(getActivity());
                     llm.setOrientation(LinearLayoutManager.VERTICAL);
                     mRecyclerView.setLayoutManager(llm);
                 }
+                mSmartListAdapter.update(smartListViewModels);
+                setLoading(false);
             }
         });
     }
@@ -555,6 +549,16 @@ public class SmartListFragment extends BaseFragment<SmartListPresenter> implemen
         }
     }
 
+    @Override
+    public void scrollToTop() {
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mRecyclerView.scrollToPosition(0);
+            }
+        });
+    }
+
     @Override
     protected SmartListPresenter createPresenter() {
         return mSmartListPresenter;
diff --git a/ring-android/app/src/main/java/cx/ring/services/ContactServiceImpl.java b/ring-android/app/src/main/java/cx/ring/services/ContactServiceImpl.java
index dbb0eb972ebb3666c450e2b6d3c0c9b98e0067de..4c32d5e1fd086c3996892912ae3c76a3ce968e27 100644
--- a/ring-android/app/src/main/java/cx/ring/services/ContactServiceImpl.java
+++ b/ring-android/app/src/main/java/cx/ring/services/ContactServiceImpl.java
@@ -454,7 +454,7 @@ public class ContactServiceImpl extends ContactService {
             return new Tuple<>(contactName, byteArray);
         } catch (IOException e) {
             Log.w(TAG, "Error loading photo for system contact");
-            return null;
+            return new Tuple<>(contactName, null);
         }
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/services/HistoryServiceImpl.java b/ring-android/app/src/main/java/cx/ring/services/HistoryServiceImpl.java
index 09e9ad27790eddf9fc1484ebed97ed7423233d98..3fbdf6ec9ce85fd391eca1b70e251b7a267ae281 100644
--- a/ring-android/app/src/main/java/cx/ring/services/HistoryServiceImpl.java
+++ b/ring-android/app/src/main/java/cx/ring/services/HistoryServiceImpl.java
@@ -23,6 +23,7 @@ package cx.ring.services;
 
 import android.content.Context;
 import android.content.Intent;
+import android.text.format.DateUtils;
 import android.util.Log;
 
 import com.j256.ormlite.android.apptools.OpenHelperManager;
@@ -83,6 +84,11 @@ public class HistoryServiceImpl extends HistoryService {
         }
     }
 
+    @Override
+    public String getRelativeTimeSpanString(long lastInteraction) {
+        return DateUtils.getRelativeTimeSpanString(lastInteraction, System.currentTimeMillis(), 0L, DateUtils.FORMAT_ABBREV_ALL).toString();
+    }
+
     /**
      * Init Helper for our DB
      */
diff --git a/ring-android/app/src/main/res/layout/frag_smartlist.xml b/ring-android/app/src/main/res/layout/frag_smartlist.xml
index 6ba58abb3049be10be679af5bff8ded90e233a3e..1f0dcab5e8cf1e2f68f3db174f4e161b4c8be156 100644
--- a/ring-android/app/src/main/res/layout/frag_smartlist.xml
+++ b/ring-android/app/src/main/res/layout/frag_smartlist.xml
@@ -68,7 +68,8 @@ along with this program; if not, write to the Free Software
         android:layout_below="@+id/error_msg_pane"
         android:background="?android:attr/selectableItemBackground"
         android:orientation="vertical"
-        android:visibility="gone">
+        android:visibility="gone"
+        tools:visibility="visible">
 
         <include
             layout="@layout/item_contact"
diff --git a/ring-android/app/src/main/res/layout/item_smartlist.xml b/ring-android/app/src/main/res/layout/item_smartlist.xml
index be24571a0d6d3eeef21447ee549ce9db435c15a2..104b0467a6be169ea376c07811e217cd5b127775 100644
--- a/ring-android/app/src/main/res/layout/item_smartlist.xml
+++ b/ring-android/app/src/main/res/layout/item_smartlist.xml
@@ -32,12 +32,14 @@ along with this program; if not, write to the Free Software
 
     <ImageView
         android:id="@+id/photo"
-        android:layout_width="64dp"
-        android:layout_height="64dp"
+        android:layout_width="60dp"
+        android:layout_height="60dp"
         android:layout_marginEnd="16dp"
         android:layout_marginRight="16dp"
         android:layout_centerVertical="true"
-        android:padding="4dp"
+        android:paddingRight="4dp"
+        android:paddingEnd="4dp"
+        android:paddingBottom="4dp"
         android:background="@null"
         android:scaleType="fitCenter"
         android:src="@drawable/ic_contact_picture" />
diff --git a/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java b/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java
index 5e7f488fa38b20901b6b4eed22819255551f5df7..6a9ae1de6adf05250046e79307e690d335b611fd 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/facades/ConversationFacade.java
@@ -402,6 +402,10 @@ public class ConversationFacade extends Observable implements Observer<ServiceEv
         }
     }
 
+    public void removeConversation(String id) {
+        mConversationMap.remove(id);
+    }
+
     private void parseNewMessage(TextMessage txt, String call) {
         Conversation conversation;
         if (call != null && !call.isEmpty()) {
diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/ContactService.java b/ring-android/libringclient/src/main/java/cx/ring/services/ContactService.java
index a60a46b9c1e29afc0f2ebbb46c3121446f096e05..d2b3f3cc2a8f3e481f5ed1086f13dc7ca35084cb 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/services/ContactService.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/services/ContactService.java
@@ -55,8 +55,6 @@ import cx.ring.utils.Tuple;
  */
 public abstract class ContactService extends Observable {
 
-    public static final String CONTACT_NAME_KEY = "CONTACT_NAME";
-    public static final String CONTACT_PHOTO_KEY = "CONTACT_PHOTO";
     public static final String BANNED = "banned";
     public static final String CONFIRMED = "confirmed";
     public static final String ID = "id";
diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/HistoryService.java b/ring-android/libringclient/src/main/java/cx/ring/services/HistoryService.java
index 68927809969ce2244a7d7611a36bbad824fcf369..adfac17281774590d65987de7ac4ed3f534e012f 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/services/HistoryService.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/services/HistoryService.java
@@ -68,6 +68,8 @@ public abstract class HistoryService extends Observable {
 
     protected abstract Dao<HistoryText, Integer> getTextHistoryDao();
 
+    public abstract String getRelativeTimeSpanString(long lastInteraction);
+
     public boolean insertNewEntry(Conference toInsert) {
 
         for (SipCall call : toInsert.getParticipants()) {
diff --git a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListPresenter.java b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListPresenter.java
index b5d45fb2dc969578ebfff35db274574be477aea6..57a2d483a584e14c4b1e56780f53f8e181834511 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListPresenter.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListPresenter.java
@@ -21,8 +21,7 @@ package cx.ring.smartlist;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Date;
 import java.util.List;
 import java.util.Set;
 
@@ -69,6 +68,8 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
     private ArrayList<Conversation> mConversations;
     private ArrayList<SmartListViewModel> mSmartListViewModels;
 
+    private CallContact mCallContact;
+
     @Inject
     public SmartListPresenter(AccountService accountService, ContactService contactService,
                               HistoryService historyService, ConversationFacade conversationFacade,
@@ -135,12 +136,14 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
 
             if (currentAccount.isSip()) {
                 // sip search
-                getView().displayNewContactRowWithName(query, null);
+                mCallContact = CallContact.buildUnknown(query, null);
+                getView().displayNewContactRowWithName(query);
             } else {
 
                 Uri uri = new Uri(query);
                 if (uri.isRingId()) {
-                    getView().displayNewContactRowWithName(query, null);
+                    mCallContact = CallContact.buildUnknown(query, null);
+                    getView().displayNewContactRowWithName(query);
                 } else {
                     getView().hideSearchRow();
                 }
@@ -160,15 +163,15 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
             }
         }
 
-        getView().updateView(filter(mSmartListViewModels, query));
+        getView().updateList(filter(mSmartListViewModels, query));
         getView().setLoading(false);
     }
 
-    public void newContactClicked(CallContact callContact) {
-        if (callContact == null) {
+    public void newContactClicked() {
+        if (mCallContact == null) {
             return;
         }
-        startConversation(callContact);
+        startConversation(mCallContact);
     }
 
     public void conversationClicked(SmartListViewModel smartListViewModel) {
@@ -192,22 +195,26 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
         }
     }
 
-    public void quickCallClicked(CallContact callContact) {
-        if (callContact != null) {
-            if (callContact.getPhones().size() > 1) {
-                CharSequence numbers[] = new CharSequence[callContact.getPhones().size()];
+    public void quickCallClicked() {
+        if (mCallContact != null) {
+            if (mCallContact.getPhones().size() > 1) {
+                CharSequence numbers[] = new CharSequence[mCallContact.getPhones().size()];
                 int i = 0;
-                for (Phone p : callContact.getPhones()) {
+                for (Phone p : mCallContact.getPhones()) {
                     numbers[i++] = p.getNumber().getRawUriString();
                 }
 
                 getView().displayChooseNumberDialog(numbers);
             } else {
-                getView().goToCallActivity(callContact.getPhones().get(0).getNumber().getRawUriString());
+                getView().goToCallActivity(mCallContact.getPhones().get(0).getNumber().getRawUriString());
             }
         }
     }
 
+    public void fabButtonClicked() {
+        getView().displayMenuItem();
+    }
+
     public void startConversation(CallContact c) {
         mContactService.addContact(c);
         getView().goToConversation(c);
@@ -250,50 +257,28 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
             mConversations = new ArrayList<>();
         }
         subscribePresence();
+        mSmartListViewModels = new ArrayList<>();
         mConversations.clear();
         mConversations.addAll(mConversationFacade.getConversationsList());
         if (mConversations != null && mConversations.size() > 0) {
-            if (mSmartListViewModels == null) {
-                mSmartListViewModels = new ArrayList<>();
-            } else {
-                mSmartListViewModels.clear();
-            }
             for (int i = 0; i < mConversations.size(); i++) {
                 Conversation conversation = mConversations.get(i);
-                SmartListViewModel smartListViewModel = getSmartListViewModelByUuid(mSmartListViewModels, conversation.getUuid());
-                CallContact contact = conversation.getContact();
-
-                if (smartListViewModel == null || i >= mSmartListViewModels.size()) {
-
-                    if (conversation.getContact().isFromSystem()) {
-                        Tuple<String, String> tuple = mContactService.loadContactDataFromSystem(contact);
-                        smartListViewModel = new SmartListViewModel(conversation, tuple.first, tuple.second, null);
-                    } else {
-                        Tuple<String, byte[]> tuple = mContactService.loadContactData(contact);
-                        smartListViewModel = new SmartListViewModel(conversation, tuple.first, null, tuple.second);
-                    }
+                SmartListViewModel smartListViewModel;
+                long lastInteractionTime = conversation.getLastInteraction().getTime();
+                String lastInteraction = lastInteractionTime == new Date(0).getTime() ?
+                        "" : mHistoryService.getRelativeTimeSpanString(lastInteractionTime);
+                Tuple<String, byte[]> tuple = mContactService.loadContactData(conversation.getContact());
+                if (tuple != null) {
+                    smartListViewModel = new SmartListViewModel(conversation,
+                            tuple.first,
+                            tuple.second,
+                            lastInteraction);
                     smartListViewModel.setOnline(mPresenceService.isBuddyOnline(conversation.getContact().getIds().get(0)));
                     mSmartListViewModels.add(smartListViewModel);
-                } else {
-                    smartListViewModel.setOnline(mPresenceService.isBuddyOnline(conversation.getContact().getIds().get(0)));
-                    if (conversation.getContact().isFromSystem()) {
-                        Tuple<String, String> tuple = mContactService.loadContactDataFromSystem(conversation.getContact());
-                        smartListViewModel.update(conversation, tuple.first, tuple.second, null);
-                    } else {
-                        Tuple<String, byte[]> tuple = mContactService.loadContactData(contact);
-                        smartListViewModel.update(conversation, tuple.first, null, tuple.second);
-                    }
                 }
             }
 
-            Collections.sort(mSmartListViewModels, new Comparator<SmartListViewModel>() {
-                @Override
-                public int compare(SmartListViewModel lhs, SmartListViewModel rhs) {
-                    return (int) ((rhs.getLastInteractionTime() - lhs.getLastInteractionTime()) / 1000l);
-                }
-            });
-
-            getView().updateView(mSmartListViewModels);
+            getView().updateList(mSmartListViewModels);
             getView().hideNoConversationMessage();
             getView().setLoading(false);
         } else {
@@ -324,21 +309,13 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
         return null;
     }
 
-    private SmartListViewModel getSmartListViewModelByUuid(ArrayList<SmartListViewModel> smartListViewModels, String uuid) {
-        for (SmartListViewModel smartListViewModel : smartListViewModels) {
-            if (smartListViewModel.getUuid().equals(uuid)) {
-                return smartListViewModel;
-            }
-        }
-        return null;
-    }
-
     private void parseEventState(String name, String address, int state) {
         switch (state) {
             case 0:
                 // on found
                 if (mLastBlockchainQuery != null && mLastBlockchainQuery.equals(name)) {
-                    getView().displayNewContactRowWithName(name, address);
+                    mCallContact = CallContact.buildUnknown(name, address);
+                    getView().displayNewContactRowWithName(name);
                     mLastBlockchainQuery = null;
                 } else {
                     if (name.equals("") || address.equals("")) {
@@ -346,7 +323,6 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
                     }
                     getView().hideSearchRow();
                     mConversationFacade.updateConversationContactWithRingId(name, address);
-                    displayConversations();
                 }
                 break;
             case 1:
@@ -355,7 +331,8 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
                 if (uriName.isRingId()
                         && mLastBlockchainQuery != null
                         && mLastBlockchainQuery.equals(name)) {
-                    getView().displayNewContactRowWithName(name, null);
+                    mCallContact = CallContact.buildUnknown(name, address);
+                    getView().displayNewContactRowWithName(name);
                 } else {
                     getView().hideSearchRow();
                 }
@@ -366,7 +343,8 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
                 if (uriAddress.isRingId()
                         && mLastBlockchainQuery != null
                         && mLastBlockchainQuery.equals(name)) {
-                    getView().displayNewContactRowWithName(address, null);
+                    mCallContact = CallContact.buildUnknown(name, address);
+                    getView().displayNewContactRowWithName(name);
                 } else {
                     getView().hideSearchRow();
                 }
@@ -411,10 +389,10 @@ public class SmartListPresenter extends RootPresenter<SmartListView> implements
                 int state = event.getEventInput(ServiceEvent.EventInput.STATE, Integer.class);
                 parseEventState(name, address, state);
                 break;
-            case INCOMING_MESSAGE:
             case HISTORY_LOADED:
             case CONVERSATIONS_CHANGED:
                 displayConversations();
+                getView().scrollToTop();
                 break;
         }
 
diff --git a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListView.java b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListView.java
index 67db8f86ba65ff534dca5c265d6280cbdf99f75d..6428160a509a73613417e6b27cf825e1f4d717bb 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListView.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListView.java
@@ -31,7 +31,7 @@ public interface SmartListView {
 
     void displayMobileDataPanel();
 
-    void displayNewContactRowWithName(String name, String address);
+    void displayNewContactRowWithName(String name);
 
     void displayChooseNumberDialog(CharSequence numbers[]);
 
@@ -41,13 +41,15 @@ public interface SmartListView {
 
     void setLoading(boolean display);
 
+    void displayMenuItem();
+
     void hideSearchRow();
 
     void hideErrorPanel();
 
     void hideNoConversationMessage();
 
-    void updateView(ArrayList<SmartListViewModel> list);
+    void updateList(ArrayList<SmartListViewModel> smartListViewModels);
 
     void goToConversation(CallContact callContact);
 
@@ -56,4 +58,6 @@ public interface SmartListView {
     void goToQRActivity();
 
     void goToContact(CallContact callContact);
+
+    void scrollToTop();
 }
diff --git a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListViewModel.java b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListViewModel.java
index f94fe58b625a770830d9630d59dab11e2008f41f..6d2092624e499b19b53ef7dc76995caf612bdc34 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListViewModel.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/smartlist/SmartListViewModel.java
@@ -19,69 +19,97 @@
  */
 package cx.ring.smartlist;
 
+import java.util.Arrays;
+
 import cx.ring.model.CallContact;
 import cx.ring.model.Conversation;
+import cx.ring.model.HistoryCall;
 import cx.ring.model.HistoryEntry;
+import cx.ring.model.TextMessage;
 
 public class SmartListViewModel {
 
+    public static final int TYPE_INCOMING_MESSAGE = 0;
+    public static final int TYPE_OUTGOING_MESSAGE = 1;
+    public static final int TYPE_INCOMING_CALL = 2;
+    public static final int TYPE_OUTGOING_CALL = 3;
+
     private String uuid;
     private String contactName;
-    private HistoryEntry lastInteraction;
-    private String photoUri;
+    private String lastInteraction = "";
     private byte[] photoData;
-    private long lastInteractionTime;
+    private String lastInteractionTime;
     private boolean hasUnreadTextMessage;
     private boolean hasOngoingCall;
     private CallContact.Status status;
     private boolean isOnline = false;
+    private int lastEntryType;
 
-    public SmartListViewModel(Conversation conversation, String contactName, String photoUri, byte[] photoData) {
+    public SmartListViewModel(Conversation conversation, String contactName, byte[] photoData, String lastInteractionTime) {
         this.uuid = conversation.getUuid();
-        setData(conversation, contactName, photoUri, photoData);
-    }
-
-    public void update(Conversation conversation, String contactName, String photoUri, byte[] photoData) {
-        setData(conversation, contactName, photoUri, photoData);
-    }
-
-    private void setData(Conversation conversation, String contactName, String photoUri, byte[] photoData) {
         this.contactName = contactName;
-        this.photoUri = photoUri;
         this.photoData = photoData;
+        this.lastInteractionTime = lastInteractionTime;
+        this.hasUnreadTextMessage = conversation.hasUnreadTextMessages();
+        this.hasOngoingCall = conversation.hasCurrentCall();
+        this.status = conversation.getContact().getStatus();
 
         for (HistoryEntry historyEntry : conversation.getHistory().values()) {
             long lastTextTimestamp = historyEntry.getTextMessages().isEmpty() ? 0 : historyEntry.getTextMessages().lastEntry().getKey();
             long lastCallTimestamp = historyEntry.getCalls().isEmpty() ? 0 : historyEntry.getCalls().lastEntry().getKey();
-            if (lastTextTimestamp > 0 && lastTextTimestamp > lastCallTimestamp) {
-                this.lastInteraction = historyEntry;
+            if (lastTextTimestamp == conversation.getLastInteraction().getTime()
+                    && lastTextTimestamp > 0
+                    && lastTextTimestamp > lastCallTimestamp) {
+                TextMessage msg = historyEntry.getTextMessages().lastEntry().getValue();
+                String msgString = msg.getMessage();
+                if (msgString != null && !msgString.isEmpty() && msgString.contains("\n")) {
+                    int lastIndexOfChar = msgString.lastIndexOf("\n");
+                    if (lastIndexOfChar + 1 < msgString.length()) {
+                        msgString = msgString.substring(msgString.lastIndexOf("\n") + 1);
+                    }
+                }
+                this.lastEntryType = msg.isIncoming() ? TYPE_INCOMING_MESSAGE : TYPE_OUTGOING_MESSAGE;
+                this.lastInteraction = msgString;
                 break;
             }
-            if (lastCallTimestamp > 0) {
-                this.lastInteraction = historyEntry;
+            if (lastCallTimestamp == conversation.getLastInteraction().getTime()
+                    && lastCallTimestamp > 0) {
+                HistoryCall lastCall = historyEntry.getCalls().lastEntry().getValue();
+                this.lastEntryType = lastCall.isIncoming() ? TYPE_INCOMING_CALL : TYPE_OUTGOING_CALL;
+                this.lastInteraction = lastCall.getDurationString();
                 break;
             }
         }
+    }
 
-        this.lastInteractionTime = conversation.getLastInteraction().getTime();
-        this.hasUnreadTextMessage = conversation.hasUnreadTextMessages();
-        this.hasOngoingCall = conversation.hasCurrentCall();
-        this.status = conversation.getContact().getStatus();
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof SmartListViewModel) {
+            SmartListViewModel slvm = (SmartListViewModel) o;
+            return !(this.photoData != null && !Arrays.equals(this.photoData, slvm.photoData))
+                    && this.uuid.equals(slvm.getUuid())
+                    && this.contactName.equals(slvm.getContactName())
+                    && this.lastInteraction.equals(slvm.getLastInteraction())
+                    && this.lastInteractionTime.equals(slvm.getLastInteractionTime())
+                    && this.hasUnreadTextMessage == slvm.hasUnreadTextMessage()
+                    && this.hasOngoingCall == slvm.hasOngoingCall()
+                    && this.lastEntryType == slvm.getLastEntryType()
+                    && this.isOnline == slvm.isOnline()
+                    && this.status == slvm.getStatus();
+        } else {
+            return false;
+        }
     }
 
     public String getContactName() {
         return contactName;
     }
 
-    public HistoryEntry getLastInteraction() {
+    public String getLastInteraction() {
         return lastInteraction;
     }
 
-    public String getPhotoUri() {
-        return photoUri;
-    }
-
-    public long getLastInteractionTime() {
+    public String getLastInteractionTime() {
         return lastInteractionTime;
     }
 
@@ -112,4 +140,8 @@ public class SmartListViewModel {
     public void setOnline(boolean online) {
         isOnline = online;
     }
+
+    public int getLastEntryType() {
+        return lastEntryType;
+    }
 }