From cdcbbbb056a25412ec3570386fd5ce413485d157 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Mon, 17 May 2021 15:56:20 -0400
Subject: [PATCH] tablet: add conversation selection

Change-Id: I1c0a7078031133e7442699720a4fb9874e47cced
---
 .../cx/ring/adapters/SmartListAdapter.java    |   9 +-
 .../cx/ring/application/JamiApplication.java  |   4 +
 .../client/ConversationSelectionActivity.java |   4 +-
 .../java/cx/ring/client/HomeActivity.java     | 105 +++++++++++++++---
 .../ContactRequestsFragment.java              |   5 +-
 .../ring/fragments/ContactPickerFragment.java |   2 +-
 .../ring/fragments/ConversationFragment.java  |  16 ++-
 .../cx/ring/fragments/ShareWithFragment.java  |   2 +-
 .../cx/ring/fragments/SmartListFragment.java  |   5 +-
 .../ring/viewholders/SmartListViewHolder.java |  11 +-
 .../drawable/background_item_smartlist.xml    |  14 +++
 .../src/main/res/layout/item_smartlist.xml    |   4 +-
 .../ContactRequestsPresenter.java             |   2 +-
 .../contactrequests/ContactRequestsView.java  |   4 +-
 .../conversation/ConversationPresenter.java   |   4 +-
 .../java/net/jami/model/Conversation.java     |   6 +
 .../jami/smartlist/SmartListPresenter.java    |   2 +-
 .../net/jami/smartlist/SmartListView.java     |   8 +-
 .../jami/smartlist/SmartListViewModel.java    |   4 +
 19 files changed, 170 insertions(+), 41 deletions(-)
 create mode 100644 ring-android/app/src/main/res/drawable/background_item_smartlist.xml

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 4d8c77179..2ed8a07ee 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
@@ -24,6 +24,7 @@ import cx.ring.databinding.ItemSmartlistBinding;
 import cx.ring.databinding.ItemSmartlistHeaderBinding;
 import net.jami.smartlist.SmartListViewModel;
 import cx.ring.viewholders.SmartListViewHolder;
+import io.reactivex.disposables.CompositeDisposable;
 
 import android.os.Parcelable;
 import android.view.LayoutInflater;
@@ -40,10 +41,12 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
 
     private List<SmartListViewModel> mSmartListViewModels = new ArrayList<>();
     private final SmartListViewHolder.SmartListListeners listener;
+    private final CompositeDisposable mDisposable;
     private RecyclerView recyclerView;
 
-    public SmartListAdapter(List<SmartListViewModel> smartListViewModels, SmartListViewHolder.SmartListListeners listener) {
+    public SmartListAdapter(List<SmartListViewModel> smartListViewModels, SmartListViewHolder.SmartListListeners listener, CompositeDisposable disposable) {
         this.listener = listener;
+        mDisposable = disposable;
         if (smartListViewModels != null)
             mSmartListViewModels.addAll(smartListViewModels);
     }
@@ -54,10 +57,10 @@ public class SmartListAdapter extends RecyclerView.Adapter<SmartListViewHolder>
         LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
         if (viewType == 0) {
             ItemSmartlistBinding itemBinding = ItemSmartlistBinding.inflate(layoutInflater, parent, false);
-            return new SmartListViewHolder(itemBinding);
+            return new SmartListViewHolder(itemBinding, mDisposable);
         } else {
             ItemSmartlistHeaderBinding itemBinding = ItemSmartlistHeaderBinding.inflate(layoutInflater, parent, false);
-            return new SmartListViewHolder(itemBinding);
+            return new SmartListViewHolder(itemBinding, mDisposable);
         }
     }
 
diff --git a/ring-android/app/src/main/java/cx/ring/application/JamiApplication.java b/ring-android/app/src/main/java/cx/ring/application/JamiApplication.java
index fd7797cea..0d0e03abf 100644
--- a/ring-android/app/src/main/java/cx/ring/application/JamiApplication.java
+++ b/ring-android/app/src/main/java/cx/ring/application/JamiApplication.java
@@ -343,6 +343,10 @@ public abstract class JamiApplication extends Application {
         return mHardwareService;
     }
 
