/* ChatCreationFragment.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.app.Fragment; 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.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.EditText; import android.widget.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; import org.linphone.LinphoneManager; import org.linphone.LinphonePreferences; import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactsManager; import org.linphone.contacts.LinphoneNumberOrAddress; import org.linphone.contacts.SearchContactsListAdapter; import org.linphone.core.Address; import org.linphone.core.ChatRoom; import org.linphone.core.ChatRoomListenerStub; import org.linphone.core.Core; import org.linphone.core.Factory; import org.linphone.core.ProxyConfig; import org.linphone.mediastream.Log; import org.linphone.ui.ContactSelectView; import org.linphone.contacts.ContactsUpdatedListener; import org.linphone.activities.LinphoneActivity; import org.linphone.R; import java.util.ArrayList; import java.util.List; import static android.content.Context.INPUT_METHOD_SERVICE; public class ChatCreationFragment extends Fragment implements View.OnClickListener, AdapterView.OnItemClickListener, ContactsUpdatedListener { private LayoutInflater mInflater; private ListView mContactsList; private LinearLayout mContactsSelectedLayout; private HorizontalScrollView mContactsSelectLayout; private ArrayList mContactsSelected; private ImageView mAllContactsButton, mLinphoneContactsButton, mClearSearchFieldButton, mBackButton, mNextButton; private boolean mOnlyDisplayLinphoneContacts; private View mAllContactsSelected, mLinphoneContactsSelected; private RelativeLayout mSearchLayout, mWaitLayout; private EditText mSearchField; private ProgressBar mContactsFetchInProgress; private SearchContactsListAdapter mSearchAdapter; private String mChatRoomSubject, mChatRoomAddress; private ChatRoom mChatRoom; private ChatRoomListenerStub mChatRoomCreationListener; private Bundle mShareInfos; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mInflater = inflater; View view = inflater.inflate(R.layout.chat_create, container, false); mContactsSelected = new ArrayList<>(); mChatRoomSubject = null; mChatRoomAddress = null; if (getArguments() != null) { if (getArguments().getSerializable("selectedContacts") != null) { mContactsSelected = (ArrayList) getArguments().getSerializable("selectedContacts"); } mChatRoomSubject = getArguments().getString("subject"); mChatRoomAddress = getArguments().getString("groupChatRoomAddress"); } mWaitLayout = view.findViewById(R.id.waitScreen); mWaitLayout.setVisibility(View.GONE); mContactsList = view.findViewById(R.id.contactsList); mContactsSelectedLayout = view.findViewById(R.id.contactsSelected); mContactsSelectLayout = view.findViewById(R.id.layoutContactsSelected); mAllContactsButton = view.findViewById(R.id.all_contacts); mAllContactsButton.setOnClickListener(this); mLinphoneContactsButton = view.findViewById(R.id.linphone_contacts); mLinphoneContactsButton.setOnClickListener(this); mAllContactsSelected = view.findViewById(R.id.all_contacts_select); mLinphoneContactsSelected = view.findViewById(R.id.linphone_contacts_select); mBackButton = view.findViewById(R.id.back); mBackButton.setOnClickListener(this); mNextButton = view.findViewById(R.id.next); mNextButton.setOnClickListener(this); mNextButton.setEnabled(false); mSearchLayout = view.findViewById(R.id.layoutSearchField); mClearSearchFieldButton = view.findViewById(R.id.clearSearchField); mClearSearchFieldButton.setOnClickListener(this); mContactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress); mContactsFetchInProgress.setVisibility(View.VISIBLE); mSearchAdapter = new SearchContactsListAdapter(null, mInflater, mContactsFetchInProgress); mSearchField = view.findViewById(R.id.searchField); mSearchField.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (before > count) { ContactsManager.getInstance().getMagicSearch().resetSearchCache(); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { mSearchAdapter.searchContacts(mSearchField.getText().toString(), mContactsList); } }); mContactsList.setAdapter(mSearchAdapter); mContactsList.setOnItemClickListener(this); if (savedInstanceState != null && savedInstanceState.getStringArrayList("mContactsSelected") != null) { mContactsSelectedLayout.removeAllViews(); // We need to get all contacts not only sip for (String uri : savedInstanceState.getStringArrayList("mContactsSelected")) { for (ContactAddress ca : mSearchAdapter.getContactsList()) { if (ca.getAddressAsDisplayableString().compareTo(uri) == 0) { ca.setView(null); addSelectedContactAddress(ca); break; } } } updateList(); updateListSelected(); } mOnlyDisplayLinphoneContacts = ContactsManager.getInstance().getSIPContacts().size() > 0 ? true : false; if (savedInstanceState != null ) { mOnlyDisplayLinphoneContacts = savedInstanceState.getBoolean("onlySipContact", true); } mSearchAdapter.setOnlySipContact(mOnlyDisplayLinphoneContacts); updateList(); displayChatCreation(); mChatRoomCreationListener = new ChatRoomListenerStub() { @Override public void onStateChanged(ChatRoom cr, ChatRoom.State newState) { if (newState == ChatRoom.State.Created) { mWaitLayout.setVisibility(View.GONE); LinphoneActivity.instance().goToChat(cr.getPeerAddress().asStringUriOnly(), mShareInfos); } else if (newState == ChatRoom.State.CreationFailed) { mWaitLayout.setVisibility(View.GONE); LinphoneActivity.instance().displayChatRoomError(); Log.e("Group chat room for address " + cr.getPeerAddress() + " has failed !"); } } }; if (getArguments() != null) { String fileSharedUri = getArguments().getString("fileSharedUri"); String messageDraft = getArguments().getString("messageDraft"); if (fileSharedUri != null || messageDraft != null) mShareInfos = new Bundle(); if (fileSharedUri != null) { LinphoneActivity.instance().checkAndRequestPermissionsToSendImage(); mShareInfos.putString("fileSharedUri", fileSharedUri); } if (messageDraft != null) mShareInfos.putString("messageDraft", messageDraft); } return view; } @Override public void onResume() { super.onResume(); InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(INPUT_METHOD_SERVICE); if (getActivity().getCurrentFocus() != null) { inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0); } } @Override public void onPause() { if (mChatRoom != null) { mChatRoom.removeListener(mChatRoomCreationListener); } super.onPause(); } private void displayChatCreation() { mNextButton.setVisibility(View.VISIBLE); mNextButton.setEnabled(mContactsSelected.size() > 0); mContactsList.setVisibility(View.VISIBLE); mSearchLayout.setVisibility(View.VISIBLE); mAllContactsButton.setVisibility(View.VISIBLE); mLinphoneContactsButton.setVisibility(View.VISIBLE); if (mOnlyDisplayLinphoneContacts) { mAllContactsSelected.setVisibility(View.INVISIBLE); mLinphoneContactsSelected.setVisibility(View.VISIBLE); } else { mAllContactsSelected.setVisibility(View.VISIBLE); mLinphoneContactsSelected.setVisibility(View.INVISIBLE); } mAllContactsButton.setEnabled(mOnlyDisplayLinphoneContacts); mLinphoneContactsButton.setEnabled(!mAllContactsButton.isEnabled()); mContactsSelectedLayout.removeAllViews(); if (mContactsSelected.size() > 0) { mSearchAdapter.setContactsSelectedList(mContactsSelected); for (ContactAddress ca : mContactsSelected) { addSelectedContactAddress(ca); } } } private void updateList() { mSearchAdapter.searchContacts(mSearchField.getText().toString(), mContactsList); mSearchAdapter.notifyDataSetChanged(); } private void updateListSelected() { if (mContactsSelected.size() > 0) { mContactsSelectLayout.invalidate(); mNextButton.setEnabled(true); } else { mNextButton.setEnabled(false); } } private int getIndexOfCa(ContactAddress ca, List caList) { for (int i = 0 ; i < caList.size() ; i++) { if (ca.getAddress() != null && ca.getAddress().getUsername() != null) { if (caList.get(i).getAddressAsDisplayableString().compareTo(ca.getAddressAsDisplayableString()) == 0) return i; } else if (ca.getPhoneNumber() != null && caList.get(i).getPhoneNumber() !=null) { if (ca.getPhoneNumber().compareTo(caList.get(i).getPhoneNumber()) == 0) return i; } } return -1; } private void resetAndResearch() { ContactsManager.getInstance().getMagicSearch().resetSearchCache(); mSearchAdapter.searchContacts(mSearchField.getText().toString(), mContactsList); } private void addSelectedContactAddress(ContactAddress ca) { View viewContact = LayoutInflater.from(LinphoneActivity.instance()).inflate(R.layout.contact_selected, null); if (ca.getContact() != null) { String name = (ca.getContact().getFullName() != null && !ca.getContact().getFullName().isEmpty()) ? ca.getContact().getFullName() : (ca.getDisplayName() != null) ? ca.getDisplayName() : (ca.getUsername() != null) ? ca.getUsername() : ""; ((TextView) viewContact.findViewById(R.id.sipUri)).setText(name); } else { ((TextView) viewContact.findViewById(R.id.sipUri)).setText(ca.getAddressAsDisplayableString()); } View removeContact = viewContact.findViewById(R.id.contactChatDelete); removeContact.setTag(ca); removeContact.setOnClickListener(this); viewContact.setOnClickListener(this); ca.setView(viewContact); mContactsSelectedLayout.addView(viewContact); mContactsSelectedLayout.invalidate(); } private void updateContactsClick(ContactAddress ca, List caSelectedList) { ca.setSelect((getIndexOfCa(ca, caSelectedList) == -1)); if (ca.isSelect()) { ContactSelectView csv = new ContactSelectView(LinphoneActivity.instance()); csv.setListener(this); csv.setContactName(ca); mContactsSelected.add(ca); addSelectedContactAddress(ca); } else { mContactsSelected.remove(getIndexOfCa(ca, mContactsSelected)); mContactsSelectedLayout.removeAllViews(); for (ContactAddress contactAddress : mContactsSelected) { if (contactAddress.getView() != null) mContactsSelectedLayout.addView(contactAddress.getView()); } } mSearchAdapter.setContactsSelectedList(mContactsSelected); mContactsSelectedLayout.invalidate(); } private void removeContactFromSelection(ContactAddress ca) { updateContactsClick(ca, mSearchAdapter.getContactsSelectedList()); mSearchAdapter.notifyDataSetInvalidated(); updateListSelected(); } @Override public void onSaveInstanceState(Bundle outState) { if (mContactsSelected != null && mContactsSelected.size() > 0) { ArrayList listUri = new ArrayList(); for (ContactAddress ca : mContactsSelected) { listUri.add(ca.getAddressAsDisplayableString()); } outState.putStringArrayList("mContactsSelected", listUri); } outState.putBoolean("onlySipContact", mOnlyDisplayLinphoneContacts); super.onSaveInstanceState(outState); } @Override public void onClick(View view) { int id = view.getId(); if (id == R.id.all_contacts) { mSearchAdapter.setOnlySipContact(mOnlyDisplayLinphoneContacts = false); mAllContactsSelected.setVisibility(View.VISIBLE); mAllContactsButton.setEnabled(false); mLinphoneContactsButton.setEnabled(true); mLinphoneContactsSelected.setVisibility(View.INVISIBLE); updateList(); resetAndResearch(); } else if (id == R.id.linphone_contacts) { mSearchAdapter.setOnlySipContact(true); mLinphoneContactsSelected.setVisibility(View.VISIBLE); mLinphoneContactsButton.setEnabled(false); mAllContactsButton.setEnabled(mOnlyDisplayLinphoneContacts = true); mAllContactsSelected.setVisibility(View.INVISIBLE); updateList(); resetAndResearch(); } else if (id == R.id.back) { if (LinphoneActivity.instance().isTablet()) { LinphoneActivity.instance().goToChatList(); } else { mContactsSelectedLayout.removeAllViews(); LinphoneActivity.instance().popBackStack(); } } else if (id == R.id.next) { if (mChatRoomAddress == null && mChatRoomSubject == null) { if (mContactsSelected.size() == 1) { mContactsSelectedLayout.removeAllViews(); mWaitLayout.setVisibility(View.VISIBLE); Core lc = LinphoneManager.getLc(); Address participant = mContactsSelected.get(0).getAddress(); ChatRoom chatRoom = lc.findOneToOneChatRoom(lc.getDefaultProxyConfig().getContact(), participant); if (chatRoom == null) { ProxyConfig lpc = lc.getDefaultProxyConfig(); if (lpc != null && lpc.getConferenceFactoryUri() != null && !LinphonePreferences.instance().useBasicChatRoomFor1To1()) { mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), true); mChatRoom.addListener(mChatRoomCreationListener); mChatRoom.addParticipant(participant); } else { chatRoom = lc.getChatRoom(participant); LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); } } else { LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); } } else { mContactsSelectedLayout.removeAllViews(); LinphoneActivity.instance().goToChatGroupInfos(null, mContactsSelected, null, true, false, mShareInfos); } } else { LinphoneActivity.instance().goToChatGroupInfos(mChatRoomAddress, mContactsSelected, mChatRoomSubject, true, true, mShareInfos); } } else if (id == R.id.clearSearchField) { mSearchField.setText(""); mSearchAdapter.searchContacts("", mContactsList); } else if (id == R.id.contactChatDelete) { ContactAddress ca = (ContactAddress) view.getTag(); removeContactFromSelection(ca); } } @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { ContactAddress ca = mSearchAdapter.getContacts().get(i); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); ProxyConfig lpc = lc.getDefaultProxyConfig(); if (lpc == null || lpc.getConferenceFactoryUri() == null) { ChatRoom chatRoom = lc.getChatRoom(ca.getAddress()); LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos); } else { removeContactFromSelection(ca); } } @Override public void onContactsUpdated() { mSearchAdapter.searchContacts(mSearchField.getText().toString(), mContactsList); } }