From 7d23170577804834e89fc2fe4dea71b1f9a65ae0 Mon Sep 17 00:00:00 2001 From: Lucas Legrand Date: Mon, 30 Jul 2018 13:55:16 +0200 Subject: [PATCH] HistoryListFragment ListView converted to RecyclerView, Adapter/ViewHolder are now in a CallHistoryAdapter separate class. SelectableHelper edited, switched (de)select_all buttons visibility between enter/quitEditionMode, searchMode in ContactsListFragment revealed a switch error. TODO: Clean all fragments code edited during RecyclerView conversion course. --- res/layout/history.xml | 2 +- res/layout/history_cell.xml | 2 + .../org/linphone/call/CallHistoryAdapter.java | 233 ++++++++++ .../org/linphone/chat/GroupInfoAdapter.java | 1 - .../contacts/ContactsListFragment.java | 32 +- .../fragments/HistoryListFragment.java | 405 ++++-------------- .../org/linphone/ui/SelectableHelper.java | 13 +- 7 files changed, 341 insertions(+), 347 deletions(-) create mode 100644 src/android/org/linphone/call/CallHistoryAdapter.java diff --git a/res/layout/history.xml b/res/layout/history.xml index ffa8d6f9c..aa8a31ca0 100644 --- a/res/layout/history.xml +++ b/res/layout/history.xml @@ -76,7 +76,7 @@ - { + public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, + View.OnLongClickListener{ + public TextView contact; + public ImageView detail; + public CheckBox select; + public ImageView callDirection; + public ImageView contactPicture; + public RelativeLayout CallContact; + public RelativeLayout SelectContact; + public LinearLayout separator; + public TextView separatorText; + private CallHistoryAdapter.ViewHolder.ClickListener listener; + + public ViewHolder(View view, CallHistoryAdapter.ViewHolder.ClickListener listener) { + super(view); + contact = (TextView) view.findViewById(R.id.sip_uri); + detail = (ImageView) view.findViewById(R.id.detail); + select = (CheckBox) view.findViewById(R.id.delete); + callDirection = (ImageView) view.findViewById(R.id.icon); + contactPicture = (ImageView) view.findViewById(R.id.contact_picture); + CallContact = (RelativeLayout) view.findViewById(R.id.history_click); + SelectContact = (RelativeLayout) view.findViewById(R.id.history_whole); + separator = (LinearLayout) view.findViewById(R.id.separator); + separatorText = (TextView) view.findViewById(R.id.separator_text); + this.listener = listener; + view.setOnClickListener(this); + view.setOnLongClickListener(this); + + } + + @Override + public void onClick(View view) { + if (listener != null) { + listener.onItemClicked(getAdapterPosition()); + } + } + + @Override + public boolean onLongClick(View view) { + if (listener != null) { + return listener.onItemLongClicked(getAdapterPosition()); + } + return false; + } + + public interface ClickListener { + public void onItemClicked(int position); + public boolean onItemLongClicked(int position); + } + + } + + private List mLogs; + private Context mContext; + private CallHistoryAdapter.ViewHolder.ClickListener clickListener; + + public CallHistoryAdapter(Context aContext, List logs,CallHistoryAdapter.ViewHolder.ClickListener listener ,SelectableHelper helper) { + super(helper); + this.mLogs = logs; + this.mContext = aContext; + this.clickListener = listener; + } + + public int getCount() { + return mLogs.size(); + } + + public Object getItem(int position) { + return mLogs.get(position); + } + + + public long getItemId(int position) { + return position; + } + + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_cell, parent, false); + return new ViewHolder(v, clickListener); + + } + + @Override + public void onBindViewHolder(@NonNull final ViewHolder holder, final int position) { + final CallLog log= mLogs.get(position); + long timestamp = log.getStartDate() * 1000; + Address address; + + holder.contact.setSelected(true); // For automated horizontal scrolling of long texts + Calendar logTime = Calendar.getInstance(); + logTime.setTimeInMillis(timestamp); + holder.separatorText.setText(timestampToHumanDate(logTime)); + holder.select.setVisibility(isEditionEnabled() ? View.VISIBLE : View.GONE); + holder.select.setChecked(isSelected(position)); + + + if (position > 0) { + CallLog previousLog = mLogs.get(position-1); + long previousTimestamp = previousLog.getStartDate() * 1000; + Calendar previousLogTime = Calendar.getInstance(); + previousLogTime.setTimeInMillis(previousTimestamp); + + if (isSameDay(previousLogTime, logTime)) { + holder.separator.setVisibility(View.GONE); + } else { + holder.separator.setVisibility(View.VISIBLE); + } + } else { + holder.separator.setVisibility(View.VISIBLE); + } + + + if (log.getDir() == Call.Dir.Incoming) { + address = log.getFromAddress(); + if (log.getStatus() == Call.Status.Missed) { + holder.callDirection.setImageResource(R.drawable.call_status_missed); + } else { + holder.callDirection.setImageResource(R.drawable.call_status_incoming); + } + } else { + address = log.getToAddress(); + holder.callDirection.setImageResource(R.drawable.call_status_outgoing); + } + + LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address); + String displayName = null; + final String sipUri = (address != null) ? address.asString() : ""; + if (c != null) { + displayName = c.getFullName(); + LinphoneUtils.setThumbnailPictureFromUri(LinphoneActivity.instance(), holder.contactPicture, c.getThumbnailUri()); + } else { + holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); + } + + if (displayName == null) { + holder.contact.setText(LinphoneUtils.getAddressDisplayName(sipUri)); + } else { + holder.contact.setText(displayName); + } + + + + holder.detail.setVisibility(isEditionEnabled() ? View.INVISIBLE : View.VISIBLE); + holder.detail.setOnClickListener(!isEditionEnabled() ? + new View.OnClickListener() { + @Override + public void onClick(View v) { + if (LinphoneActivity.isInstanciated()) { + LinphoneActivity.instance().displayHistoryDetail(sipUri, log); + } + } + } + : + null + ); + } + + @Override + public int getItemCount() { + return mLogs.size(); + } + + @SuppressLint("SimpleDateFormat") + private String timestampToHumanDate(Calendar cal) { + SimpleDateFormat dateFormat; + if (isToday(cal)) { + return mContext.getString(R.string.today); + } else if (isYesterday(cal)) { + return mContext.getString(R.string.yesterday); + } else { + dateFormat = new SimpleDateFormat(mContext.getResources().getString(R.string.history_date_format)); + } + + return dateFormat.format(cal.getTime()); + } + + private boolean isSameDay(Calendar cal1, Calendar cal2) { + if (cal1 == null || cal2 == null) { + return false; + } + + return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && + cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && + cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR)); + } + + private boolean isToday(Calendar cal) { + return isSameDay(cal, Calendar.getInstance()); + } + + private boolean isYesterday(Calendar cal) { + Calendar yesterday = Calendar.getInstance(); + yesterday.roll(Calendar.DAY_OF_MONTH, -1); + return isSameDay(cal, yesterday); + } +} \ No newline at end of file diff --git a/src/android/org/linphone/chat/GroupInfoAdapter.java b/src/android/org/linphone/chat/GroupInfoAdapter.java index e0d0eecfe..317f3a853 100644 --- a/src/android/org/linphone/chat/GroupInfoAdapter.java +++ b/src/android/org/linphone/chat/GroupInfoAdapter.java @@ -59,7 +59,6 @@ public class GroupInfoAdapter extends RecyclerView.Adapter mLogs; - + private CallHistoryAdapter mhistoryAdapter; + private LinearLayoutManager layoutManager; + private Context mContext; + private SelectableHelper mSelectionHelper; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mInflater = inflater; View view = inflater.inflate(R.layout.history, container, false); + mContext = getActivity().getApplicationContext(); + mSelectionHelper = new SelectableHelper(view, this); noCallHistory = (TextView) view.findViewById(R.id.no_call_history); noMissedCallHistory = (TextView) view.findViewById(R.id.no_missed_call_history); - historyList = (ListView) view.findViewById(R.id.history_list); - historyList.setOnItemClickListener(this); + historyList = (RecyclerView) view.findViewById(R.id.history_list); - delete = (ImageView) view.findViewById(R.id.delete); - delete.setOnClickListener(this); + + + layoutManager = new LinearLayoutManager(mContext); + historyList.setLayoutManager(layoutManager); + //Divider between items + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(historyList.getContext(), + layoutManager.getOrientation()); + dividerItemDecoration.setDrawable(mContext.getResources().getDrawable(R.drawable.divider)); + historyList.addItemDecoration(dividerItemDecoration); + + + + + + +// delete = (ImageView) view.findViewById(R.id.delete); +// delete.setOnClickListener(this); editList = (LinearLayout) view.findViewById(R.id.edit_list); topBar = (LinearLayout) view.findViewById(R.id.top_bar); - cancel = (ImageView) view.findViewById(R.id.cancel); - cancel.setOnClickListener(this); +// cancel = (ImageView) view.findViewById(R.id.cancel); +// cancel.setOnClickListener(this); allCalls = (ImageView) view.findViewById(R.id.all_calls); allCalls.setOnClickListener(this); @@ -100,17 +125,17 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On missedCallsSelected = view.findViewById(R.id.missed_calls_select); - selectAll = (ImageView) view.findViewById(R.id.select_all); - selectAll.setOnClickListener(this); - - deselectAll = (ImageView) view.findViewById(R.id.deselect_all); - deselectAll.setOnClickListener(this); +// selectAll = (ImageView) view.findViewById(R.id.select_all); +// selectAll.setOnClickListener(this); +// +// deselectAll = (ImageView) view.findViewById(R.id.deselect_all); +// deselectAll.setOnClickListener(this); allCalls.setEnabled(false); onlyDisplayMissedCalls = false; edit = (ImageView) view.findViewById(R.id.edit); - edit.setOnClickListener(this); +// edit.setOnClickListener(this); return view; } @@ -119,12 +144,6 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); } - private void selectAllList(boolean isSelectAll){ - int size = historyList.getAdapter().getCount(); - for(int i=0; i 0) { @@ -141,37 +160,6 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On } } - private void removeCallLogs(){ - int size = historyList.getAdapter().getCount(); - for(int i=0; i missedCalls = new ArrayList(); @@ -217,8 +205,11 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); if (!hideHistoryListAndDisplayMessageIfEmpty()) { - historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); - historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); +// historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); + mhistoryAdapter= new CallHistoryAdapter(getActivity().getApplicationContext(), mLogs, this, mSelectionHelper); + historyList.setAdapter(mhistoryAdapter); + mSelectionHelper.setAdapter(mhistoryAdapter); + mSelectionHelper.setDialogMessage(R.string.chat_room_delete_dialog); } } @@ -242,56 +233,6 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On public void onClick(View v) { int id = v.getId(); - if (id == R.id.select_all) { - deselectAll.setVisibility(View.VISIBLE); - selectAll.setVisibility(View.GONE); - enabledDeleteButton(true); - selectAllList(true); - return; - } - if (id == R.id.deselect_all) { - deselectAll.setVisibility(View.GONE); - selectAll.setVisibility(View.VISIBLE); - enabledDeleteButton(false); - selectAllList(false); - return; - } - - if (id == R.id.cancel) { - quitEditMode(); - return; - } - - if (id == R.id.delete) { - if(historyList.getCheckedItemCount() == 0) { - quitEditMode(); - return; - } - - final Dialog dialog = LinphoneActivity.instance().displayDialog(getString(R.string.delete_text)); - Button delete = (Button) dialog.findViewById(R.id.delete_button); - Button cancel = (Button) dialog.findViewById(R.id.cancel); - - delete.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - removeCallLogs(); - dialog.dismiss(); - quitEditMode(); - } - }); - - cancel.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - dialog.dismiss(); - quitEditMode(); - } - }); - dialog.show(); - return; - } - if (id == R.id.all_calls) { allCalls.setEnabled(false); allCallsSelected.setVisibility(View.VISIBLE); @@ -307,247 +248,61 @@ public class HistoryListFragment extends Fragment implements OnClickListener, On missedCalls.setEnabled(false); onlyDisplayMissedCalls = true; } - - if (id == R.id.edit) { - topBar.setVisibility(View.GONE); - editList.setVisibility(View.VISIBLE); - enabledDeleteButton(false); - isEditMode = true; - } - if (!hideHistoryListAndDisplayMessageIfEmpty()) { - historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); - historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); - } - - if(isEditMode){ - deselectAll.setVisibility(View.GONE); - selectAll.setVisibility(View.VISIBLE); +// historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); + mhistoryAdapter = new CallHistoryAdapter(mContext, mLogs, this ,mSelectionHelper); + historyList.setAdapter(mhistoryAdapter); + mSelectionHelper.setAdapter(mhistoryAdapter); + mSelectionHelper.setDialogMessage(R.string.chat_room_delete_dialog); } } @Override public void onItemClick(AdapterView adapter, View view, int position, long id) { - if (isEditMode) { + if (mhistoryAdapter.isEditionEnabled()) { CallLog log = mLogs.get(position); LinphoneManager.getLc().removeCallLog(log); mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); } } - public void quitEditMode(){ - isEditMode = false; - editList.setVisibility(View.GONE); - topBar.setVisibility(View.VISIBLE); - refresh(); - if (!hideHistoryListAndDisplayMessageIfEmpty()) { - historyList.setChoiceMode(AbsListView.CHOICE_MODE_MULTIPLE); - historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); - } - if (getResources().getBoolean(R.bool.isTablet)) { - displayFirstLog(); + + @Override + public void onDeleteSelection(Object[] objectsToDelete) { + int size = mhistoryAdapter.getSelectedItemCount(); + for(int i=0; i 0) { - CallLog previousLog = mLogs.get(position-1); - long previousTimestamp = previousLog.getStartDate() * 1000; - Calendar previousLogTime = Calendar.getInstance(); - previousLogTime.setTimeInMillis(previousTimestamp); - - if (isSameDay(previousLogTime, logTime)) { - separator.setVisibility(View.GONE); + @Override + public void onItemClicked(int position) { + if (mhistoryAdapter.isEditionEnabled()) { + mhistoryAdapter.toggleSelection(position); + }else{ + if (LinphoneActivity.isInstanciated()) { + CallLog log = mLogs.get(position); + Address address; + if (log.getDir() == Call.Dir.Incoming) { + address = log.getFromAddress(); } else { - separator.setVisibility(View.VISIBLE); + address = log.getToAddress(); } - } else { - separator.setVisibility(View.VISIBLE); + LinphoneActivity.instance().setAddresGoToDialerAndCall(address.asStringUriOnly(), address.getDisplayName(), null); } - - if (log.getDir() == Call.Dir.Incoming) { - address = log.getFromAddress(); - if (log.getStatus() == Call.Status.Missed) { - holder.callDirection.setImageResource(R.drawable.call_status_missed); - } else { - holder.callDirection.setImageResource(R.drawable.call_status_incoming); - } - } else { - address = log.getToAddress(); - holder.callDirection.setImageResource(R.drawable.call_status_outgoing); - } - - LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(address); - String displayName = null; - final String sipUri = (address != null) ? address.asString() : ""; - if (c != null) { - displayName = c.getFullName(); - LinphoneUtils.setThumbnailPictureFromUri(LinphoneActivity.instance(), holder.contactPicture, c.getThumbnailUri()); - } else { - holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); - } - - if (displayName == null) { - holder.contact.setText(LinphoneUtils.getAddressDisplayName(sipUri)); - } else { - holder.contact.setText(displayName); - } - - if (isEditMode) { - holder.CallContact.setOnClickListener(null); - holder.select.setVisibility(View.VISIBLE); - holder.select.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - historyList.setItemChecked(position, b); - if(getNbItemsChecked() == getCount()){ - deselectAll.setVisibility(View.VISIBLE); - selectAll.setVisibility(View.GONE); - enabledDeleteButton(true); - } else { - if(getNbItemsChecked() == 0){ - deselectAll.setVisibility(View.GONE); - selectAll.setVisibility(View.VISIBLE); - enabledDeleteButton(false); - } else { - deselectAll.setVisibility(View.GONE); - selectAll.setVisibility(View.VISIBLE); - enabledDeleteButton(true); - } - } - } - }); - holder.detail.setVisibility(View.INVISIBLE); - if(historyList.isItemChecked(position)) { - holder.select.setChecked(true); - } else { - holder.select.setChecked(false); - } - } else { - holder.select.setVisibility(View.GONE); - holder.detail.setVisibility(View.VISIBLE); - holder.detail.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (LinphoneActivity.isInstanciated()) { - LinphoneActivity.instance().displayHistoryDetail(sipUri, log); - } - } - }); - holder.CallContact.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (LinphoneActivity.isInstanciated()) { - CallLog log = mLogs.get(position); - Address address; - if (log.getDir() == Call.Dir.Incoming) { - address = log.getFromAddress(); - } else { - address = log.getToAddress(); - } - LinphoneActivity.instance().setAddresGoToDialerAndCall(address.asStringUriOnly(), address.getDisplayName(), null); - } - } - }); - } - return view; } } + + @Override + public boolean onItemLongClicked(int position) { + if (!mhistoryAdapter.isEditionEnabled()) { + mSelectionHelper.enterEditionMode(); + } + mhistoryAdapter.toggleSelection(position); + return true; + } } \ No newline at end of file diff --git a/src/android/org/linphone/ui/SelectableHelper.java b/src/android/org/linphone/ui/SelectableHelper.java index 49922d849..9b35b5581 100644 --- a/src/android/org/linphone/ui/SelectableHelper.java +++ b/src/android/org/linphone/ui/SelectableHelper.java @@ -67,7 +67,8 @@ public class SelectableHelper { @Override public void onClick(View v) { if (mAdapter.getItemCount() > 0) { - mAdapter.enableEdition(true); + enterEditionMode(); +// mAdapter.enableEdition(true); mTopBar.setVisibility(View.GONE); mEditTopBar.setVisibility(View.VISIBLE); } @@ -92,6 +93,8 @@ public class SelectableHelper { mDeleteSelectionButton = view.findViewById(R.id.delete); mDeleteSelectionButton.setEnabled(false); + + //Display confirmation for deletion mDeleteSelectionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -149,8 +152,8 @@ public class SelectableHelper { mTopBar.setVisibility(View.VISIBLE); mEditTopBar.setVisibility(View.GONE); mDeleteSelectionButton.setEnabled(false); - mSelectAllButton.setVisibility(View.VISIBLE); - mDeselectAllButton.setVisibility(View.GONE); + mSelectAllButton.setVisibility(View.GONE); + mDeselectAllButton.setVisibility(View.VISIBLE); } public void enterEditionMode() { @@ -158,8 +161,8 @@ public class SelectableHelper { mTopBar.setVisibility(View.GONE); mEditTopBar.setVisibility(View.VISIBLE); mDeleteSelectionButton.setEnabled(false); - mSelectAllButton.setVisibility(View.GONE); - mDeselectAllButton.setVisibility(View.VISIBLE); + mSelectAllButton.setVisibility(View.VISIBLE); + mDeselectAllButton.setVisibility(View.GONE); } private Object[] getSelectedObjects() {