Skip to content
Snippets Groups Projects
Commit 5cce15ec authored by Hadrien De Sousa's avatar Hadrien De Sousa
Browse files

Add animation to SmartListFragment


Use DiffUtils to manage change in SmartListFragment adapter

Tuleap: #1374
Change-Id: I0872c9178c7fd9062d57287e61c4a2a650c7c393
Reviewed-by: default avatarAline Bonnet <aline.bonnet@savoirfairelinux.com>
parent 1c0e6738
Branches
Tags
No related merge requests found
Showing
with 243 additions and 180 deletions
......@@ -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;
}
}
}
\ No newline at end of file
/*
* 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
......@@ -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;
......
......@@ -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);
}
}
}
......@@ -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
*/
......
......@@ -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"
......
......@@ -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" />
......
......@@ -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()) {
......
......@@ -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";
......
......@@ -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()) {
......
......@@ -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,20 +195,24 @@ 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) {
......@@ -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;
}
......
......@@ -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();
}
......@@ -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;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment