diff --git a/res/layout-FR/chat.xml b/res/layout-FR/chat.xml
index 1f7d9ef4c..0e10d6ffc 100644
--- a/res/layout-FR/chat.xml
+++ b/res/layout-FR/chat.xml
@@ -7,11 +7,11 @@
android:orientation="vertical" >
@@ -31,23 +31,16 @@
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
+
-
@@ -30,24 +30,17 @@
android:textColor="@color/text_contrast" />
-
-
-
-
-
-
-
-
+
+
lastSentMessagesBubbles;
private HashMap latestImageMessages;
- private int messagesFilterLimit = 0;
private boolean useLinphoneMessageStorage;
- private boolean messagesArePresentButHidden = false;
+ private List openImagesId ;
+ private ListView messagesList;
private ProgressBar progressBar;
private int bytesSent;
@@ -129,6 +126,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
private Thread uploadThread;
private TextWatcher textWatcher;
private OnGlobalLayoutListener keyboardListener;
+ private ChatMessageAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -148,20 +146,19 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
remoteComposing = (TextView) view.findViewById(R.id.remoteComposing);
remoteComposing.setVisibility(View.GONE);
-
+
+ messagesList = (ListView) view.findViewById(R.id.chatMessageList);
+ openImagesId = new ArrayList();
+
message = (EditText) view.findViewById(R.id.message);
if (!getActivity().getResources().getBoolean(R.bool.allow_chat_multiline)) {
message.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
message.setMaxLines(1);
}
-
uploadLayout = (RelativeLayout) view.findViewById(R.id.uploadLayout);
textLayout = (RelativeLayout) view.findViewById(R.id.messageLayout);
-
- messagesLayout = (RelativeLayout) view.findViewById(R.id.messages);
- messagesScrollView = (LinphoneScrollView) view.findViewById(R.id.chatScrollView);
+
progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
-
sendImage = (TextView) view.findViewById(R.id.sendPicture);
if (!getResources().getBoolean(R.bool.disable_chat_send_file)) {
registerForContextMenu(sendImage);
@@ -174,7 +171,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
} else {
sendImage.setEnabled(false);
}
-
+
cancelUpload = (ImageView) view.findViewById(R.id.cancelUpload);
cancelUpload.setOnClickListener(new OnClickListener() {
@Override
@@ -192,10 +189,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
//Only works if using liblinphone storage
chatRoom.markAsRead();
}
-
- if (savedInstanceState != null) {
- messagesFilterLimit = savedInstanceState.getInt("messagesFilterLimit");
- }
+
displayChatHeader(displayName, pictureUri);
uploadServerUri = LinphonePreferences.instance().getSharingPictureServerUrl();
@@ -248,7 +242,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
public void onSaveInstanceState(Bundle outState) {
outState.putString("fileToUploadPath", fileToUploadPath);
outState.putParcelable("imageToUpload", imageToUpload);
- outState.putInt("messagesFilterLimit", messagesFilterLimit);
super.onSaveInstanceState(outState);
}
@@ -283,64 +276,70 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
public void hideKeyboardVisibleMode() {
LinphoneActivity.instance().hideMenu(false);
contactPicture.setVisibility(View.VISIBLE);
- scrollToEnd();
+ //scrollToEnd();
}
-
- private void invalidate() {
- messagesFilterLimit += MESSAGES_STEP;
-
- if (!messagesArePresentButHidden) {
- LinphoneChatMessage[] history = chatRoom.getHistory();
- for (int i = 0; i < history.length; i++) {
- LinphoneChatMessage msg = history[i];
- boolean show = i >= history.length - messagesFilterLimit;
- if (msg.getExternalBodyUrl() != null) {
- displayImageMessage(msg.getStorageId(), null, msg.getTime(), !msg.isOutgoing(), msg.getStatus(), messagesLayout, msg.getExternalBodyUrl(), show);
- } else {
- displayMessage(msg.getStorageId(), msg.getText(), msg.getTime(), !msg.isOutgoing(), msg.getStatus(), messagesLayout, show);
- }
- }
- messagesArePresentButHidden = true;
+
+ class ChatMessageAdapter extends BaseAdapter {
+ LinphoneChatMessage[] history;
+ Context context;
+
+ public ChatMessageAdapter(Context context, LinphoneChatMessage[] history) {
+ this.history = history;
+ this.context = context;
+ }
+
+ public void refreshHistory(){
+ this.history = chatRoom.getHistory();
+ }
+
+ @Override
+ public int getCount() {
+ return history.length;
}
- invalidate(messagesFilterLimit);
- }
+ @Override
+ public LinphoneChatMessage getItem(int position) {
+ return history[position];
+ }
- private void invalidate(final int limit) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
-
- int start = messagesLayout.getChildCount() - messagesFilterLimit;
- if (start < 0)
- start = 0;
-
- for (int i = start; i < messagesLayout.getChildCount(); i++) {
- messagesLayout.getChildAt(i).setVisibility(View.VISIBLE);
- }
-
- LinphoneActivity.instance().updateMissedChatCount();
-
- if (start != 0) {
- messagesScrollView.setScrollViewListener(new ScrollViewListener() {
- @Override
- public void OnScrollToTop(final int previousHeight) {
- invalidate();
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- //Scroll to latest saw message
- if (messagesScrollView != null && messagesLayout != null && messagesLayout.getChildCount() >= MESSAGES_STEP-1)
- messagesScrollView.scrollTo(0, messagesLayout.getChildAt(MESSAGES_STEP-1).getBottom());
- }
- }, 300);
- }
- });
- } else {
- messagesScrollView.setScrollViewListener(null);
- }
+ @Override
+ public long getItemId(int position) {
+ return history[position].getStorageId();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ BubbleChat bubble;
+ LinphoneChatMessage msg = history[position];
+ View v;
+ Boolean showImage = false;
+
+ if (msg.getExternalBodyUrl() != null ) {
+ if(!openImagesId.isEmpty() && openImagesId.contains(msg.getStorageId())) showImage = true;
+ bubble = displayImageMessage(msg.getStorageId(), null, msg.getTime(), !msg.isOutgoing(), msg.getStatus(), context, msg.getExternalBodyUrl(),showImage);
+ } else {
+ bubble = displayMessage(msg.getStorageId(), msg.getText(), msg.getTime(), !msg.isOutgoing(), msg.getStatus(), context);
+
}
- });
+
+ v = bubble.getView();
+ bubble.setNativeMessageObject(msg);
+ registerForContextMenu(v);
+
+ RelativeLayout rlayout = new RelativeLayout(context);
+ rlayout.addView(v);
+
+ return rlayout;
+ }
+ }
+
+ public View getBubble(int position){
+ return messagesList.getChildAt(position);
+ }
+
+ public void dispayMessageList(){
+ adapter = new ChatMessageAdapter(this.getActivity(), chatRoom.getHistory());
+ messagesList.setAdapter(adapter);
}
private void displayChatHeader(String displayName, String pictureUri) {
@@ -359,45 +358,18 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
}
- private int checkId(int id) {
- if (id <= 0) {
- return previousMessageID + 1;
- }
- return id;
- }
-
- private BubbleChat displayMessage(int id, String message, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
- return displayMessage(id, message, time, isIncoming, status, layout, true);
- }
-
- private BubbleChat 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, null, previousMessageID);
+ private BubbleChat displayMessage(int id, String message, long time, boolean isIncoming, LinphoneChatMessage.State status, Context context) {
+ BubbleChat bubble = new BubbleChat(context, id, message, null, time, isIncoming, status, null);
if (!isIncoming) {
if (lastSentMessagesBubbles == null)
lastSentMessagesBubbles = new ArrayList();
lastSentMessagesBubbles.add(bubble);
}
-
- View v = bubble.getView();
-
- if (!show)
- v.setVisibility(View.GONE);
-
- previousMessageID = id;
- layout.addView(v);
- registerForContextMenu(v);
-
return bubble;
}
- private BubbleChat displayImageMessage(int id, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url) {
- return displayImageMessage(id, image, time, isIncoming, status, layout, url, true);
- }
-
- private BubbleChat displayImageMessage(int id, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url, boolean show) {
- id = checkId(id);
- final BubbleChat bubble = new BubbleChat(layout.getContext(), id, null, image, time, isIncoming, status, url, previousMessageID);
+ private BubbleChat displayImageMessage(int id, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, Context context, final String url, boolean show) {
+ final BubbleChat bubble = new BubbleChat(context, id, null, image, time, isIncoming, status, url);
if (!isIncoming) {
if (lastSentMessagesBubbles == null)
lastSentMessagesBubbles = new ArrayList();
@@ -421,8 +393,10 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
final Bitmap bm = ChatFragment.downloadImage(url);
if (bm != null) {
if (useLinphoneMessageStorage) {
- String newFileUrl = saveImage(bm, finalId, null);
+ String newFileUrl = saveImage(bm, finalId, getMessageForId(finalId));
bubble.updateUrl(newFileUrl);
+ adapter.refreshHistory();
+ openImagesId.add(finalId);
} else {
LinphoneActivity.instance().getChatStorage().saveImage(finalId, bm);
}
@@ -449,27 +423,28 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
});
} else { // Show
- bubble.setShowOrDownloadText(getString(R.string.show_image));
- bubble.setShowOrDownloadImageButtonListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- Bitmap bm = BitmapFactory.decodeFile(url);
- if (bm != null) {
- ((ImageView)v.findViewById(R.id.image)).setImageBitmap(bm);
- v.findViewById(R.id.image).setVisibility(View.VISIBLE);
- v.findViewById(R.id.download).setVisibility(View.GONE);
+ if(show){
+ Bitmap bm = BitmapFactory.decodeFile(url);
+ ((ImageView)v.findViewById(R.id.image)).setImageBitmap(bm);
+ v.findViewById(R.id.image).setVisibility(View.VISIBLE);
+ v.findViewById(R.id.download).setVisibility(View.GONE);
+ } else {
+ bubble.setShowOrDownloadText(getString(R.string.show_image));
+ bubble.setShowOrDownloadImageButtonListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Bitmap bm = BitmapFactory.decodeFile(url);
+ if (bm != null) {
+ openImagesId.add(finalId);
+ ((ImageView)v.findViewById(R.id.image)).setImageBitmap(bm);
+ v.findViewById(R.id.image).setVisibility(View.VISIBLE);
+ v.findViewById(R.id.download).setVisibility(View.GONE);
+ }
}
- }
- });
+ });
+ }
}
-
- if (!show)
- v.setVisibility(View.GONE);
-
- previousMessageID = id;
- layout.addView(v);
- registerForContextMenu(v);
-
+
return bubble;
}
@@ -485,7 +460,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
LinphoneActivity.instance().getChatStorage().deleteDraft(sipUri);
}
- messagesFilterLimit = 0;
sipUri = newSipUri;
if (LinphoneActivity.isInstanciated()) {
String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
@@ -618,12 +592,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void displayMessages() {
- messagesLayout.removeAllViews();
- messagesArePresentButHidden = false;
- messagesFilterLimit = 0;
- previousMessageID = 0;
- invalidate();
- scrollToEnd();
+ dispayMessageList();
}
private void sendTextMessage() {
@@ -639,13 +608,13 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
LinphoneChatMessage chatMessage = chatRoom.createLinphoneChatMessage(messageToSend);
chatRoom.sendMessage(chatMessage, this);
- int newId = -1;
if (LinphoneActivity.isInstanciated()) {
- newId = LinphoneActivity.instance().onMessageSent(sipUri, messageToSend);
+ LinphoneActivity.instance().onMessageSent(sipUri, messageToSend);
}
- BubbleChat bubble = displayMessage(newId, messageToSend, System.currentTimeMillis(), false, State.InProgress, messagesLayout);
- bubble.setNativeMessageObject(chatMessage);
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
+
Log.i("Sent message current status: " + chatMessage.getStatus());
scrollToEnd();
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
@@ -666,14 +635,15 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
if (LinphoneActivity.isInstanciated()) {
newId = LinphoneActivity.instance().onMessageSent(sipUri, bitmap, url);
}
- newId = checkId(newId);
+ newId = chatMessage.getStorageId();
latestImageMessages.put(newId, url);
if (useLinphoneMessageStorage)
url = saveImage(bitmap, newId, chatMessage);
-
- BubbleChat bubble = displayImageMessage(newId, bitmap, System.currentTimeMillis(), false, State.InProgress, messagesLayout, url);
- bubble.setNativeMessageObject(chatMessage);
+
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
+
scrollToEnd();
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
@@ -698,13 +668,8 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void hideMessageBubble(int id) {
- for (int i = 0; i < messagesLayout.getChildCount(); i++) {
- View v = messagesLayout.getChildAt(i);
- if (v.getId() == id) {
- v.setVisibility(View.GONE);
- break;
- }
- }
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
}
private void resendMessage(int id) {
@@ -723,15 +688,8 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
private void scrollToEnd() {
- messagesScrollView.postDelayed(new Runnable() {
- @Override
- public void run() {
- messagesScrollView.fullScroll(View.FOCUS_DOWN);
-
- //Only works if using liblinphone storage
- chatRoom.markAsRead();
- }
- }, 100);
+ messagesList.smoothScrollToPosition(messagesList.getBottom());
+ chatRoom.markAsRead();
}
private void copyTextMessageToClipboard(int id) {
@@ -748,22 +706,22 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
mHandler.post(new Runnable() {
@Override
public void run() {
- displayMessage(id, message.getText(), message.getTime(), true, null, messagesLayout);
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
}
});
} else if (message.getExternalBodyUrl() != null) {
- Bitmap bm = null;
if (!useLinphoneMessageStorage) {
byte[] rawImage = LinphoneActivity.instance().getChatStorage().getRawImageFromMessage(id);
if (rawImage != null) {
- bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
+ Bitmap bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
}
}
- final Bitmap fbm = bm;
mHandler.post(new Runnable() {
@Override
public void run() {
- displayImageMessage(id, fbm, message.getTime(), true, null, messagesLayout, message.getExternalBodyUrl());
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
}
});
}
@@ -805,7 +763,9 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
}
}
}
+ adapter.notifyDataSetChanged();
}
+
});
}
}
diff --git a/src/org/linphone/ChatStorage.java b/src/org/linphone/ChatStorage.java
index b7249e923..32eb6bf7e 100644
--- a/src/org/linphone/ChatStorage.java
+++ b/src/org/linphone/ChatStorage.java
@@ -380,7 +380,7 @@ public class ChatStorage {
if (useNativeAPI) {
LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms();
for (LinphoneChatRoom chatroom : chats) {
- if (chatroom.getHistory().length > 0) {
+ if (chatroom.getHistory(1).length > 0) {
chatList.add(chatroom.getPeerAddress().asStringUriOnly());
}
}
diff --git a/src/org/linphone/ui/BubbleChat.java b/src/org/linphone/ui/BubbleChat.java
index 68409889d..b97f5b0e7 100644
--- a/src/org/linphone/ui/BubbleChat.java
+++ b/src/org/linphone/ui/BubbleChat.java
@@ -22,7 +22,6 @@ import java.util.Calendar;
import java.util.HashMap;
import java.util.Map.Entry;
-import org.linphone.LinphoneUtils;
import org.linphone.R;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatMessage.State;
@@ -94,14 +93,14 @@ public class BubbleChat {
private LinphoneChatMessage nativeMessage;
private int id;
- public BubbleChat(final Context context, int ID, String message, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, String url, int previousID) {
+ public BubbleChat(final Context context, int ID, String message, Bitmap image, long time, boolean isIncoming, LinphoneChatMessage.State status, String url) {
view = new RelativeLayout(context);
imageUrl = url;
textMessage = message;
state = status;
id = ID;
- LayoutParams layoutParams = new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
if (isIncoming) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
@@ -111,14 +110,11 @@ public class BubbleChat {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
view.setBackgroundResource(R.drawable.chat_bubble_outgoing);
}
-
- if (previousID != -1) {
- layoutParams.addRule(RelativeLayout.BELOW, previousID);
- }
- view.setId(id);
- layoutParams.setMargins(0, LinphoneUtils.pixelsToDpi(context.getResources(), 10), 0, 0);
- view.setLayoutParams(layoutParams);
+ layoutParams.setMargins(10, 0, 10, 0);
+
+ view.setId(id);
+ view.setLayoutParams(layoutParams);
Spanned text = null;
if (message != null) {
@@ -218,6 +214,7 @@ public class BubbleChat {
} else {
statusView.setImageResource(R.drawable.chat_message_inprogress);
}
+
view.invalidate();
}