+    public ConversationFacade getFacade() {
+        return mConversationFacade;
+    }
+
     private void setupActivityListener() {
         registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
 
diff --git a/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.java b/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.java
index 3f464ecfc..5d0a7cc11 100644
--- a/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/ConversationSelectionActivity.java
@@ -53,7 +53,7 @@ import io.reactivex.disposables.CompositeDisposable;
 public class ConversationSelectionActivity extends AppCompatActivity {
     private final static String TAG = ConversationSelectionActivity.class.getSimpleName();
 
-    private CompositeDisposable mDisposable = new CompositeDisposable();
+    private final CompositeDisposable mDisposable = new CompositeDisposable();
 
     @Inject
     @Singleton
@@ -90,7 +90,7 @@ public class ConversationSelectionActivity extends AppCompatActivity {
             @Override
             public void onItemLongClick(SmartListViewModel smartListViewModel) {
             }
-        });
+        }, mDisposable);
         list.setLayoutManager(new LinearLayoutManager(this));
         list.setAdapter(adapter);
     }
diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
index 893a8cf8c..9024023ae 100644
--- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
@@ -49,11 +49,13 @@ import androidx.fragment.app.FragmentTransaction;
 import com.google.android.material.bottomnavigation.BottomNavigationView;
 import com.google.android.material.dialog.MaterialAlertDialogBuilder;
 
+import net.jami.facades.ConversationFacade;
 import net.jami.model.Account;
 import net.jami.model.AccountConfig;
 import net.jami.model.Conversation;
 import net.jami.services.AccountService;
 import net.jami.services.NotificationService;
+import net.jami.smartlist.SmartListViewModel;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -87,6 +89,7 @@ import cx.ring.utils.ContentUriHandler;
 import cx.ring.utils.ConversationPath;
 import cx.ring.utils.DeviceUtils;
 import cx.ring.views.SwitchButton;
+import io.reactivex.Observable;
 import io.reactivex.android.schedulers.AndroidSchedulers;
 import io.reactivex.disposables.CompositeDisposable;
 import io.reactivex.schedulers.Schedulers;
@@ -195,7 +198,7 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
         }
 
         // if app opened from notification display trust request fragment when mService will connected
-        Intent intent = getIntent();
+        /*Intent intent = getIntent();
         Bundle extra = intent.getExtras();
         String action = intent.getAction();
         if (ACTION_PRESENT_TRUST_REQUEST_FRAGMENT.equals(action)) {
@@ -213,13 +216,12 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
             fragmentManager.beginTransaction()
                     .replace(R.id.main_frame, fContent, HOME_TAG)
                     .commitNow();
-        } else if (fContent instanceof Refreshable) {
-            ((Refreshable) fContent).refresh();
         }
         if (mAccountWithPendingrequests != null) {
             presentTrustRequestFragment(mAccountWithPendingrequests);
             mAccountWithPendingrequests = null;
-        }
+        }*/
+        handleIntent(getIntent());
     }
 
     @Override
