New history list

This commit is contained in:
Sylvain Berfini 2012-08-09 12:14:09 +02:00
parent 281f75c158
commit 72c0af5937
4 changed files with 248 additions and 71 deletions

View file

@ -53,7 +53,7 @@
</LinearLayout> </LinearLayout>
<ListView <ExpandableListView
android:id="@+id/historyList" android:id="@+id/historyList"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View file

@ -15,7 +15,7 @@
android:layout_marginLeft="10dp"/> android:layout_marginLeft="10dp"/>
<TextView <TextView
android:id="@+id/sipUri" android:id="@+id/dateAndTime"
android:lines="1" android:lines="1"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<ImageView
android:contentDescription="@string/content_description_delete"
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:src="@drawable/list_delete"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_alignParentRight="true" />
<TextView
android:id="@+id/sipUri"
android:lines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/black"
android:layout_marginLeft="30dp"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/delete" />
</RelativeLayout>

View file

@ -30,31 +30,32 @@ import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.util.SparseArray;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo; import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.BaseExpandableListAdapter;
import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.ExpandableListView;
import android.widget.AdapterView.OnItemClickListener; import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.BaseAdapter; import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
/** /**
* @author Sylvain Berfini * @author Sylvain Berfini
*/ */
public class HistoryFragment extends Fragment implements OnClickListener, OnItemClickListener { public class HistoryFragment extends Fragment implements OnClickListener, OnChildClickListener, OnGroupClickListener {
private ListView historyList; private Handler mHandler = new Handler();
private ExpandableListView historyList;
private LayoutInflater mInflater; private LayoutInflater mInflater;
private ImageView allCalls, missedCalls, edit, ok; private ImageView allCalls, missedCalls, edit, ok;
private boolean onlyDisplayMissedCalls, isEditMode; private boolean onlyDisplayMissedCalls, isEditMode;
private List<LinphoneCallLog> mLogs; private SparseArray<List<LinphoneCallLog>> mLogs;
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -62,9 +63,9 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
mInflater = inflater; mInflater = inflater;
View view = inflater.inflate(R.layout.history, container, false); View view = inflater.inflate(R.layout.history, container, false);
historyList = (ListView) view.findViewById(R.id.historyList); historyList = (ExpandableListView) view.findViewById(R.id.historyList);
historyList.setOnItemClickListener(this); historyList.setOnChildClickListener(this);
registerForContextMenu(historyList); historyList.setOnGroupClickListener(this);
allCalls = (ImageView) view.findViewById(R.id.allCalls); allCalls = (ImageView) view.findViewById(R.id.allCalls);
allCalls.setOnClickListener(this); allCalls.setOnClickListener(this);
@ -86,8 +87,97 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
if (LinphoneActivity.isInstanciated()) if (LinphoneActivity.isInstanciated())
LinphoneActivity.instance().selectMenu(FragmentsAvailable.HISTORY); LinphoneActivity.instance().selectMenu(FragmentsAvailable.HISTORY);
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); List<LinphoneCallLog> logs = Arrays.asList(LinphoneManager.getLc().getCallLogs());
historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); initLogsLists(logs);
historyList.setAdapter(new CallHistoryAdapter(getActivity()));
}
private void initLogsLists(List<LinphoneCallLog> logs) {
mLogs = new SparseArray<List<LinphoneCallLog>>();
String[] keys = new String[logs.size()];
for (LinphoneCallLog log : logs) {
String groupBy = getCorrespondentDisplayName(log);
int key = -1;
for (int k = 0; k < keys.length; k++) {
if (keys[k] == null || keys[k].equals(groupBy)) {
key = k;
keys[k] = groupBy;
break;
}
}
List<LinphoneCallLog> group = mLogs.get(key, new ArrayList<LinphoneCallLog>());
group.add(log);
if (group.size() == 1) {
mLogs.append(key, group);
}
}
}
private void initMissedLogsLists(List<LinphoneCallLog> logs) {
initLogsLists(logs);
for (int k = 0; k < mLogs.size(); k++) {
List<LinphoneCallLog> group = mLogs.get(k);
boolean removeGroup = true;
for (LinphoneCallLog log : group) {
if (log.getDirection() == CallDirection.Incoming && log.getStatus() == CallStatus.Missed) {
removeGroup = false;
break;
}
}
if (removeGroup) {
mLogs.remove(k);
}
}
}
private void collapseAllGroups() {
mHandler.post(new Runnable() {
@Override
public void run() {
for (int groupToCollapse = 0; groupToCollapse < historyList.getExpandableListAdapter().getGroupCount(); groupToCollapse++) {
if (historyList.isGroupExpanded(groupToCollapse)) {
historyList.collapseGroup(groupToCollapse);
}
}
}
});
}
private void expandAllGroups() {
mHandler.post(new Runnable() {
@Override
public void run() {
for (int groupToExpand = 0; groupToExpand < historyList.getExpandableListAdapter().getGroupCount(); groupToExpand++) {
if (!historyList.isGroupExpanded(groupToExpand)) {
historyList.expandGroup(groupToExpand);
}
}
}
});
}
private String getCorrespondentDisplayName(LinphoneCallLog log) {
String displayName;
LinphoneAddress address;
if (log.getDirection() == CallDirection.Incoming) {
address = log.getFrom();
} else {
address = log.getTo();
}
LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getActivity().getContentResolver());
displayName = address.getDisplayName();
String sipUri = address.asStringUriOnly();
if (displayName == null) {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
displayName = LinphoneUtils.getUsernameFromAddress(sipUri);
} else {
displayName = sipUri;
}
}
return displayName;
} }
@Override @Override
@ -96,16 +186,6 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
menu.add(0, v.getId(), 0, getString(R.string.delete)); menu.add(0, v.getId(), 0, getString(R.string.delete));
} }
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
LinphoneCallLog log = mLogs.get(info.position);
LinphoneManager.getLc().removeCallLog(log);
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs());
historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext()));
return true;
}
@Override @Override
public void onClick(View v) { public void onClick(View v) {
int id = v.getId(); int id = v.getId();
@ -115,12 +195,14 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
missedCalls.setEnabled(true); missedCalls.setEnabled(true);
onlyDisplayMissedCalls = false; onlyDisplayMissedCalls = false;
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); initLogsLists(Arrays.asList(LinphoneManager.getLc().getCallLogs()));
} }
else if (id == R.id.missedCalls) { else if (id == R.id.missedCalls) {
allCalls.setEnabled(true); allCalls.setEnabled(true);
missedCalls.setEnabled(false); missedCalls.setEnabled(false);
onlyDisplayMissedCalls = true; onlyDisplayMissedCalls = true;
initMissedLogsLists(Arrays.asList(LinphoneManager.getLc().getCallLogs()));
} }
else if (id == R.id.ok) { else if (id == R.id.ok) {
edit.setVisibility(View.VISIBLE); edit.setVisibility(View.VISIBLE);
@ -134,17 +216,37 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
} }
historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext()));
if (id == R.id.ok) {
collapseAllGroups();
}
else if (id == R.id.edit) {
expandAllGroups();
}
} }
@Override @Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) { public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
if (isEditMode) { if (isEditMode) {
LinphoneCallLog log = mLogs.get(position); for (LinphoneCallLog log : mLogs.get(groupPosition)) {
LinphoneManager.getLc().removeCallLog(log); LinphoneManager.getLc().removeCallLog(log);
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs()); }
initLogsLists(Arrays.asList(LinphoneManager.getLc().getCallLogs()));
historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext())); historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext()));
expandAllGroups();
}
return false;
}
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
LinphoneCallLog log = mLogs.get(groupPosition).get(childPosition);
if (isEditMode) {
LinphoneManager.getLc().removeCallLog(log);
initLogsLists(Arrays.asList(LinphoneManager.getLc().getCallLogs()));
historyList.setAdapter(new CallHistoryAdapter(getActivity().getApplicationContext()));
expandAllGroups();
} else { } else {
LinphoneCallLog log = mLogs.get(position);
LinphoneAddress address; LinphoneAddress address;
if (log.getDirection() == CallDirection.Incoming) { if (log.getDirection() == CallDirection.Incoming) {
address = log.getFrom(); address = log.getFrom();
@ -153,40 +255,34 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
} }
LinphoneActivity.instance().displayHistoryDetail(address.asStringUriOnly(), log); LinphoneActivity.instance().displayHistoryDetail(address.asStringUriOnly(), log);
} }
return false;
} }
class CallHistoryAdapter extends BaseAdapter { class CallHistoryAdapter extends BaseExpandableListAdapter {
private Bitmap missedCall, outgoingCall, incomingCall; private Bitmap missedCall, outgoingCall, incomingCall;
CallHistoryAdapter(Context aContext) { CallHistoryAdapter(Context aContext) {
missedCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_missed); missedCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_missed);
if (onlyDisplayMissedCalls) { if (!onlyDisplayMissedCalls) {
List<LinphoneCallLog> missedCalls = new ArrayList<LinphoneCallLog>();
for (LinphoneCallLog log : mLogs) {
if (log.getStatus() == CallStatus.Missed) {
missedCalls.add(log);
}
}
mLogs = missedCalls;
} else {
outgoingCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_outgoing); outgoingCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_outgoing);
incomingCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_incoming); incomingCall = BitmapFactory.decodeResource(getResources(), R.drawable.call_status_incoming);
} }
} }
public int getCount() {
return mLogs.size(); @Override
public Object getChild(int groupPosition, int childPosition) {
return mLogs.get(groupPosition).get(childPosition);
} }
public Object getItem(int position) { @Override
return mLogs.get(position); public long getChildId(int groupPosition, int childPosition) {
return childPosition;
} }
public long getItemId(int position) { @Override
return position; public View getChildView(int groupPosition, int childPosition,
} boolean isLastChild, View convertView, ViewGroup parent) {
public View getView(int position, View convertView, ViewGroup parent) {
View view = null; View view = null;
if (convertView != null) { if (convertView != null) {
view = convertView; view = convertView;
@ -194,10 +290,10 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
view = mInflater.inflate(R.layout.history_cell, parent,false); view = mInflater.inflate(R.layout.history_cell, parent,false);
} }
LinphoneCallLog log = mLogs.get(position); LinphoneCallLog log = (LinphoneCallLog) getChild(groupPosition, childPosition);
LinphoneAddress address; LinphoneAddress address;
TextView contact = (TextView) view.findViewById(R.id.sipUri); TextView dateAndTime = (TextView) view.findViewById(R.id.dateAndTime);
ImageView detail = (ImageView) view.findViewById(R.id.detail); ImageView detail = (ImageView) view.findViewById(R.id.detail);
ImageView delete = (ImageView) view.findViewById(R.id.delete); ImageView delete = (ImageView) view.findViewById(R.id.delete);
ImageView callDirection = (ImageView) view.findViewById(R.id.icon); ImageView callDirection = (ImageView) view.findViewById(R.id.icon);
@ -216,22 +312,8 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
} }
LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver()); LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
String displayName = address.getDisplayName();
String sipUri = address.asStringUriOnly(); String sipUri = address.asStringUriOnly();
dateAndTime.setText(log.getStartDate() + " " + log.getCallDuration());
if (displayName == null) {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
contact.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
} else {
contact.setText(sipUri);
}
} else {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(address.getDisplayName())) {
contact.setText(LinphoneUtils.getUsernameFromAddress(address.getDisplayName()));
} else {
contact.setText(displayName);
}
}
view.setTag(sipUri); view.setTag(sipUri);
if (isEditMode) { if (isEditMode) {
@ -245,5 +327,71 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnItem
return view; return view;
} }
} @Override
public int getChildrenCount(int groupPosition) {
return mLogs.get(groupPosition).size();
}
@Override
public Object getGroup(int groupPosition) {
return mLogs.get(groupPosition);
}
@Override
public int getGroupCount() {
return mLogs.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
View view = null;
if (convertView != null) {
view = convertView;
} else {
view = mInflater.inflate(R.layout.history_group, parent,false);
}
LinphoneCallLog log = (LinphoneCallLog) getChild(groupPosition, 0);
LinphoneAddress address;
TextView contact = (TextView) view.findViewById(R.id.sipUri);
ImageView delete = (ImageView) view.findViewById(R.id.delete);
if (log.getDirection() == CallDirection.Incoming) {
address = log.getFrom();
} else {
address = log.getTo();
}
LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
String displayName = getCorrespondentDisplayName(log);
String sipUri = address.asStringUriOnly();
contact.setText(displayName + " (" + getChildrenCount(groupPosition) + ")");
view.setTag(sipUri);
if (isEditMode) {
delete.setVisibility(View.VISIBLE);
} else {
delete.setVisibility(View.GONE);
}
return view;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
} }