From 313a80d517426bd2dcb850a218fd2a98fe4451da Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 24 Oct 2017 10:37:51 +0200 Subject: [PATCH] More work on GroupChatFragment --- res/values/strings.xml | 3 +- src/android/org/linphone/LinphoneManager.java | 52 +---- .../linphone/chat/ChatBubbleViewHolder.java | 30 +-- .../org/linphone/chat/ChatEventsAdapter.java | 31 ++- .../org/linphone/chat/ChatFragment.java | 4 +- .../org/linphone/chat/GroupChatFragment.java | 182 ++++++++++++++++-- 6 files changed, 195 insertions(+), 107 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 6cf32ec1a..218bbcacb 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -170,7 +170,8 @@ Do you want to delete selected conversation? Do you want to delete selected message? Remote is writing... - %s is writing... + %s is writing... + %s are writing... Small Medium Large diff --git a/src/android/org/linphone/LinphoneManager.java b/src/android/org/linphone/LinphoneManager.java index bee21190d..473cd1bd3 100644 --- a/src/android/org/linphone/LinphoneManager.java +++ b/src/android/org/linphone/LinphoneManager.java @@ -619,57 +619,7 @@ public class LinphoneManager implements CoreListener, ChatMessageListener, Senso @Override public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage message) { - if (mServiceContext.getResources().getBoolean(R.bool.disable_chat)) { - return; - } - final Address from = message.getFromAddress(); - String to = message.getToAddress().asString(); - try { - final LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(from); - if (LinphoneActivity.instance().isOnBackground()) { - if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat_message_notification)) { - if (contact != null) { - LinphoneService.instance().removedNotification(to, from.asStringUriOnly(), contact.getFullName() - , getString(R.string.message_cant_be_decrypted_notif)); - } else { - LinphoneService.instance().removedNotification(to, from.asStringUriOnly(), from.getUsername() - , getString(R.string.message_cant_be_decrypted_notif)); - } - } - } else if (!mAreDisplayAlertMessage){ - mAreDisplayAlertMessage = true; - final Dialog dialog = LinphoneActivity.instance().displayDialog( - getString(R.string.message_cant_be_decrypted).replace("%s" - , (contact != null) ? contact.getFullName() : from.getUsername())); - Button delete = (Button) dialog.findViewById(R.id.delete_button); - delete.setText(getString(R.string.call)); - Button cancel = (Button) dialog.findViewById(R.id.cancel); - cancel.setText(getString(R.string.ok)); - - delete.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - LinphoneManager.getInstance().newOutgoingCall(from.asStringUriOnly() - , (contact != null) ? contact.getFullName() : from.getUsername()); - dialog.dismiss(); - LinphoneManager.getInstance().setAreDisplayAlertMessage(false); - } - }); - - cancel.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - dialog.dismiss(); - LinphoneManager.getInstance().setAreDisplayAlertMessage(false); - } - }); - if(LinphoneManager.getLc().limeEnabled() == Core.LimeState.Mandatory) - dialog.show(); - } - } catch (Exception e) { - Log.e(e); - } } @Override @@ -1839,7 +1789,7 @@ public class LinphoneManager implements CoreListener, ChatMessageListener, Senso @Override public void onChatRoomInstantiated(Core lc, ChatRoom cr) { - cr.setListener(this); + } @Override diff --git a/src/android/org/linphone/chat/ChatBubbleViewHolder.java b/src/android/org/linphone/chat/ChatBubbleViewHolder.java index f573b9a0a..d315eb070 100644 --- a/src/android/org/linphone/chat/ChatBubbleViewHolder.java +++ b/src/android/org/linphone/chat/ChatBubbleViewHolder.java @@ -29,13 +29,9 @@ 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 class ChatBubbleViewHolder { + public String messageId; public LinearLayout eventLayout; public TextView eventTime; @@ -61,8 +57,6 @@ public class ChatBubbleViewHolder implements ChatMessageListener { 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); @@ -86,24 +80,4 @@ public class ChatBubbleViewHolder implements ChatMessageListener { fileExtensionLabel = view.findViewById(R.id.file_extension); fileNameLabel = 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 index d94803553..aac734da2 100644 --- a/src/android/org/linphone/chat/ChatEventsAdapter.java +++ b/src/android/org/linphone/chat/ChatEventsAdapter.java @@ -19,40 +19,55 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. package org.linphone.chat; -import android.content.Context; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; +import org.linphone.R; import org.linphone.core.ChatMessage; import java.util.ArrayList; public class ChatEventsAdapter extends BaseAdapter { private ArrayList mHistory; - private Context mContext; - - public ChatEventsAdapter() { + private LayoutInflater mLayoutInflater; + public ChatEventsAdapter(LayoutInflater inflater) { + mLayoutInflater = inflater; } @Override public int getCount() { - return 0; + return mHistory.size(); } @Override public Object getItem(int i) { - return null; + return mHistory.get(i); } @Override public long getItemId(int i) { - return 0; + return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { - return null; + ChatBubbleViewHolder holder; + if (view != null) { + holder = (ChatBubbleViewHolder) view.getTag(); + } else { + view = mLayoutInflater.inflate(R.layout.chat_bubble, null); + holder = new ChatBubbleViewHolder(view); + view.setTag(holder); + } + + ChatMessage msg = (ChatMessage)getItem(i); + holder.messageId = msg.getMessageId(); + + //TODO + + return view; } } diff --git a/src/android/org/linphone/chat/ChatFragment.java b/src/android/org/linphone/chat/ChatFragment.java index 6faebd3e2..33abaca3a 100644 --- a/src/android/org/linphone/chat/ChatFragment.java +++ b/src/android/org/linphone/chat/ChatFragment.java @@ -1329,7 +1329,7 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa view.setTag(holder); } - LinphoneManager.addListener(holder); + /*LinphoneManager.addListener(holder); if (holder.id == message.getStorageId()) { // Horrible workaround to not reload image on edit chat list if (holder.messageImage.getTag() != null @@ -1341,7 +1341,7 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa } else { holder.id = message.getStorageId(); } - view.setId(holder.id); + view.setId(holder.id);*/ registerForContextMenu(view); view.setOnClickListener(new OnClickListener() { @Override diff --git a/src/android/org/linphone/chat/GroupChatFragment.java b/src/android/org/linphone/chat/GroupChatFragment.java index b4a213eba..22d35bf17 100644 --- a/src/android/org/linphone/chat/GroupChatFragment.java +++ b/src/android/org/linphone/chat/GroupChatFragment.java @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. package org.linphone.chat; +import android.app.Dialog; import android.app.Fragment; import android.os.Bundle; import android.text.Editable; @@ -26,19 +27,23 @@ import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; import org.linphone.LinphoneManager; +import org.linphone.LinphoneService; import org.linphone.R; import org.linphone.activities.LinphoneActivity; import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactsManager; import org.linphone.contacts.LinphoneContact; import org.linphone.core.Address; +import org.linphone.core.Buffer; import org.linphone.core.ChatMessage; +import org.linphone.core.ChatMessageListener; import org.linphone.core.ChatRoom; import org.linphone.core.ChatRoomListener; import org.linphone.core.Content; @@ -48,6 +53,8 @@ import org.linphone.core.Participant; import java.util.ArrayList; import java.util.List; +import static org.linphone.fragments.FragmentsAvailable.CHAT; + public class GroupChatFragment extends Fragment implements ChatRoomListener { private ImageView mBackButton, mCallButton, mBackToCallButton, mGroupInfosButton, mEditButton; private ImageView mCancelEditButton, mSelectAllButton, mDeselectAllButton, mDeleteSelectionButton; @@ -130,7 +137,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mEditButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -138,7 +145,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mCancelEditButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -146,7 +153,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mSelectAllButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -154,7 +161,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mDeselectAllButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -162,7 +169,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mDeleteSelectionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -172,7 +179,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mAttachImageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + //TODO } }); @@ -180,16 +187,14 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { mSendMessageButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - + sendMessage(); } }); mMessageTextToSend = view.findViewById(R.id.message); mMessageTextToSend.addTextChangedListener(new TextWatcher() { @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { - - } + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @@ -200,9 +205,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { } @Override - public void afterTextChanged(Editable editable) { - - } + public void afterTextChanged(Editable editable) { } }); mRemoteComposing = view.findViewById(R.id.remote_composing); @@ -215,6 +218,11 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { @Override public void onResume() { super.onResume(); + + if (LinphoneActivity.isInstanciated()) { + LinphoneActivity.instance().selectMenu(CHAT); + } + initChatRoom(); displayChatRoomHeader(); displayChatRoomHistory(); @@ -282,12 +290,100 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { } private void displayChatRoomHistory() { - mMessagesAdapter = new ChatEventsAdapter(); + mMessagesAdapter = new ChatEventsAdapter(mInflater); + //TODO + } + + private void sendMessage() { + String text = mMessageTextToSend.getText().toString(); + ChatMessage msg = mChatRoom.createMessage(text); + msg.setListener(new ChatMessageListener() { + @Override + public void onFileTransferRecv(ChatMessage message, Content content, Buffer buffer) { + + } + + @Override + public Buffer onFileTransferSend(ChatMessage message, Content content, int offset, int size) { + return null; + } + + @Override + public void onFileTransferProgressIndication(ChatMessage message, Content content, int offset, int total) { + ChatBubbleViewHolder holder = (ChatBubbleViewHolder) message.getUserData(); + if (holder != null && message.getMessageId().equals(holder.messageId)) { + holder.fileTransferProgressBar.setProgress(offset * 100 / total); + } + } + + @Override + public void onMsgStateChanged(ChatMessage message, ChatMessage.State state) { + ChatBubbleViewHolder holder = (ChatBubbleViewHolder) message.getUserData(); + if (holder != null && message.getMessageId().equals(holder.messageId)) { + if (state == ChatMessage.State.DeliveredToUser && message.isOutgoing()) { + holder.imdmLayout.setVisibility(View.VISIBLE); + holder.imdmIcon.setImageResource(R.drawable.message_delivered); + holder.imdmLabel.setText(R.string.delivered); + holder.imdmLabel.setTextColor(getResources().getColor(R.color.colorD)); + } else if (state == ChatMessage.State.Displayed && message.isOutgoing()) { + holder.imdmLayout.setVisibility(View.VISIBLE); + holder.imdmIcon.setImageResource(R.drawable.message_read); + holder.imdmLabel.setText(R.string.displayed); + holder.imdmLabel.setTextColor(getResources().getColor(R.color.colorK)); + } else if (state == ChatMessage.State.NotDelivered && message.isOutgoing()) { + holder.imdmLayout.setVisibility(View.VISIBLE); + holder.imdmIcon.setImageResource(R.drawable.message_undelivered); + holder.imdmLabel.setText(R.string.resend); + holder.imdmLabel.setTextColor(getResources().getColor(R.color.colorI)); + } + } + } + }); + msg.send(); + mMessageTextToSend.setText(""); } @Override public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) { + final Address from = msg.getFromAddress(); + final LinphoneContact contact = ContactsManager.getInstance().findContactFromAddress(from); + if (LinphoneActivity.instance().isOnBackground()) { + if (!getResources().getBoolean(R.bool.disable_chat_message_notification)) { + String to = msg.getToAddress().asString(); + if (contact != null) { + LinphoneService.instance().removedNotification(to, from.asStringUriOnly(), + contact.getFullName(), getString(R.string.message_cant_be_decrypted_notif)); + } else { + LinphoneService.instance().removedNotification(to, from.asStringUriOnly(), + from.getUsername(), getString(R.string.message_cant_be_decrypted_notif)); + } + } + } else if (LinphoneManager.getLc().limeEnabled() == Core.LimeState.Mandatory) { + final Dialog dialog = LinphoneActivity.instance().displayDialog( + getString(R.string.message_cant_be_decrypted) + .replace("%s", (contact != null) ? contact.getFullName() : from.getUsername())); + Button delete = dialog.findViewById(R.id.delete_button); + delete.setText(getString(R.string.call)); + Button cancel = dialog.findViewById(R.id.cancel); + cancel.setText(getString(R.string.ok)); + delete.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + LinphoneManager.getInstance().newOutgoingCall(from.asStringUriOnly() + , (contact != null) ? contact.getFullName() : from.getUsername()); + dialog.dismiss(); + } + }); + + cancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + dialog.dismiss(); + } + }); + dialog.show(); + } } @Override @@ -304,9 +400,61 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener { @Override public void onIsComposingReceived(ChatRoom cr, Address remoteAddr, boolean isComposing) { - if (isComposing) { - mRemoteComposing.setText(getString(R.string.remote_composing_2).replace("%s", remoteAddr.getDisplayName())); + if (cr.canHandleParticipants() && cr.getNbParticipants() > 2) { + ArrayList composing = new ArrayList<>(); + for (Address a : cr.getComposingAddresses()) { + boolean found = false; + for (LinphoneContact c : mParticipants) { + if (c.hasAddress(a.asStringUriOnly())) { + composing.add(c.getFullName()); + found = true; + break; + } + } + if (!found) { + String displayName = a.getDisplayName(); + if (displayName != null && !displayName.isEmpty()) { + composing.add(displayName); + } else { + composing.add(a.getUsername()); + } + } + } + + if (composing.size() == 1) { + mRemoteComposing.setText(getString(R.string.remote_composing_single).replace("%s", composing.get(0))); + mRemoteComposing.setVisibility(View.VISIBLE); + } else if (composing.size() > 2) { + StringBuilder remotes = new StringBuilder(); + int i = 0; + for (String remote : composing) { + remotes.append(remote); + i++; + if (i != composing.size()) { + remotes.append(", "); + } + } + mRemoteComposing.setText(getString(R.string.remote_composing_multiple).replace("%s", remotes.toString())); + mRemoteComposing.setVisibility(View.VISIBLE); + } else { + mRemoteComposing.setVisibility(View.GONE); + } + } else { + if (isComposing) { + String displayName; + if (mParticipants.size() > 0) { + displayName = mParticipants.get(0).getFullName(); + } else { + displayName = remoteAddr.getDisplayName(); + if (displayName == null || displayName.isEmpty()) { + displayName = remoteAddr.getUsername(); + } + } + mRemoteComposing.setText(getString(R.string.remote_composing_single).replace("%s", displayName)); + mRemoteComposing.setVisibility(View.VISIBLE); + } else { + mRemoteComposing.setVisibility(View.GONE); + } } - mRemoteComposing.setVisibility(isComposing ? View.VISIBLE : View.GONE); } }