Started ChatEventsAdapter

This commit is contained in:
Sylvain Berfini 2017-10-25 10:32:53 +02:00
parent 562b4d5e2b
commit 59a522a421
5 changed files with 240 additions and 71 deletions

View file

@ -54,3 +54,7 @@ username_max_length=64
username_min_length=1 username_min_length=1
username_regex=^[a-z0-9_.\-]*$ username_regex=^[a-z0-9_.\-]*$
xmlrpc_url=https://subscribe.linphone.org:444/wizard.php xmlrpc_url=https://subscribe.linphone.org:444/wizard.php
[server]
db_uri=/data/user/0/org.linphone/files/linphone.db
db_backend=sqlite3

View file

@ -228,6 +228,7 @@ public class LinphoneManager implements CoreListener, ChatMessageListener, Senso
mChatDatabaseFile = basePath + "/linphone-history.db"; mChatDatabaseFile = basePath + "/linphone-history.db";
mCallLogDatabaseFile = basePath + "/linphone-log-history.db"; mCallLogDatabaseFile = basePath + "/linphone-log-history.db";
mFriendsDatabaseFile = basePath + "/linphone-friends.db"; mFriendsDatabaseFile = basePath + "/linphone-friends.db";
mLinphoneTestDb = basePath + "/linphone.db";
mErrorToneFile = basePath + "/error.wav"; mErrorToneFile = basePath + "/error.wav";
mUserCertificatePath = basePath; mUserCertificatePath = basePath;
@ -258,6 +259,7 @@ public class LinphoneManager implements CoreListener, ChatMessageListener, Senso
private final String mFriendsDatabaseFile; private final String mFriendsDatabaseFile;
private final String mErrorToneFile; private final String mErrorToneFile;
private final String mUserCertificatePath; private final String mUserCertificatePath;
private final String mLinphoneTestDb;
private byte[] mUploadingImage; private byte[] mUploadingImage;
private Timer mTimer; private Timer mTimer;
@ -939,6 +941,7 @@ public class LinphoneManager implements CoreListener, ChatMessageListener, Senso
copyIfNotExist(R.raw.lpconfig, mLPConfigXsd); copyIfNotExist(R.raw.lpconfig, mLPConfigXsd);
copyFromPackage(R.raw.rootca, new File(mLinphoneRootCaFile).getName()); copyFromPackage(R.raw.rootca, new File(mLinphoneRootCaFile).getName());
copyFromPackage(R.raw.assistant_create, new File(mDynamicConfigFile).getName()); copyFromPackage(R.raw.assistant_create, new File(mDynamicConfigFile).getName());
copyFromPackage(R.raw.linphone, new File(mLinphoneTestDb).getName());
} }
public void copyIfNotExist(int ressourceId, String target) throws IOException { public void copyIfNotExist(int ressourceId, String target) throws IOException {

View file

@ -19,23 +19,58 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
package org.linphone.chat; package org.linphone.chat;
import android.content.Context;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import android.widget.RelativeLayout;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneUtils;
import org.linphone.R; import org.linphone.R;
import org.linphone.activities.LinphoneActivity;
import org.linphone.compatibility.Compatibility;
import org.linphone.contacts.ContactsManager;
import org.linphone.contacts.LinphoneContact;
import org.linphone.core.Address;
import org.linphone.core.ChatMessage; import org.linphone.core.ChatMessage;
import org.linphone.core.Core;
import org.linphone.core.EventLog;
import java.util.ArrayList; import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Pattern;
public class ChatEventsAdapter extends BaseAdapter { public class ChatEventsAdapter extends BaseAdapter {
private ArrayList<ChatMessage> mHistory; private Context mContext;
private List<EventLog> mHistory;
private List<LinphoneContact> mParticipants;
private LayoutInflater mLayoutInflater; private LayoutInflater mLayoutInflater;
public ChatEventsAdapter(LayoutInflater inflater) { public ChatEventsAdapter(Context context, LayoutInflater inflater, EventLog[] history, List<LinphoneContact> participants) {
mContext = context;
mLayoutInflater = inflater; mLayoutInflater = inflater;
mHistory = new ArrayList<>(); //TODO mHistory = Arrays.asList(history);
mParticipants = participants;
}
public void updateHistory(EventLog[] history) {
mHistory = Arrays.asList(history);
notifyDataSetChanged();
}
public void addToHistory(EventLog log) {
mHistory.add(log);
notifyDataSetChanged();
}
public void setContacts(List<LinphoneContact> participants) {
mParticipants = participants;
} }
@Override @Override
@ -64,11 +99,190 @@ public class ChatEventsAdapter extends BaseAdapter {
view.setTag(holder); view.setTag(holder);
} }
ChatMessage msg = (ChatMessage)getItem(i); holder.eventLayout.setVisibility(View.GONE);
holder.messageId = msg.getMessageId(); holder.bubbleLayout.setVisibility(View.GONE);
holder.delete.setVisibility(View.GONE);
holder.messageText.setVisibility(View.GONE);
holder.messageImage.setVisibility(View.GONE);
holder.fileExtensionLabel.setVisibility(View.GONE);
holder.fileNameLabel.setVisibility(View.GONE);
holder.fileTransferLayout.setVisibility(View.GONE);
holder.fileTransferProgressBar.setProgress(0);
holder.fileTransferAction.setEnabled(true);
holder.messageStatus.setVisibility(View.INVISIBLE);
holder.messageSendingInProgress.setVisibility(View.GONE);
holder.imdmLayout.setVisibility(View.INVISIBLE);
//TODO EventLog event = (EventLog)getItem(i);
if (event.getType() == EventLog.Type.ConferenceChatMessage) {
holder.bubbleLayout.setVisibility(View.VISIBLE);
ChatMessage message = null;//event.getChatMessage();
holder.messageId = message.getMessageId();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
ChatMessage.State status = message.getState();
Address remoteSender = message.getFromAddress();
String displayName;
if (message.isOutgoing()) {
displayName = remoteSender.getDisplayName();
if (status == ChatMessage.State.InProgress) {
holder.messageSendingInProgress.setVisibility(View.VISIBLE);
}
if (!message.isSecured() && LinphoneManager.getLc().limeEnabled() == Core.LimeState.Mandatory && status != ChatMessage.State.InProgress) {
holder.messageStatus.setVisibility(View.VISIBLE);
holder.messageStatus.setImageResource(R.drawable.chat_unsecure);
}
if (status == ChatMessage.State.DeliveredToUser) {
holder.imdmLayout.setVisibility(View.VISIBLE);
holder.imdmIcon.setImageResource(R.drawable.chat_delivered);
holder.imdmLabel.setText(R.string.delivered);
holder.imdmLabel.setTextColor(mContext.getResources().getColor(R.color.colorD));
} else if (status == ChatMessage.State.Displayed) {
holder.imdmLayout.setVisibility(View.VISIBLE);
holder.imdmIcon.setImageResource(R.drawable.chat_read);
holder.imdmLabel.setText(R.string.displayed);
holder.imdmLabel.setTextColor(mContext.getResources().getColor(R.color.colorK));
} else if (status == ChatMessage.State.NotDelivered) {
holder.imdmLayout.setVisibility(View.VISIBLE);
holder.imdmIcon.setImageResource(R.drawable.chat_error);
holder.imdmLabel.setText(R.string.resend);
holder.imdmLabel.setTextColor(mContext.getResources().getColor(R.color.colorI));
}
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.setMargins(100, 10, 10, 10);
holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_outgoing);
Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font3);
Compatibility.setTextAppearance(holder.fileTransferAction, mContext, R.style.font15);
holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_confirm_delete_button);
holder.contactPictureMask.setImageResource(R.drawable.avatar_chat_mask_outgoing);
} else {
LinphoneContact contact = null;
for (LinphoneContact c : mParticipants) {
if (contact.hasAddress(remoteSender.asStringUriOnly())) {
contact = c;
break;
}
}
if (contact != null) {
if (contact.getFullName() != null) {
displayName = contact.getFullName();
} else {
displayName = remoteSender.getDisplayName();
if (displayName == null || displayName.isEmpty()) {
displayName = remoteSender.getUsername();
}
}
holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
if (contact.hasPhoto()) {
LinphoneUtils.setThumbnailPictureFromUri(LinphoneActivity.instance(), holder.contactPicture, contact.getThumbnailUri());
}
} else {
displayName = remoteSender.getDisplayName();
if (displayName == null || displayName.isEmpty()) {
displayName = remoteSender.getUsername();
}
holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
}
/*if (isEditMode) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
layoutParams.setMargins(100, 10, 10, 10);
}*/
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
layoutParams.setMargins(10, 10, 100, 10);
holder.background.setBackgroundResource(R.drawable.resizable_chat_bubble_incoming);
Compatibility.setTextAppearance(holder.contactName, mContext, R.style.font9);
Compatibility.setTextAppearance(holder.fileTransferAction, mContext, R.style.font8);
holder.fileTransferAction.setBackgroundResource(R.drawable.resizable_assistant_button);
holder.contactPictureMask.setImageResource(R.drawable.avatar_chat_mask);
}
holder.contactName.setText(timestampToHumanDate(mContext, message.getTime()) + " - " + displayName);
Spanned text = null;
String msg = message.getText();
if (msg != null) {
text = getTextWithHttpLinks(msg);
holder.messageText.setText(text);
holder.messageText.setMovementMethod(LinkMovementMethod.getInstance());
holder.messageText.setVisibility(View.VISIBLE);
}
holder.bubbleLayout.setLayoutParams(layoutParams);
} else {
holder.eventLayout.setVisibility(View.VISIBLE);
//TODO
}
return view; return view;
} }
private String timestampToHumanDate(Context context, long timestamp) {
try {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
SimpleDateFormat dateFormat;
if (isToday(cal)) {
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.today_date_format));
} else {
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.messages_date_format));
}
return dateFormat.format(cal.getTime());
} catch (NumberFormatException nfe) {
return String.valueOf(timestamp);
}
}
private boolean isToday(Calendar cal) {
return isSameDay(cal, Calendar.getInstance());
}
private boolean isSameDay(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
return false;
}
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
private Spanned getTextWithHttpLinks(String text) {
if (text.contains("<")) {
text = text.replace("<", "&lt;");
}
if (text.contains(">")) {
text = text.replace(">", "&gt;");
}
if (text.contains("\n")) {
text = text.replace("\n", "<br>");
}
if (text.contains("http://")) {
int indexHttp = text.indexOf("http://");
int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
String link = text.substring(indexHttp, indexFinHttp);
String linkWithoutScheme = link.replace("http://", "");
text = text.replaceFirst(Pattern.quote(link), "<a href=\"" + link + "\">" + linkWithoutScheme + "</a>");
}
if (text.contains("https://")) {
int indexHttp = text.indexOf("https://");
int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
String link = text.substring(indexHttp, indexFinHttp);
String linkWithoutScheme = link.replace("https://", "");
text = text.replaceFirst(Pattern.quote(link), "<a href=\"" + link + "\">" + linkWithoutScheme + "</a>");
}
return Compatibility.fromHtml(text);
}
} }