@@ -251,7 +253,7 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
-        Log.d(TAG, "onNewIntent: " + intent);
+        /*Log.d(TAG, "onNewIntent: " + intent);
         String action = intent.getAction();
         if (ACTION_PRESENT_TRUST_REQUEST_FRAGMENT.equals(action)) {
             Bundle extra = intent.getExtras();
@@ -265,11 +267,51 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
             if (fContent instanceof SmartListFragment) {
                 ((SmartListFragment)fContent).handleIntent(intent);
             }
-        } else if (DRingService.ACTION_CONV_ACCEPT.equals(action))  {
-            if (DeviceUtils.isTablet(this)) {
+        } else if (DRingService.ACTION_CONV_ACCEPT.equals(action) || Intent.ACTION_VIEW.equals(action))  {
+            startConversation(ConversationPath.fromIntent(intent));
+        }*/
+    }
+
+    private void handleIntent(Intent intent) {
+        Log.d(TAG, "handleIntent: " + intent);
+        Bundle extra = intent.getExtras();
+        String action = intent.getAction();
+        if (ACTION_PRESENT_TRUST_REQUEST_FRAGMENT.equals(action)) {
+            if (extra == null || extra.getString(ContactRequestsFragment.ACCOUNT_ID) == null) {
+                return;
+            }
+            //mAccountWithPendingrequests = extra.getString(ContactRequestsFragment.ACCOUNT_ID);
+            presentTrustRequestFragment(extra.getString(ContactRequestsFragment.ACCOUNT_ID));
+        } else if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
+            ConversationPath path = ConversationPath.fromBundle(extra);
+            if (path != null) {
+
+                intent.setClass(this, ConversationActivity.class);
+                startActivity(intent);
+            }
+        } else if (DRingService.ACTION_CONV_ACCEPT.equals(action) || Intent.ACTION_VIEW.equals(action))  {
+            startConversation(ConversationPath.fromIntent(intent));
+            /*if (DeviceUtils.isTablet(this)) {
                 startConversationTablet(ConversationPath.fromIntent(intent).toBundle());
+            }*/
+        } //else {
+            FragmentManager fragmentManager = getSupportFragmentManager();
+            fContent = fragmentManager.findFragmentById(R.id.main_frame);
+            if (fContent == null || Intent.ACTION_SEARCH.equals(action)) {
+                if (fContent instanceof SmartListFragment) {
+                    ((SmartListFragment)fContent).handleIntent(intent);
+                } else {
+                    fContent = new SmartListFragment();
+                    fragmentManager.beginTransaction()
+                            .replace(R.id.main_frame, fContent, HOME_TAG)
+                            .commitNow();
+                }
             }
-        }
+            /*if (mAccountWithPendingrequests != null) {
+                presentTrustRequestFragment(mAccountWithPendingrequests);
+                mAccountWithPendingrequests = null;
+            }*/
+        //}
     }
 
     private void showMigrationDialog() {
@@ -370,6 +412,39 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
             if (DeviceUtils.isTablet(this)) {
                 selectNavigationItem(R.id.navigation_home);
                 showTabletToolbar();
+            } else {
+                // Remove ConversationFragment that might have been restored after an orientation change
+                if (fConversation == null)
+                    fConversation = (ConversationFragment) getSupportFragmentManager().findFragmentByTag(ConversationFragment.class.getSimpleName());
+                if (fConversation != null) {
+                   // fConversation = null;
+                   // getSupportFragmentManager().findFragmentByTag(ConversationFragment.class.getSimpleName());
+                    getSupportFragmentManager().beginTransaction().remove(fConversation).commitNow();
+                    fConversation = null;
+                }
+            }
+        }
+
+        // Select first conversation in tablet mode
+        if (DeviceUtils.isTablet(this)) {
+            Intent intent = getIntent();
+            Uri uri = intent == null ? null : intent.getData();
+            if ((intent == null || uri == null) && fConversation == null) {
+                ConversationFacade facade = ((JamiApplication) getApplication()).getFacade();
+                Observable<List<Observable<SmartListViewModel>>> smartlist = null;
+                if (fContent instanceof SmartListFragment)
+                    smartlist = facade.getSmartList(false);
+                else if (fContent instanceof ContactRequestsFragment)
+                    smartlist = facade.getPendingList();
+
+                if (smartlist != null) {
+                    mDisposable.add(smartlist
+                            .filter(list -> !list.isEmpty())
+                            .map(list -> list.get(0).firstOrError())
+                            .firstElement()
+                            .flatMapSingle(e -> e)
+                            .subscribe(element -> startConversation(element.getAccountId(), element.getUri())));
+                }
             }
         }
     }
