diff --git a/res/layout/chat_bubble.xml b/res/layout/chat_bubble.xml
index 454fbe5e3..bbe8d147b 100644
--- a/res/layout/chat_bubble.xml
+++ b/res/layout/chat_bubble.xml
@@ -22,8 +22,7 @@
android:id="@+id/event_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textStyle="italic"
- android:text="Aujourd'hui"/>
+ android:textStyle="italic"/>
+ android:layout_height="wrap_content"/>
Do you want to delete selected conversation?
Do you want to delete selected message?
Remote is writing...
+ %s is writing...
Small
Medium
Large
diff --git a/src/android/org/linphone/activities/LinphoneActivity.java b/src/android/org/linphone/activities/LinphoneActivity.java
index b12bf8eb4..1eaa02516 100644
--- a/src/android/org/linphone/activities/LinphoneActivity.java
+++ b/src/android/org/linphone/activities/LinphoneActivity.java
@@ -711,12 +711,7 @@ public class LinphoneActivity extends LinphoneGenericActivity implements OnClick
if(sipUri == null && message == null && fileUri == null) {
changeCurrentFragment(FragmentsAvailable.CREATE_CHAT, extras);
} else {
- ChatRoom room = LinphoneManager.getLc().getChatRoom(lAddress);
- if (room.canHandleParticipants()) {
- changeCurrentFragment(FragmentsAvailable.GROUP_CHAT, extras);
- } else {
- changeCurrentFragment(FragmentsAvailable.CHAT, extras);
- }
+ changeCurrentFragment(FragmentsAvailable.GROUP_CHAT, extras);
}
}
diff --git a/src/android/org/linphone/chat/ChatBubbleViewHolder.java b/src/android/org/linphone/chat/ChatBubbleViewHolder.java
new file mode 100644
index 000000000..49123e141
--- /dev/null
+++ b/src/android/org/linphone/chat/ChatBubbleViewHolder.java
@@ -0,0 +1,109 @@
+/*
+ChatBubbleViewHolder.java
+Copyright (C) 2017 Belledonne Communications, Grenoble, France
+
+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 2
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package org.linphone.chat;
+
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import org.linphone.R;
+import org.linphone.core.Buffer;
+import org.linphone.core.ChatMessage;
+import org.linphone.core.ChatMessageListener;
+import org.linphone.core.Content;
+
+public class ChatBubbleViewHolder implements ChatMessageListener {
+ public int id;
+
+ public LinearLayout eventLayout;
+ public TextView eventTime;
+ public TextView eventMessage;
+
+ public RelativeLayout bubbleLayout;
+ public CheckBox delete;
+ public LinearLayout background;
+ public ImageView contactPicture;
+ public TextView contactName;
+ public TextView messageText;
+ public ImageView messageImage;
+ public RelativeLayout fileTransferLayout;
+ public ProgressBar fileTransferProgressBar;
+ public Button fileTransferAction;
+ public ImageView messageStatus;
+ public ProgressBar messageSendingInProgress;
+ public ImageView contactPictureMask;
+ public LinearLayout imdmLayout;
+ public ImageView imdmIcon;
+ public TextView imdmLabel;
+ public TextView fileExtensionLabel;
+ public TextView fileNameLabel;
+
+ public ChatBubbleViewHolder(View view) {
+ id = view.getId();
+
+ eventLayout = view.findViewById(R.id.event);
+ eventTime = view.findViewById(R.id.event_date);
+ eventMessage = view.findViewById(R.id.event_text);
+
+ bubbleLayout = (RelativeLayout) view.findViewById(R.id.bubble);
+ delete = (CheckBox) view.findViewById(R.id.delete_message);
+ background = (LinearLayout) view.findViewById(R.id.background);
+ contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
+ contactName = (TextView) view.findViewById(R.id.contact_header);
+ messageText = (TextView) view.findViewById(R.id.message);
+ messageImage = (ImageView) view.findViewById(R.id.image);
+ fileTransferLayout = (RelativeLayout) view.findViewById(R.id.file_transfer_layout);
+ fileTransferProgressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
+ fileTransferAction = (Button) view.findViewById(R.id.file_transfer_action);
+ messageStatus = (ImageView) view.findViewById(R.id.status);
+ messageSendingInProgress = (ProgressBar) view.findViewById(R.id.inprogress);
+ contactPictureMask = (ImageView) view.findViewById(R.id.mask);
+ imdmLayout = (LinearLayout) view.findViewById(R.id.imdmLayout);
+ imdmIcon = (ImageView) view.findViewById(R.id.imdmIcon);
+ imdmLabel = (TextView) view.findViewById(R.id.imdmText);
+ fileExtensionLabel = (TextView) view.findViewById(R.id.file_extension);
+ fileNameLabel = (TextView) view.findViewById(R.id.file_name);
+ }
+
+ @Override
+ public void onMsgStateChanged(ChatMessage msg, ChatMessage.State state) {
+
+ }
+
+ @Override
+ public void onFileTransferRecv(ChatMessage msg, Content content, Buffer buffer) {
+
+ }
+
+ @Override
+ public Buffer onFileTransferSend(ChatMessage message, Content content, int offset, int size) {
+ return null;
+ }
+
+ @Override
+ public void onFileTransferProgressIndication(ChatMessage msg, Content content, int offset, int total) {
+ if (msg.getStorageId() == id) fileTransferProgressBar.setProgress(offset * 100 / total);
+ }
+}
\ No newline at end of file
diff --git a/src/android/org/linphone/chat/ChatEventsAdapter.java b/src/android/org/linphone/chat/ChatEventsAdapter.java
new file mode 100644
index 000000000..d94803553
--- /dev/null
+++ b/src/android/org/linphone/chat/ChatEventsAdapter.java
@@ -0,0 +1,58 @@
+/*
+GroupChatFragment.java
+Copyright (C) 2017 Belledonne Communications, Grenoble, France
+
+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 2
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+package org.linphone.chat;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import org.linphone.core.ChatMessage;
+
+import java.util.ArrayList;
+
+public class ChatEventsAdapter extends BaseAdapter {
+ private ArrayList mHistory;
+ private Context mContext;
+
+ public ChatEventsAdapter() {
+
+ }
+
+ @Override
+ public int getCount() {
+ return 0;
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return null;
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ return null;
+ }
+}
diff --git a/src/android/org/linphone/chat/ChatFragment.java b/src/android/org/linphone/chat/ChatFragment.java
index a33604a6e..3abce121d 100644
--- a/src/android/org/linphone/chat/ChatFragment.java
+++ b/src/android/org/linphone/chat/ChatFragment.java
@@ -1263,72 +1263,7 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa
}
class ChatMessageAdapter extends BaseAdapter {
- private class ViewHolder implements ChatMessageListener {
- public int id;
- public LinearLayout eventLayout;
- public RelativeLayout bubbleLayout;
- public CheckBox delete;
- public LinearLayout background;
- public ImageView contactPicture;
- public TextView contactName;
- public TextView messageText;
- public ImageView messageImage;
- public RelativeLayout fileTransferLayout;
- public ProgressBar fileTransferProgressBar;
- public Button fileTransferAction;
- public ImageView messageStatus;
- public ProgressBar messageSendingInProgress;
- public ImageView contactPictureMask;
- public LinearLayout imdmLayout;
- public ImageView imdmIcon;
- public TextView imdmLabel;
- public TextView fileExtensionLabel;
- public TextView fileNameLabel;
-
- public ViewHolder(View view) {
- id = view.getId();
-
- eventLayout = (LinearLayout) view.findViewById(R.id.event);
- bubbleLayout = (RelativeLayout) view.findViewById(R.id.bubble);
- delete = (CheckBox) view.findViewById(R.id.delete_message);
- background = (LinearLayout) view.findViewById(R.id.background);
- contactPicture = (ImageView) view.findViewById(R.id.contact_picture);
- contactName = (TextView) view.findViewById(R.id.contact_header);
- messageText = (TextView) view.findViewById(R.id.message);
- messageImage = (ImageView) view.findViewById(R.id.image);
- fileTransferLayout = (RelativeLayout) view.findViewById(R.id.file_transfer_layout);
- fileTransferProgressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
- fileTransferAction = (Button) view.findViewById(R.id.file_transfer_action);
- messageStatus = (ImageView) view.findViewById(R.id.status);
- messageSendingInProgress = (ProgressBar) view.findViewById(R.id.inprogress);
- contactPictureMask = (ImageView) view.findViewById(R.id.mask);
- imdmLayout = (LinearLayout) view.findViewById(R.id.imdmLayout);
- imdmIcon = (ImageView) view.findViewById(R.id.imdmIcon);
- imdmLabel = (TextView) view.findViewById(R.id.imdmText);
- fileExtensionLabel = (TextView) view.findViewById(R.id.file_extension);
- fileNameLabel = (TextView) view.findViewById(R.id.file_name);
- }
-
- @Override
- public void onMsgStateChanged(ChatMessage msg, State state) {
-
- }
-
- @Override
- public void onFileTransferRecv(ChatMessage msg, Content content, Buffer buffer) {
-
- }
-
- @Override
- public Buffer onFileTransferSend(ChatMessage message, Content content, int offset, int size) {
- return null;
- }
-
- @Override
- public void onFileTransferProgressIndication(ChatMessage msg, Content content, int offset, int total) {
- if (msg.getStorageId() == id) fileTransferProgressBar.setProgress(offset * 100 / total);
- }
- }
+ private
ArrayList history;
Context context;
@@ -1382,16 +1317,16 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa
public View getView(final int position, View convertView, ViewGroup parent) {
final ChatMessage message = history.get(position);
View view = null;
- final ViewHolder holder;
+ final ChatBubbleViewHolder holder;
boolean sameMessage = false;
if (convertView != null) {
view = convertView;
- holder = (ViewHolder) view.getTag();
+ holder = (ChatBubbleViewHolder) view.getTag();
//LinphoneManager.removeListener(holder);
} else {
view = LayoutInflater.from(context).inflate(R.layout.chat_bubble, null);
- holder = new ViewHolder(view);
+ holder = new ChatBubbleViewHolder(view);
view.setTag(holder);
}
diff --git a/src/android/org/linphone/chat/GroupChatFragment.java b/src/android/org/linphone/chat/GroupChatFragment.java
index 136f03f16..c3bc5c4c7 100644
--- a/src/android/org/linphone/chat/GroupChatFragment.java
+++ b/src/android/org/linphone/chat/GroupChatFragment.java
@@ -1,14 +1,3 @@
-package org.linphone.chat;
-
-import android.app.Fragment;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-
-import org.linphone.R;
-
/*
GroupChatFragment.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France
@@ -28,27 +17,285 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-public class GroupChatFragment extends Fragment implements View.OnClickListener {
- private ImageView call, infos;
+package org.linphone.chat;
+import android.app.Fragment;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Adapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.linphone.LinphoneManager;
+import org.linphone.LinphoneUtils;
+import org.linphone.R;
+import org.linphone.activities.LinphoneActivity;
+import org.linphone.contacts.ContactsManager;
+import org.linphone.contacts.LinphoneContact;
+import org.linphone.core.Address;
+import org.linphone.core.ChatMessage;
+import org.linphone.core.ChatRoom;
+import org.linphone.core.ChatRoomListener;
+import org.linphone.core.Content;
+import org.linphone.core.Core;
+import org.linphone.core.Participant;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GroupChatFragment extends Fragment implements ChatRoomListener {
+ private ImageView mBackButton, mCallButton, mBackToCallButton, mGroupInfosButton, mEditButton;
+ private ImageView mCancelEditButton, mSelectAllButton, mDeselectAllButton, mDeleteSelectionButton;
+ private ImageView mAttachImageButton, mSendMessageButton;
+ private TextView mRoomLabel, mRemoteComposing;
+ private EditText mMessageTextToSend;
private LayoutInflater mInflater;
+ private Bitmap defaultContactAvatar;
+ private ListView mChatEventsList;
+
+ private ChatEventsAdapter mMessagesAdapter;
+ private String mRemoteSipUri;
+ private Address mRemoteSipAddress;
+ private ChatRoom mChatRoom;
+ private List mParticipants;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Retain the fragment across configuration changes
+ setRetainInstance(true);
+
+ if (getArguments() != null && getArguments().getString("SipUri") != null) {
+ mRemoteSipUri = getArguments().getString("SipUri");
+ mRemoteSipAddress = LinphoneManager.getLc().createAddress(mRemoteSipUri);
+ }
+
+ defaultContactAvatar = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.chat_picture_over);
+
mInflater = inflater;
View view = inflater.inflate(R.layout.chat, container, false);
- call = view.findViewById(R.id.start_call);
- call.setVisibility(View.GONE);
+ mBackButton = view.findViewById(R.id.back);
+ mBackButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ getFragmentManager().popBackStackImmediate();
+ }
+ });
- infos = view.findViewById(R.id.group_infos);
- infos.setVisibility(View.VISIBLE);
+ mCallButton = view.findViewById(R.id.start_call);
+ mCallButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LinphoneActivity.instance().setAddresGoToDialerAndCall(mRemoteSipUri, null, null);
+ }
+ });
+
+ mBackToCallButton = view.findViewById(R.id.back_to_call);
+ mBackToCallButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LinphoneActivity.instance().resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
+ }
+ });
+
+ mGroupInfosButton = view.findViewById(R.id.group_infos);
+ mGroupInfosButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mEditButton = view.findViewById(R.id.edit);
+ mEditButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mCancelEditButton = view.findViewById(R.id.cancel);
+ mCancelEditButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mSelectAllButton = view.findViewById(R.id.select_all);
+ mSelectAllButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mDeselectAllButton = view.findViewById(R.id.deselect_all);
+ mDeselectAllButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mDeleteSelectionButton = view.findViewById(R.id.delete);
+ mDeleteSelectionButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mRoomLabel = view.findViewById(R.id.contact_name);
+
+ mAttachImageButton = view.findViewById(R.id.send_picture);
+ mAttachImageButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mSendMessageButton = view.findViewById(R.id.send_message);
+ mSendMessageButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+
+ mMessageTextToSend = view.findViewById(R.id.message);
+ mMessageTextToSend.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ mSendMessageButton.setEnabled(mMessageTextToSend.getText().length() > 0);
+ if (mChatRoom != null) {
+ mChatRoom.compose();
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+
+ }
+ });
+
+ mRemoteComposing = view.findViewById(R.id.remote_composing);
+
+ mChatEventsList = view.findViewById(R.id.chat_message_list);
return view;
}
@Override
- public void onClick(View view) {
+ public void onResume() {
+ super.onResume();
+ initChatRoom();
+ displayChatRoomHeader();
+ displayChatRoomHistory();
+ }
+
+ private void initChatRoom() {
+ Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (mRemoteSipAddress == null || mRemoteSipUri == null || mRemoteSipUri.length() == 0 || core == null) {
+ LinphoneActivity.instance().goToDialerFragment();
+ return;
+ }
+
+ mChatRoom = core.getChatRoom(mRemoteSipAddress);
+ mChatRoom.setListener(this);
+ mChatRoom.markAsRead();
+ LinphoneActivity.instance().updateMissedChatCount();
+
+ mParticipants = new ArrayList<>();
+ if (mChatRoom.canHandleParticipants()) {
+ for (Participant p : mChatRoom.getParticipants()) {
+ LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(p.getAddress());
+ if (c != null) {
+ mParticipants.add(c);
+ }
+ }
+ } else {
+ LinphoneContact c = ContactsManager.getInstance().findContactFromAddress(mRemoteSipAddress);
+ if (c != null) {
+ mParticipants.add(c);
+ }
+ }
+ }
+
+ private void displayChatRoomHeader() {
+ Core core = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (core == null) return;
+
+ mRemoteComposing.setVisibility(View.INVISIBLE);
+
+ if (core.getCallByRemoteAddress(mRemoteSipUri) != null) {
+ mBackToCallButton.setVisibility(View.VISIBLE);
+ } else {
+ mBackToCallButton.setVisibility(View.GONE);
+ if (mChatRoom.canHandleParticipants()) {
+ mCallButton.setVisibility(View.GONE);
+ mGroupInfosButton.setVisibility(View.VISIBLE);
+ mRoomLabel.setText(mChatRoom.getSubject());
+ } else {
+ mCallButton.setVisibility(View.VISIBLE);
+ mGroupInfosButton.setVisibility(View.GONE);
+
+ if (mParticipants.size() == 0) {
+ // Contact not found
+ String displayName = mRemoteSipAddress.getDisplayName();
+ if (displayName == null || displayName.isEmpty()) {
+ mRoomLabel.setText(mRemoteSipAddress.getUsername());
+ } else {
+ mRoomLabel.setText(displayName);
+ }
+ } else {
+ mRoomLabel.setText(mParticipants.get(0).getFullName());
+ }
+ }
+ }
+ }
+
+ private void displayChatRoomHistory() {
+ mMessagesAdapter = new ChatEventsAdapter();
+ }
+
+ @Override
+ public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) {
}
+
+ @Override
+ public void onMessageReceived(ChatRoom cr, ChatMessage msg) {
+ cr.markAsRead();
+ LinphoneActivity.instance().updateMissedChatCount();
+
+ String externalBodyUrl = msg.getExternalBodyUrl();
+ Content fileTransferContent = msg.getFileTransferInformation();
+ if (externalBodyUrl != null || fileTransferContent != null) {
+ LinphoneActivity.instance().checkAndRequestExternalStoragePermission();
+ }
+ }
+
+ @Override
+ public void onIsComposingReceived(ChatRoom cr, Address remoteAddr, boolean isComposing) {
+ if (isComposing) {
+ mRemoteComposing.setText(getString(R.string.remote_composing_2).replace("%s", remoteAddr.getDisplayName()));
+ }
+ mRemoteComposing.setVisibility(isComposing ? View.VISIBLE : View.GONE);
+ }
}
diff --git a/src/android/org/linphone/chat/InfoGroupChatFragment.java b/src/android/org/linphone/chat/InfoGroupChatFragment.java
index 711bd5398..115f98d41 100644
--- a/src/android/org/linphone/chat/InfoGroupChatFragment.java
+++ b/src/android/org/linphone/chat/InfoGroupChatFragment.java
@@ -1,5 +1,3 @@
-package org.linphone.chat;
-
/*
InfoGroupChatFragment.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France
@@ -19,6 +17,8 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+package org.linphone.chat;
+
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
diff --git a/src/android/org/linphone/chat/SearchContactsListAdapter.java b/src/android/org/linphone/chat/SearchContactsListAdapter.java
index 05607044d..c8857460c 100644
--- a/src/android/org/linphone/chat/SearchContactsListAdapter.java
+++ b/src/android/org/linphone/chat/SearchContactsListAdapter.java
@@ -1,5 +1,3 @@
-package org.linphone.chat;
-
/*
SearchContactsListAdapter.java
Copyright (C) 2017 Belledonne Communications, Grenoble, France
@@ -19,6 +17,8 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+package org.linphone.chat;
+
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;