Add new items for chat
BIN
res/drawable-xhdpi/chat_attachment_default.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
res/drawable-xhdpi/chat_attachment_over.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/chat_picture_over" />
|
||||
android:drawable="@drawable/chat_attachment_over" />
|
||||
<item
|
||||
android:drawable="@drawable/chat_picture_default" />
|
||||
android:drawable="@drawable/chat_attachment_default" />
|
||||
</selector>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
|
@ -120,7 +120,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/chat_send_picture" />
|
||||
android:src="@drawable/chat_send_file" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/sendMessage"
|
||||
|
@ -220,4 +220,21 @@
|
|||
android:layout_marginBottom="10dp"
|
||||
android:layout_below="@+id/topBar"/>
|
||||
|
||||
<AutoCompleteTextView
|
||||
android:contentDescription="@string/content_description_search"
|
||||
android:textCursorDrawable="@null"
|
||||
android:visibility="gone"
|
||||
android:layout_margin="10dp"
|
||||
android:id="@+id/searchContactField"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:textColor="@android:color/black"
|
||||
android:background="@drawable/resizable_textfield"
|
||||
android:gravity="center"
|
||||
android:completionThreshold="1"
|
||||
android:layout_below="@+id/topBar"
|
||||
android:paddingRight="5dp"
|
||||
android:inputType="textPersonName"/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
|
@ -1,8 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/fragmentContainer"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/status"
|
||||
android:name="org.linphone.StatusFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
tools:layout="@layout/status" />
|
||||
|
||||
</LinearLayout>
|
39
res/layout/search_contact_cell.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:background="@drawable/list_selector"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/Contact_name"
|
||||
android:lines="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@id/icon"
|
||||
android:layout_centerVertical="true"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textColor="@color/text_contrast"
|
||||
android:layout_marginLeft="10dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/contact_address"
|
||||
android:visibility="gone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_marginRight="20dp"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -28,6 +28,7 @@ import android.os.Bundle;
|
|||
public class ChatActivity extends Activity {
|
||||
private static final String CHAT_FRAGMENT = "chatFragment";
|
||||
private ChatFragment chatFragment;
|
||||
private StatusFragment status;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -35,10 +36,12 @@ public class ChatActivity extends Activity {
|
|||
setContentView(R.layout.chat_activity);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
if( getIntent().getExtras() != null) {
|
||||
extras.putString("SipUri", getIntent().getExtras().getString("SipUri"));
|
||||
extras.putString("DisplayName", getIntent().getExtras().getString("DisplayName"));
|
||||
extras.putString("PictureUri", getIntent().getExtras().getString("PictureUri"));
|
||||
extras.putString("ThumbnailUri", getIntent().getExtras().getString("ThumbnailUri"));
|
||||
}
|
||||
|
||||
ChatFragment fragment = new ChatFragment();
|
||||
fragment.setArguments(extras);
|
||||
|
@ -54,6 +57,12 @@ public class ChatActivity extends Activity {
|
|||
chatFragment.setArguments(extras);
|
||||
fm.beginTransaction().add(R.id.fragmentContainer, chatFragment, CHAT_FRAGMENT).commit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void updateStatusFragment(StatusFragment fragment) {
|
||||
status = fragment;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,10 @@ import java.io.File;
|
|||
import android.app.Fragment;
|
||||
import android.graphics.Matrix;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
|
||||
import org.linphone.compatibility.Compatibility;
|
||||
|
@ -39,6 +42,8 @@ import org.linphone.core.LinphoneChatMessage.State;
|
|||
import org.linphone.core.LinphoneCoreException;
|
||||
import org.linphone.core.LinphoneCoreFactory;
|
||||
import org.linphone.core.LinphoneCoreListenerBase;
|
||||
import org.linphone.core.LinphoneFriend;
|
||||
import org.linphone.core.PresenceActivityType;
|
||||
import org.linphone.mediastream.Log;
|
||||
import org.linphone.ui.BubbleChat;
|
||||
|
||||
|
@ -73,13 +78,18 @@ import android.view.ViewGroup;
|
|||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Filter;
|
||||
import android.widget.Filterable;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.SectionIndexer;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
|
@ -100,6 +110,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
private ImageView cancelUpload, edit, selectAll, deselectAll, startCall, delete, sendImage, sendMessage;
|
||||
private TextView contactName, remoteComposing;
|
||||
private ImageView back;
|
||||
private AutoCompleteTextView searchContactField;
|
||||
private RelativeLayout uploadLayout, textLayout, topBar;
|
||||
private ListView messagesList;
|
||||
|
||||
|
@ -112,6 +123,7 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
private LinphoneCoreListenerBase mListener;
|
||||
private ByteArrayInputStream mUploadingImageStream;
|
||||
private LinphoneChatMessage currentMessageInFileTransferUploadState;
|
||||
private boolean newChatConversation = false;
|
||||
|
||||
public static boolean isInstanciated() {
|
||||
return instance != null;
|
||||
|
@ -127,15 +139,21 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
// Retain the fragment across configuration changes
|
||||
setRetainInstance(true);
|
||||
|
||||
if(getArguments() == null || getArguments().getString("SipUri") == null) {
|
||||
newChatConversation = true;
|
||||
} else {
|
||||
//Retrieve parameter from intent
|
||||
sipUri = getArguments().getString("SipUri");
|
||||
displayName = getArguments().getString("DisplayName");
|
||||
pictureUri = getArguments().getString("PictureUri");
|
||||
}
|
||||
|
||||
//Initialize UI
|
||||
contactName = (TextView) view.findViewById(R.id.contact_name);
|
||||
//contactPicture = (ImageView) view.findViewById(R.id.contactPicture);
|
||||
messagesList = (ListView) view.findViewById(R.id.chatMessageList);
|
||||
searchContactField = (AutoCompleteTextView) view.findViewById(R.id.searchContactField);
|
||||
|
||||
textLayout = (RelativeLayout) view.findViewById(R.id.messageLayout);
|
||||
progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
|
||||
topBar = (RelativeLayout) view.findViewById(R.id.topBar);
|
||||
|
@ -164,8 +182,20 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
delete = (ImageView) view.findViewById(R.id.delete);
|
||||
delete.setOnClickListener(this);
|
||||
|
||||
|
||||
if (newChatConversation) {
|
||||
messagesList.setVisibility(View.GONE);
|
||||
searchContactField.setVisibility(View.VISIBLE);
|
||||
searchContactField.setAdapter(new SearchContactsListAdapter(ContactsManager.getInstance().getAllContacts(), null, inflater));
|
||||
edit.setVisibility(View.INVISIBLE);
|
||||
startCall.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
displayChatHeader(displayName, pictureUri);
|
||||
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
if (lc != null) {
|
||||
chatRoom = lc.getOrCreateChatRoom(sipUri);
|
||||
chatRoom.markAsRead();
|
||||
}
|
||||
}
|
||||
|
||||
//Manage multiline
|
||||
message = (EditText) view.findViewById(R.id.message);
|
||||
|
@ -211,13 +241,6 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
}
|
||||
});
|
||||
|
||||
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
if (lc != null) {
|
||||
chatRoom = lc.getOrCreateChatRoom(sipUri);
|
||||
//Only works if using liblinphone storage
|
||||
chatRoom.markAsRead();
|
||||
}
|
||||
|
||||
mListener = new LinphoneCoreListenerBase(){
|
||||
@Override
|
||||
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
|
||||
|
@ -534,8 +557,11 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
String draft = getArguments().getString("messageDraft");
|
||||
message.setText(draft);
|
||||
|
||||
|
||||
if(!newChatConversation) {
|
||||
remoteComposing.setVisibility(chatRoom.isRemoteComposing() ? View.VISIBLE : View.GONE);
|
||||
dispayMessageList();
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
|
@ -585,6 +611,38 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
boolean isNetworkReachable = lc == null ? false : lc.isNetworkReachable();
|
||||
|
||||
if(newChatConversation){
|
||||
String address = searchContactField.getText().toString();
|
||||
if(address != null && !address.equals("")) {
|
||||
if (!LinphoneUtils.isSipAddress(address)) {
|
||||
if (LinphoneManager.getLc().getDefaultProxyConfig() == null) {
|
||||
Log.w("Error");
|
||||
}
|
||||
address = address + "@" + LinphoneManager.getLc().getDefaultProxyConfig().getDomain();
|
||||
if (!LinphoneUtils.isStrictSipAddress(address)) {
|
||||
address = "sip:" + address;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(address);
|
||||
LinphoneAddress lAddress;
|
||||
try {
|
||||
lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(address);
|
||||
} catch (LinphoneCoreException e) {
|
||||
Log.e("Cannot display chat",e);
|
||||
return;
|
||||
}
|
||||
|
||||
chatRoom = lc.getOrCreateChatRoom(lAddress.toString());
|
||||
|
||||
if (chatRoom != null && messageToSend != null && messageToSend.length() > 0 && isNetworkReachable) {
|
||||
LinphoneChatMessage message = chatRoom.createLinphoneChatMessage(messageToSend);
|
||||
chatRoom.sendChatMessage(message);
|
||||
LinphoneActivity.instance().displayChat(lAddress.toString());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (chatRoom != null && messageToSend != null && messageToSend.length() > 0 && isNetworkReachable) {
|
||||
LinphoneChatMessage message = chatRoom.createLinphoneChatMessage(messageToSend);
|
||||
chatRoom.sendChatMessage(message);
|
||||
|
@ -594,13 +652,13 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
}
|
||||
|
||||
message.setListener(LinphoneManager.getInstance());
|
||||
|
||||
invalidate();
|
||||
Log.i("Sent message current status: " + message.getStatus());
|
||||
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
|
||||
LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendImageMessage(String path) {
|
||||
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
|
||||
|
@ -810,4 +868,111 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
|
|||
public void onLinphoneChatMessageFileTransferProgressChanged(LinphoneChatMessage msg, LinphoneContent content, int offset, int total) {
|
||||
progressBar.setProgress(offset * 100 / total);
|
||||
}
|
||||
|
||||
class SearchContactsListAdapter extends BaseAdapter implements Filterable {
|
||||
private List<ContactAddress> contacts;
|
||||
private Cursor cursor;
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
SearchContactsListAdapter(List<Contact> contactsList, Cursor c, LayoutInflater inflater) {
|
||||
cursor = c;
|
||||
mInflater = inflater;
|
||||
contacts = new ArrayList<ContactAddress>();
|
||||
for(Contact con: ContactsManager.getInstance().getAllContacts()){
|
||||
for(String numberOrAddress : con.getNumbersOrAddresses()){
|
||||
contacts.add(new ContactAddress(con,numberOrAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Filter getFilter() {
|
||||
return new Filter() {
|
||||
@Override
|
||||
protected void publishResults(CharSequence constraint,
|
||||
FilterResults results) {
|
||||
if (results.count > 0) {
|
||||
notifyDataSetChanged();
|
||||
} else {
|
||||
notifyDataSetInvalidated();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FilterResults performFiltering(CharSequence constraint) {
|
||||
List<ContactAddress> result = new ArrayList<ContactAddress>();
|
||||
Log.w(constraint);
|
||||
if(constraint != null) {
|
||||
for (ContactAddress c : contacts) {
|
||||
Log.w(c.mAddress);
|
||||
Log.w(c.mContact.getName());
|
||||
if (c.mContact.getName().startsWith(constraint.toString()) || c.mAddress.startsWith(constraint.toString())) {
|
||||
result.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
FilterResults r = new FilterResults();
|
||||
r.values = result;
|
||||
r.count = result.size();
|
||||
return r;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class ContactAddress {
|
||||
public Contact mContact;
|
||||
public String mAddress;
|
||||
|
||||
ContactAddress(Contact contact, String address){
|
||||
mContact = contact;
|
||||
mAddress = address;
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return contacts.size();
|
||||
}
|
||||
|
||||
public Object getItem(int position) {
|
||||
if (contacts == null || position >= contacts.size()) {
|
||||
List<ContactAddress> contacts_list = new ArrayList<ContactAddress>();
|
||||
for(Contact c: ContactsManager.getInstance().getAllContacts()){
|
||||
for(String numberOrAddress : c.getNumbersOrAddresses()){
|
||||
contacts_list.add(new ContactAddress(c,numberOrAddress));
|
||||
}
|
||||
}
|
||||
return contacts_list;
|
||||
} else {
|
||||
return contacts.get(position);
|
||||
}
|
||||
}
|
||||
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view = null;
|
||||
ContactAddress contact = null;
|
||||
do {
|
||||
contact = (ContactAddress) getItem(position);
|
||||
} while (contact == null);
|
||||
|
||||
if (convertView != null) {
|
||||
view = convertView;
|
||||
} else {
|
||||
view = mInflater.inflate(R.layout.search_contact_cell, parent, false);
|
||||
}
|
||||
|
||||
TextView name = (TextView) view.findViewById(R.id.Contact_name);
|
||||
name.setText(contact.mContact.getName());
|
||||
|
||||
TextView address = (TextView) view.findViewById(R.id.contact_address);
|
||||
address.setText(contact.mAddress);
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
|
|||
hideAndDisplayMessageIfNoChat();
|
||||
}
|
||||
else if (id == R.id.new_discussion) {
|
||||
LinphoneActivity.instance().displayChat(null);
|
||||
/*String sipUri = fastNewChat.getText().toString();
|
||||
if (sipUri.equals("")) {
|
||||
LinphoneActivity.instance().displayContacts(true);
|
||||
|
@ -247,7 +248,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
|
|||
if (!LinphoneUtils.isStrictSipAddress(sipUri)) {
|
||||
sipUri = "sip:" + sipUri;
|
||||
}
|
||||
LinphoneActivity.instance().displayChat(sipUri);
|
||||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|