@@ -387,11 +462,14 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
                 .subscribe(account -> startConversation(account.getAccountID(), net.jami.model.Uri.fromString(conversationId))));
     }
     public void startConversation(String accountId, net.jami.model.Uri conversationId) {
-        Log.w(TAG, "startConversation " + accountId + " " + conversationId);
+        startConversation(new ConversationPath(accountId, conversationId));
+    }
+    public void startConversation(ConversationPath path) {
+        Log.w(TAG, "startConversation " + path);
         if (!DeviceUtils.isTablet(this)) {
-            startActivity(new Intent(Intent.ACTION_VIEW, ConversationPath.toUri(accountId, conversationId), this, ConversationActivity.class));
+            startActivity(new Intent(Intent.ACTION_VIEW, path.toUri(), this, ConversationActivity.class));
         } else {
-            startConversationTablet(ConversationPath.toBundle(accountId, conversationId));
+            startConversationTablet(path.toBundle());
         }
     }
 
@@ -399,7 +477,6 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
         fConversation = new ConversationFragment();
         fConversation.setArguments(bundle);
 
-        //getSupportFragmentManager().get
         if (!(fContent instanceof ContactRequestsFragment)) {
             selectNavigationItem(R.id.navigation_home);
         }
@@ -584,10 +661,6 @@ public class HomeActivity extends AppCompatActivity implements BottomNavigationV
 
     }
 