View file

@ -1393,7 +1393,7 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa
} else { } else {
holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap()); holder.contactPicture.setImageBitmap(ContactsManager.getInstance().getDefaultAvatarBitmap());
} }
holder.contactName.setText(timestampToHumanDate(context, message.getTime()) + " - " + displayName); //holder.contactName.setText(timestampToHumanDate(context, message.getTime()) + " - " + displayName);
if (status == ChatMessage.State.InProgress) { if (status == ChatMessage.State.InProgress) {
holder.messageSendingInProgress.setVisibility(View.VISIBLE); holder.messageSendingInProgress.setVisibility(View.VISIBLE);
@ -1477,12 +1477,12 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa
} else { } else {
Spanned text = null; Spanned text = null;
String msg = message.getText(); String msg = message.getText();
if (msg != null) { /*if (msg != null) {
text = getTextWithHttpLinks(msg); text = getTextWithHttpLinks(msg);
holder.messageText.setText(text); holder.messageText.setText(text);
holder.messageText.setMovementMethod(LinkMovementMethod.getInstance()); holder.messageText.setMovementMethod(LinkMovementMethod.getInstance());
holder.messageText.setVisibility(View.VISIBLE); holder.messageText.setVisibility(View.VISIBLE);
} }*/
} }
if (message.isOutgoing()) { if (message.isOutgoing()) {
@ -1643,66 +1643,6 @@ public class ChatFragment extends Fragment implements OnClickListener, ChatMessa
return view; return view;
} }
private String timestampToHumanDate(Context context, long timestamp) {
try {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
SimpleDateFormat dateFormat;
if (isToday(cal)) {
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.today_date_format));
} else {
dateFormat = new SimpleDateFormat(context.getResources().getString(R.string.messages_date_format));
}
return dateFormat.format(cal.getTime());
} catch (NumberFormatException nfe) {
return String.valueOf(timestamp);
}
}
private boolean isToday(Calendar cal) {
return isSameDay(cal, Calendar.getInstance());
}
private boolean isSameDay(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null) {
return false;
}
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
private Spanned getTextWithHttpLinks(String text) {
if (text.contains("<")) {
text = text.replace("<", "&lt;");
}
if (text.contains(">")) {
text = text.replace(">", "&gt;");
}
if (text.contains("\n")) {
text = text.replace("\n", "<br>");
}
if (text.contains("http://")) {
int indexHttp = text.indexOf("http://");
int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
String link = text.substring(indexHttp, indexFinHttp);
String linkWithoutScheme = link.replace("http://", "");
text = text.replaceFirst(Pattern.quote(link), "<a href=\"" + link + "\">" + linkWithoutScheme + "</a>");
}
if (text.contains("https://")) {
int indexHttp = text.indexOf("https://");
int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
String link = text.substring(indexHttp, indexFinHttp);
String linkWithoutScheme = link.replace("https://", "");
text = text.replaceFirst(Pattern.quote(link), "<a href=\"" + link + "\">" + linkWithoutScheme + "</a>");
}
return Compatibility.fromHtml(text);
}
public void loadBitmap(String path, ImageView imageView) { public void loadBitmap(String path, ImageView imageView) {
if (cancelPotentialWork(path, imageView)) { if (cancelPotentialWork(path, imageView)) {
if(LinphoneUtils.isExtensionImage(path)) if(LinphoneUtils.isExtensionImage(path))

View file

@ -267,6 +267,10 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
mParticipants.add(c); mParticipants.add(c);
} }
} }
if (mMessagesAdapter != null) {
mMessagesAdapter.setContacts(mParticipants);
}
} }
private void initChatRoom() { private void initChatRoom() {
@ -320,7 +324,7 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
} }
private void displayChatRoomHistory() { private void displayChatRoomHistory() {
mMessagesAdapter = new ChatEventsAdapter(mInflater); mMessagesAdapter = new ChatEventsAdapter(getActivity(), mInflater, mChatRoom.getHistoryEvents(0), mParticipants);
mChatEventsList.setAdapter(mMessagesAdapter); mChatEventsList.setAdapter(mMessagesAdapter);
} }
@ -373,6 +377,10 @@ public class GroupChatFragment extends Fragment implements ChatRoomListener, Con
mMessageTextToSend.setText(""); mMessageTextToSend.setText("");
} }
private void scrollToBottom() {
mChatEventsList.setSelection(mMessagesAdapter.getCount() - 1);
}
@Override @Override
public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) { public void onUndecryptableMessageReceived(ChatRoom cr, ChatMessage msg) {
final Address from = msg.getFromAddress(); final Address from = msg.getFromAddress();