Improved chat messages performances

This commit is contained in:
Sylvain Berfini 2013-08-20 12:13:20 +02:00
parent 389d3177ec
commit 5ed2e63ca0
5 changed files with 111 additions and 78 deletions

View file

@ -116,8 +116,8 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
private BubbleChat lastSentMessageBubble;
private HashMap<Integer, String> latestImageMessages;
private int messagesFilterLimit = 0;
private List<ChatMessage> messagesList;
private boolean useLinphoneMessageStorage;
private boolean messagesArePresentButHidden = false;
private ProgressBar progressBar;
private int bytesSent;
@ -239,10 +239,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
return view;
}
private void refreshMessages() {
messagesList = LinphoneActivity.instance().getChatMessages(sipUri);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("fileToUploadPath", fileToUploadPath);
@ -286,52 +282,46 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void invalidate() {
refreshMessages();
if (messagesFilterLimit == 0) {
if (messagesList.size() > MESSAGES_STEP)
messagesFilterLimit = MESSAGES_STEP;
else
messagesFilterLimit = messagesList.size();
} else {
if (messagesFilterLimit + MESSAGES_STEP <= messagesList.size())
messagesFilterLimit += MESSAGES_STEP;
else
messagesFilterLimit = messagesList.size();
if (!messagesArePresentButHidden) {
LinphoneChatMessage[] history = chatRoom.getHistory();
for (int i = 0; i < history.length; i++) {
LinphoneChatMessage msg = history[i];
if (msg.getExternalBodyUrl() != null) {
Bitmap bm = BitmapFactory.decodeFile(msg.getExternalBodyUrl());
displayImageMessage(msg.getStorageId(), bm, msg.getTime(), !msg.isOutgoing(), msg.getStatus(), messagesLayout, msg.getExternalBodyUrl(), i >= history.length - messagesFilterLimit);
} else {
displayMessage(msg.getStorageId(), msg.getText(), msg.getTime(), !msg.isOutgoing(), msg.getStatus(), messagesLayout, i >= history.length - messagesFilterLimit);
}
}
messagesArePresentButHidden = true;
}
invalidate(messagesFilterLimit);
}
private void invalidate(final int limit) {
messagesLayout.removeAllViews();
mHandler.post(new Runnable() {
@Override
public void run() {
previousMessageID = -1;
ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
int start = messagesLayout.getChildCount() - messagesFilterLimit;
if (start < 0)
start = 0;
for (int i = messagesList.size() - limit; i < messagesList.size(); i++) {
ChatMessage msg = messagesList.get(i);
if (msg.getMessage() != null && msg.getMessage().length() > 0) {
displayMessage(msg.getId(), msg.getMessage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
} else {
displayImageMessage(msg.getId(), msg.getImage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout, msg.getUrl());
for (int i = start; i < messagesLayout.getChildCount(); i++) {
messagesLayout.getChildAt(i).setVisibility(View.VISIBLE);
}
if (!msg.isRead()) {
// Only works if not using liblinphone storage
chatStorage.markMessageAsRead(msg.getId());
}
}
LinphoneActivity.instance().updateMissedChatCount();
if (limit < messagesList.size()) {
if (start != 0) {
messagesScrollView.setScrollViewListener(new ScrollViewListener() {
@Override
public void OnScrollToTop(final int previousHeight) {
invalidate();mHandler.postDelayed(new Runnable() {
invalidate();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
//Scroll to latest saw message
@ -379,7 +369,11 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
return id;
}
private void displayMessage(int id, String message, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
private void displayMessage(int id, String message, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
displayMessage(id, message, time, isIncoming, status, layout, true);
}
private void displayMessage(int id, String message, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, boolean show) {
id = checkId(id);
BubbleChat bubble = new BubbleChat(layout.getContext(), id, message, null, time, isIncoming, status, previousMessageID);
if (!isIncoming) {
@ -387,12 +381,19 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
View v = bubble.getView();
if (!show)
v.setVisibility(View.GONE);
previousMessageID = id;
layout.addView(v);
registerForContextMenu(v);
}
private void displayImageMessage(int id, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url) {
displayImageMessage(id, image, time, isIncoming, status, layout, url, true);
}
private void displayImageMessage(int id, Bitmap image, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url) {
private void displayImageMessage(int id, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url, boolean show) {
id = checkId(id);
BubbleChat bubble = new BubbleChat(layout.getContext(), id, null, image, time, isIncoming, status, previousMessageID);
if (!isIncoming) {
@ -435,6 +436,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
});
if (!show)
v.setVisibility(View.GONE);
previousMessageID = id;
layout.addView(v);
registerForContextMenu(v);
@ -489,7 +493,13 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
switch (item.getItemId()) {
case MENU_DELETE_MESSAGE:
LinphoneActivity.instance().getChatStorage().deleteMessage(chatRoom, item.getGroupId());
invalidate();
for (int i = 0; i < messagesLayout.getChildCount(); i++) {
View v = messagesLayout.getChildAt(i);
if (v.getId() == item.getGroupId()) {
v.setVisibility(View.GONE);
break;
}
}
break;
case MENU_SAVE_PICTURE:
saveImage(item.getGroupId());
@ -576,7 +586,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
newId = LinphoneActivity.instance().onMessageSent(sipUri, messageToSend);
}
displayMessage(newId, messageToSend, String.valueOf(System.currentTimeMillis()), false, State.InProgress, messagesLayout);
displayMessage(newId, messageToSend, System.currentTimeMillis(), false, State.InProgress, messagesLayout);
scrollToEnd();
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
@ -602,7 +612,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
if (useLinphoneMessageStorage)
saveImage(bitmap, newId, chatMessage);
displayImageMessage(newId, bitmap, String.valueOf(System.currentTimeMillis()), false, State.InProgress, messagesLayout, url);
displayImageMessage(newId, bitmap, System.currentTimeMillis(), false, State.InProgress, messagesLayout, url);
scrollToEnd();
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
@ -632,7 +642,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
mHandler.post(new Runnable() {
@Override
public void run() {
displayMessage(id, message.getText(), String.valueOf(message.getTime()), true, null, messagesLayout);
displayMessage(id, message.getText(), message.getTime(), true, null, messagesLayout);
}
});
} else if (message.getExternalBodyUrl() != null) {
@ -647,7 +657,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
mHandler.post(new Runnable() {
@Override
public void run() {
displayImageMessage(id, fbm, String.valueOf(message.getTime()), true, null, messagesLayout, fbm == null ? "" : message.getExternalBodyUrl());
displayImageMessage(id, fbm, message.getTime(), true, null, messagesLayout, fbm == null ? "" : message.getExternalBodyUrl());
}
});
}

View file

@ -67,6 +67,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
private ImageView clearFastChat;
private EditText fastNewChat;
private boolean isEditMode = false;
private boolean useLinphoneStorage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@ -104,7 +105,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
} else {
noChatHistory.setVisibility(View.GONE);
chatList.setVisibility(View.VISIBLE);
chatList.setAdapter(new ChatListAdapter());
chatList.setAdapter(new ChatListAdapter(useLinphoneStorage));
}
}
@ -125,7 +126,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
super.onResume();
//Check if the is the first time we show the chat view since we use liblinphone chat storage
boolean useLinphoneStorage = getResources().getBoolean(R.bool.use_linphone_chat_storage);
useLinphoneStorage = getResources().getBoolean(R.bool.use_linphone_chat_storage);
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(LinphoneActivity.instance());
boolean updateNeeded = prefs.getBoolean(getString(R.string.pref_first_time_linphone_chat_storage), true);
if (useLinphoneStorage && updateNeeded) {
@ -256,7 +257,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
String correspondent = conversations.get(j);
LinphoneChatRoom room = LinphoneManager.getLc().getOrCreateChatRoom(correspondent);
for (ChatMessage message : db.getMessages(correspondent)) {
LinphoneChatMessage msg = room.createLinphoneChatMessage(message.getMessage(), message.getUrl(), message.getStatus(), Long.parseLong(message.getTimestamp()), message.isRead(), message.isIncoming());
LinphoneChatMessage msg = room.createLinphoneChatMessage(message.getMessage(), message.getUrl(), message.getStatus(), Long.parseLong(message.getTimestamp()), true, message.isIncoming());
if (message.getImage() != null) {
String path = saveImageAsFile(message.getId(), message.getImage());
if (path != null)
@ -301,7 +302,10 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
class ChatListAdapter extends BaseAdapter {
ChatListAdapter() {
private boolean useNativeAPI;
ChatListAdapter(boolean useNativeAPI) {
this.useNativeAPI = useNativeAPI;
}
public int getCount() {
@ -345,6 +349,20 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
String message = "";
if (useNativeAPI) {
LinphoneChatRoom chatRoom = LinphoneManager.getLc().getOrCreateChatRoom(contact);
LinphoneChatMessage[] history = chatRoom.getHistory(20);
if (history != null && history.length > 0) {
for (int i = history.length - 1; i >= 0; i--) {
LinphoneChatMessage msg = history[i];
if (msg.getText() != null && msg.getText().length() > 0) {
message = msg.getText();
break;
}
}
}
} else {
List<ChatMessage> messages = LinphoneActivity.instance().getChatMessages(contact);
if (messages != null && messages.size() > 0) {
int iterator = messages.size() - 1;
@ -358,12 +376,11 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
iterator = -1;
}
}
String message = "";
message = (lastMessage == null || lastMessage.getMessage() == null) ? "" : lastMessage.getMessage();
}
}
TextView lastMessageView = (TextView) view.findViewById(R.id.lastMessage);
lastMessageView.setText(message);
}
TextView sipUri = (TextView) view.findViewById(R.id.sipUri);
sipUri.setSelected(true); // For animation

View file

@ -320,9 +320,11 @@ public class ChatStorage {
if (useNativeAPI) {
LinphoneChatMessage[] history = chatroom.getHistory();
if (history.length > id-1) {
LinphoneChatMessage msg = history[id-1];
for (LinphoneChatMessage msg : history) {
if (msg.getStorageId() == id) {
message = msg.getText();
break;
}
}
} else {
Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null);
@ -377,8 +379,12 @@ public class ChatStorage {
public void deleteMessage(LinphoneChatRoom chatroom, int id) {
if (useNativeAPI) {
LinphoneChatMessage[] history = chatroom.getHistory();
LinphoneChatMessage message = history[id-1];
for (LinphoneChatMessage message : history) {
if (message.getStorageId() == id) {
chatroom.deleteMessage(message);
break;
}
}
} else {
db.delete(TABLE_NAME, "id LIKE " + id, null);
}

View file

@ -87,7 +87,7 @@ public class BubbleChat {
private ImageView statusView;
private Button download;
public BubbleChat(Context context, int id, String message, Bitmap image, String time, boolean isIncoming, LinphoneChatMessage.State status, int previousID) {
public BubbleChat(Context context, int id, String message, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, int previousID) {
view = new RelativeLayout(context);
LayoutParams layoutParams = new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
@ -201,10 +201,10 @@ public class BubbleChat {
return view;
}
private String timestampToHumanDate(Context context, String timestamp) {
private String timestampToHumanDate(Context context, long timestamp) {
try {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(Long.parseLong(timestamp));
cal.setTimeInMillis(timestamp);
SimpleDateFormat dateFormat;
if (isToday(cal)) {
@ -215,7 +215,7 @@ public class BubbleChat {
return dateFormat.format(cal.getTime());
} catch (NumberFormatException nfe) {
return timestamp;
return String.valueOf(timestamp);
}
}

@ -1 +1 @@
Subproject commit e033f0ed6991a28bce4309b4480a50a38d52f79c
Subproject commit 34f405894cca981328688eb435d414552b2b345c