-    public interface Refreshable {
-        void refresh();
-    }
-
     public void setBadge(int menuId, int number) {
         if (number == 0)
             mBinding.navigationView.removeBadge(menuId);
diff --git a/ring-android/app/src/main/java/cx/ring/contactrequests/ContactRequestsFragment.java b/ring-android/app/src/main/java/cx/ring/contactrequests/ContactRequestsFragment.java
index 177a6b73d..a8171d6b5 100644
--- a/ring-android/app/src/main/java/cx/ring/contactrequests/ContactRequestsFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/contactrequests/ContactRequestsFragment.java
@@ -45,6 +45,7 @@ import cx.ring.mvp.BaseSupportFragment;
 import net.jami.smartlist.SmartListViewModel;
 
 import cx.ring.viewholders.SmartListViewHolder;
+import io.reactivex.disposables.CompositeDisposable;
 
 public class ContactRequestsFragment extends BaseSupportFragment<ContactRequestsPresenter> implements ContactRequestsView,
         SmartListViewHolder.SmartListListeners {
@@ -100,7 +101,7 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
     }
 
     @Override
-    public void updateView(final List<SmartListViewModel> list) {
+    public void updateView(final List<SmartListViewModel> list, CompositeDisposable disposable) {
         if (binding == null) {
             return;
         }
@@ -114,7 +115,7 @@ public class ContactRequestsFragment extends BaseSupportFragment<ContactRequests
         if (binding.requestsList.getAdapter() != null) {
             mAdapter.update(list);
         } else {
-            mAdapter = new SmartListAdapter(list, ContactRequestsFragment.this);
+            mAdapter = new SmartListAdapter(list, ContactRequestsFragment.this, disposable);
             binding.requestsList.setAdapter(mAdapter);
             LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
             binding.requestsList.setLayoutManager(mLayoutManager);
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ContactPickerFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ContactPickerFragment.java
index 9e61d435c..e7b51b4c9 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ContactPickerFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ContactPickerFragment.java
@@ -141,7 +141,7 @@ public class ContactPickerFragment extends BottomSheetDialogFragment {
             public void onItemLongClick(SmartListViewModel item) {
 
             }
-        });
+        }, mDisposableBag);
         binding.createGroupBtn.setOnClickListener(v -> mDisposableBag.add(mConversationFacade.createConversation(mAccountId, mCurrentSelection)
                 .observeOn(AndroidSchedulers.mainThread())
                 .subscribe(conversation -> {
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.java
index 466512b85..034e88443 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ConversationFragment.java
@@ -833,16 +833,28 @@ public class ConversationFragment extends BaseSupportFragment<ConversationPresen
         presenter.clickOnGoingPane();
     }
 
+    @Override
+    public void onStart() {
+        super.onStart();
+        presenter.resume(mIsBubble);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        presenter.pause();
+    }
+
     @Override
     public void onPause() {
         super.onPause();
-        presenter.pause();
+        //presenter.pause();
     }
 
     @Override
     public void onResume() {
         super.onResume();
-        presenter.resume(mIsBubble);
+        //presenter.resume(mIsBubble);
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ShareWithFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ShareWithFragment.java
index e012290d9..75738a0cf 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ShareWithFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ShareWithFragment.java
@@ -156,7 +156,7 @@ public class ShareWithFragment extends Fragment {
             public void onItemLongClick(SmartListViewModel smartListViewModel) {
 
             }
-        });
+        }, mDisposable);
         list.setLayoutManager(new LinearLayoutManager(context));
         list.setAdapter(adapter);
         return view;
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 4bb7dd86f..bf708184b 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
@@ -74,6 +74,7 @@ import cx.ring.utils.ClipboardHelper;
 import cx.ring.utils.ConversationPath;
 import cx.ring.utils.DeviceUtils;
 import cx.ring.viewholders.SmartListViewHolder;
+import io.reactivex.disposables.CompositeDisposable;
 
 public class SmartListFragment extends BaseSupportFragment<SmartListPresenter> implements SearchView.OnQueryTextListener,
         SmartListViewHolder.SmartListListeners,
@@ -391,11 +392,11 @@ public class SmartListFragment extends BaseSupportFragment<SmartListPresenter> i
     }
 
     @Override
-    public void updateList(@Nullable final List<SmartListViewModel> smartListViewModels) {
+    public void updateList(@Nullable final List<SmartListViewModel> smartListViewModels, CompositeDisposable parentDisposable) {
         if (binding == null)
             return;
         if (binding.confsList.getAdapter() == null) {
-            mSmartListAdapter = new SmartListAdapter(smartListViewModels, SmartListFragment.this);
+            mSmartListAdapter = new SmartListAdapter(smartListViewModels, SmartListFragment.this, parentDisposable);
             binding.confsList.setAdapter(mSmartListAdapter);
             binding.confsList.setHasFixedSize(true);
             LinearLayoutManager llm = new LinearLayoutManager(getActivity());
diff --git a/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.java b/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.java
index d5c2a8e34..61e03b2d4 100644
--- a/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.java
+++ b/ring-android/app/src/main/java/cx/ring/viewholders/SmartListViewHolder.java
@@ -47,16 +47,18 @@ public class SmartListViewHolder extends RecyclerView.ViewHolder {
     public final ItemSmartlistHeaderBinding headerBinding;
     private final CompositeDisposable compositeDisposable = new CompositeDisposable();
 
-    public SmartListViewHolder(@NonNull ItemSmartlistBinding b) {
+    public SmartListViewHolder(@NonNull ItemSmartlistBinding b, @NonNull CompositeDisposable parentDisposable) {
         super(b.getRoot());
         binding = b;
         headerBinding = null;
+        parentDisposable.add(compositeDisposable);
     }
 
-    public SmartListViewHolder(@NonNull ItemSmartlistHeaderBinding b) {
+    public SmartListViewHolder(@NonNull ItemSmartlistHeaderBinding b, @NonNull CompositeDisposable parentDisposable) {
         super(b.getRoot());
         binding = null;
         headerBinding = b;
+        parentDisposable.add(compositeDisposable);
     }
 
     public void bind(final SmartListListeners clickListener, final SmartListViewModel smartListViewModel) {
@@ -67,6 +69,10 @@ public class SmartListViewHolder extends RecyclerView.ViewHolder {
             compositeDisposable.add(Observable.create(e -> itemView.setOnClickListener(e::onNext))
                     .throttleFirst(1000, TimeUnit.MILLISECONDS)
                     .subscribe(v -> clickListener.onItemClick(smartListViewModel)));
+            Observable<Boolean> isSelected = smartListViewModel.getSelected();
+            if (isSelected != null) {
+                compositeDisposable.add(isSelected.subscribe(binding.itemLayout::setActivated));
+            }
             itemView.setOnLongClickListener(v -> {
                 clickListener.onItemLongClick(smartListViewModel);
                 return true;
@@ -101,6 +107,7 @@ public class SmartListViewHolder extends RecyclerView.ViewHolder {
                     .withViewModel(smartListViewModel)
                     .withCircleCrop(true)
                     .build(binding.photo.getContext()));
+
         } else if (headerBinding != null) {
             headerBinding.headerTitle.setText(smartListViewModel.getHeaderTitle() == SmartListViewModel.Title.Conversations
                     ? R.string.navigation_item_conversation : R.string.search_results_public_directory);
diff --git a/ring-android/app/src/main/res/drawable/background_item_smartlist.xml b/ring-android/app/src/main/res/drawable/background_item_smartlist.xml
new file mode 100644
index 000000000..985e870cc
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/background_item_smartlist.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="?attr/colorControlHighlight">
+    <item>
+        <selector
+            android:exitFadeDuration="@android:integer/config_mediumAnimTime">
+            <item
+                android:drawable="@color/transparent_grey"
+                android:state_activated="true" />
+
+            <item android:drawable="@color/background" />
+        </selector>
+    </item>
+</ripple>
\ No newline at end of file
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 21967cdb1..b4f8578f4 100644
--- a/ring-android/app/src/main/res/layout/item_smartlist.xml
+++ b/ring-android/app/src/main/res/layout/item_smartlist.xml
@@ -19,10 +19,10 @@ along with this program; if not, write to the Free Software
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/call_entry"
+    android:id="@+id/item_layout"
     android:layout_width="match_parent"
     android:layout_height="72dp"
-    android:background="?android:attr/selectableItemBackground"
+    android:background="@drawable/background_item_smartlist"
     android:descendantFocusability="blocksDescendants"
     android:paddingLeft="16dp"
     android:paddingTop="8dp"
diff --git a/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsPresenter.java b/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsPresenter.java
index a59891e68..4c66792b5 100644
--- a/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsPresenter.java
+++ b/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsPresenter.java
@@ -64,7 +64,7 @@ public class ContactRequestsPresenter extends RootPresenter<net.jami.contactrequ
                     return vms;
                 }))
                 .observeOn(mUiScheduler)
-                .subscribe(viewModels -> getView().updateView(viewModels),
+                .subscribe(viewModels -> getView().updateView(viewModels, mCompositeDisposable),
                         e -> Log.d(TAG, "updateList subscribe onError", e)));
     }
 
diff --git a/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsView.java b/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsView.java
index 1f96a6163..b94d7ad23 100644
--- a/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsView.java
+++ b/ring-android/libringclient/src/main/java/net/jami/contactrequests/ContactRequestsView.java
@@ -24,9 +24,11 @@ import java.util.List;
 import net.jami.model.Uri;
 import net.jami.smartlist.SmartListViewModel;
 
+import io.reactivex.disposables.CompositeDisposable;
+
 public interface ContactRequestsView {
 
-    void updateView(List<SmartListViewModel> list);
+    void updateView(List<SmartListViewModel> list, CompositeDisposable disposable);
     void updateItem(SmartListViewModel item);
 
     void goToConversation(String accountId, Uri contactId);
diff --git a/ring-android/libringclient/src/main/java/net/jami/conversation/ConversationPresenter.java b/ring-android/libringclient/src/main/java/net/jami/conversation/ConversationPresenter.java
index 9624e69f2..0e793ccc5 100644
--- a/ring-android/libringclient/src/main/java/net/jami/conversation/ConversationPresenter.java
+++ b/ring-android/libringclient/src/main/java/net/jami/conversation/ConversationPresenter.java
@@ -120,8 +120,8 @@ public class ConversationPresenter extends RootPresenter<ConversationView> {
         Log.w(TAG, "setConversation " + conversation.getAggregateHistory().size());
         if (mConversation == conversation)
             return;
-        if (mConversation != null)
-            mConversation.setVisible(false);
+        //if (mConversation != null)
+        //    mConversation.setVisible(false);
         mConversation = conversation;
         mConversationSubject.onNext(conversation);
         ConversationView view = getView();
diff --git a/ring-android/libringclient/src/main/java/net/jami/model/Conversation.java b/ring-android/libringclient/src/main/java/net/jami/model/Conversation.java
index 37a24d1a1..0aa215df5 100644
--- a/ring-android/libringclient/src/main/java/net/jami/model/Conversation.java
+++ b/ring-android/libringclient/src/main/java/net/jami/model/Conversation.java
@@ -75,6 +75,7 @@ public class Conversation extends ConversationHistory {
 
     // runtime flag set to true if the user is currently viewing this conversation
     private boolean mVisible = false;
+    private final Subject<Boolean> mVisibleSubject = BehaviorSubject.createDefault(mVisible);
 
     // indicate the list needs sorting
     private boolean mDirty = false;
@@ -294,6 +295,10 @@ public class Conversation extends ConversationHistory {
         return mVisible;
     }
 
+    public Observable<Boolean> getVisible()  {
+        return mVisibleSubject;
+    }
+
     public void setLoaded(Single<Conversation> loaded) {
         isLoaded = loaded;
     }
@@ -304,6 +309,7 @@ public class Conversation extends ConversationHistory {
 
     public void setVisible(boolean visible) {
         mVisible = visible;
+        mVisibleSubject.onNext(mVisible);
     }
 
     public List<Contact> getContacts() {
diff --git a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListPresenter.java b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListPresenter.java
index a643e2427..da3d8043b 100644
--- a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListPresenter.java
+++ b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListPresenter.java
@@ -184,7 +184,7 @@ public class SmartListPresenter extends RootPresenter<SmartListView> {
                         return;
                     }
                     view.hideNoConversationMessage();
-                    view.updateList(viewModels);
+                    view.updateList(viewModels, mConversationDisposable);
                 }, e -> Log.w(TAG, "showConversations error ", e)));
     }
 
diff --git a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListView.java b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListView.java
index 936707378..8664c5fb6 100644
--- a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListView.java
+++ b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListView.java
@@ -24,13 +24,15 @@ import java.util.List;
 import net.jami.model.Uri;
 import net.jami.mvp.BaseView;
 
+import io.reactivex.disposables.CompositeDisposable;
+
 public interface SmartListView extends BaseView {
 
-    void displayChooseNumberDialog(CharSequence numbers[]);
+    void displayChooseNumberDialog(CharSequence[] numbers);
 
     void displayNoConversationMessage();
 
-    void displayConversationDialog(net.jami.smartlist.SmartListViewModel smartListViewModel);
+    void displayConversationDialog(SmartListViewModel smartListViewModel);
 
     void displayClearDialog(Uri callContact);
 
@@ -46,7 +48,7 @@ public interface SmartListView extends BaseView {
 
     void hideNoConversationMessage();
 
-    void updateList(List<net.jami.smartlist.SmartListViewModel> smartListViewModels);
+    void updateList(List<SmartListViewModel> smartListViewModels, CompositeDisposable parentDisposable);
     void update(SmartListViewModel model);
     void update(int position);
 
diff --git a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListViewModel.java b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListViewModel.java
index 2e9eccdfe..8ca3f7923 100644
--- a/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListViewModel.java
+++ b/ring-android/libringclient/src/main/java/net/jami/smartlist/SmartListViewModel.java
@@ -49,6 +49,7 @@ public class SmartListViewModel
     private final boolean showPresence;
     private boolean isOnline = false;
     private boolean isChecked = false;
+    private Observable<Boolean> isSelected = null;
     private final Interaction lastEvent;
 
     public enum Title {
@@ -94,6 +95,7 @@ public class SmartListViewModel
         hasUnreadTextMessage = (lastEvent != null) && !lastEvent.isRead();
         this.hasOngoingCall = false;
         this.lastEvent = lastEvent;
+        isSelected = conversation.getVisible();
         for (Contact contact : contacts) {
             if (contact.isUser())
                 continue;
@@ -172,6 +174,8 @@ public class SmartListViewModel
         isChecked = checked;
     }
 
+    public Observable<Boolean> getSelected() { return isSelected; }
+
     public void setHasOngoingCall(boolean hasOngoingCall) {
         this.hasOngoingCall = hasOngoingCall;
     }
-- 
GitLab