/* 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.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; 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.HorizontalScrollView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.SearchView; import android.widget.Switch; import android.widget.TextView; import org.linphone.LinphoneManager; import org.linphone.LinphonePreferences; import org.linphone.R; import org.linphone.activities.LinphoneActivity; import org.linphone.contacts.ContactAddress; import org.linphone.contacts.ContactsManager; import org.linphone.contacts.ContactsUpdatedListener; 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.ProxyConfig; import org.linphone.mediastream.Log; import org.linphone.ui.ContactSelectView; import java.util.ArrayList; import java.util.List; import static android.content.Context.INPUT_METHOD_SERVICE; public class ChatCreationFragment extends Fragment implements View.OnClickListener, SearchContactsListAdapter.ViewHolder.ClickListener, ContactsUpdatedListener { private RecyclerView mContactsList; private LinearLayout mContactsSelectedLayout; private HorizontalScrollView mContactsSelectLayout; private ArrayList mContactsSelected; private ImageView mAllContactsButton, mLinphoneContactsButton, mBackButton, mNextButton; private boolean mOnlyDisplayLinphoneContacts; private View mAllContactsSelected, mLinphoneContactsSelected; private RelativeLayout mSearchLayout, mWaitLayout, mLinphoneContactsToggle, mAllContactsToggle; private SearchView mSearchField; private ProgressBar mContactsFetchInProgress; private SearchContactsListAdapter mSearchAdapter; private String mChatRoomSubject, mChatRoomAddress; private ChatRoom mChatRoom; private ChatRoomListenerStub mChatRoomCreationListener; private Bundle mShareInfos; private ImageView mSecurityToggleOff, mSecurityToggleOn; private Switch mSecurityToggle; private boolean mCreateGroupChatRoom; private boolean mChatRoomEncrypted; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreate(savedInstanceState); View view = inflater.inflate(R.layout.chat_create, container, false); mContactsSelected = new ArrayList<>(); mChatRoomSubject = null; mChatRoomAddress = null; mCreateGroupChatRoom = false; if (getArguments() != null) { if (getArguments().getSerializable("selectedContacts") != null) { mContactsSelected = (ArrayList) getArguments().getSerializable("selectedContacts"); } mChatRoomSubject = getArguments().getString("subject"); mChatRoomAddress = getArguments().getString("groupChatRoomAddress"); mCreateGroupChatRoom = getArguments().getBoolean("createGroupChatRoom", false); mChatRoomEncrypted = getArguments().getBoolean("encrypted", false); } 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); mContactsFetchInProgress = view.findViewById(R.id.contactsFetchInProgress); mContactsFetchInProgress.setVisibility(View.VISIBLE); mSearchAdapter = new SearchContactsListAdapter(null, mContactsFetchInProgress, this, mCreateGroupChatRoom == false); mSearchField = view.findViewById(R.id.searchField); mSearchField.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { return true; } @Override public boolean onQueryTextChange(String newText) { mSearchAdapter.searchContacts(newText, mContactsList); return true; } }); mLinphoneContactsToggle = view.findViewById(R.id.layout_linphone_contacts); mAllContactsToggle = view.findViewById(R.id.layout_all_contacts); mSecurityToggle = view.findViewById(R.id.security_toogle); mSecurityToggleOn = view.findViewById(R.id.security_toogle_on); mSecurityToggleOff = view.findViewById(R.id.security_toogle_off); mSecurityToggleOn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mSecurityToggle.setChecked(true); } }); mSecurityToggleOff.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mSecurityToggle.setChecked(false); } }); mSecurityToggle.setChecked(mChatRoomEncrypted); if (mChatRoomSubject != null && mChatRoomAddress != null) { mSecurityToggle.setEnabled(false); mSecurityToggleOn.setOnClickListener(null); mSecurityToggleOff.setOnClickListener(null); } LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext()); mContactsList.setAdapter(mSearchAdapter); DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mContactsList.getContext(), layoutManager.getOrientation()); dividerItemDecoration.setDrawable(getActivity().getApplicationContext().getResources().getDrawable(R.drawable.divider)); mContactsList.addItemDecoration(dividerItemDecoration); mContactsList.setLayoutManager(layoutManager); 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, cr.getLocalAddress().asString()); } 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() { ContactsManager.addContactsListener(this); 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); } ContactsManager.removeContactsListener(this); super.onPause(); } private void displayChatCreation() { mNextButton.setVisibility(View.VISIBLE); mNextButton.setEnabled(mContactsSelected.size() > 0); mContactsList.setVisibility(View.VISIBLE); mSearchLayout.setVisibility(View.VISIBLE); if (getResources().getBoolean(R.bool.hide_non_linphone_contacts)) { mLinphoneContactsButton.setVisibility(View.INVISIBLE); mAllContactsButton.setEnabled(false); mLinphoneContactsButton.setEnabled(false); mOnlyDisplayLinphoneContacts = true; mAllContactsButton.setOnClickListener(null); mLinphoneContactsButton.setOnClickListener(null); mLinphoneContactsSelected.setVisibility(View.INVISIBLE); mLinphoneContactsSelected.setVisibility(View.INVISIBLE); } else { 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()); } if (mCreateGroupChatRoom) { mLinphoneContactsToggle.setVisibility(View.GONE); mAllContactsToggle.setVisibility(View.GONE); mContactsSelectLayout.setVisibility(View.VISIBLE); mNextButton.setVisibility(View.VISIBLE); } else { mLinphoneContactsToggle.setVisibility(View.VISIBLE); mAllContactsToggle.setVisibility(View.VISIBLE); mContactsSelectLayout.setVisibility(View.GONE); mNextButton.setVisibility(View.GONE); } mContactsSelectedLayout.removeAllViews(); if (mContactsSelected.size() > 0) { mSearchAdapter.setContactsSelectedList(mContactsSelected); for (ContactAddress ca : mContactsSelected) { addSelectedContactAddress(ca); } } } private void updateList() { mSearchAdapter.searchContacts(mSearchField.getQuery().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.getQuery().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 addOrRemoveContactFromSelection(ContactAddress ca) { updateContactsClick(ca, mSearchAdapter.getContactsSelectedList()); mSearchAdapter.notifyDataSetChanged(); 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) { mContactsSelectedLayout.removeAllViews(); LinphoneActivity.instance().goToChatGroupInfos(null, mContactsSelected, null, true, false, mShareInfos, mSecurityToggle.isChecked()); } else { LinphoneActivity.instance().goToChatGroupInfos(mChatRoomAddress, mContactsSelected, mChatRoomSubject, true, true, mShareInfos, mSecurityToggle.isChecked()); } } else if (id == R.id.clearSearchField) { mSearchField.setQuery("", false); mSearchAdapter.searchContacts("", mContactsList); } else if (id == R.id.contactChatDelete) { ContactAddress ca = (ContactAddress) view.getTag(); addOrRemoveContactFromSelection(ca); } } @Override public void onItemClicked(int position) { ContactAddress ca = mSearchAdapter.getContacts().get(position); Core lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull(); ProxyConfig lpc = lc.getDefaultProxyConfig(); boolean createEncryptedChatRoom = mSecurityToggle.isChecked(); if (lpc == null || lpc.getConferenceFactoryUri() == null || mCreateGroupChatRoom == false) { if (createEncryptedChatRoom && lpc != null && lpc.getConferenceFactoryUri() != null) { mChatRoom = lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), true); if (mChatRoom != null) { LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, mChatRoom.getLocalAddress().asString()); } else { mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), !createEncryptedChatRoom, createEncryptedChatRoom); mChatRoom.addListener(mChatRoomCreationListener); Address participants[] = new Address[1]; participants[0] = ca.getAddress(); mChatRoom.addParticipants(participants); } } else { if (lpc != null && lpc.getConferenceFactoryUri() != null && !LinphonePreferences.instance().useBasicChatRoomFor1To1()) { mChatRoom = lc.findOneToOneChatRoom(lpc.getIdentityAddress(), ca.getAddress(), false); if (mChatRoom == null) { mWaitLayout.setVisibility(View.VISIBLE); mChatRoom = lc.createClientGroupChatRoom(getString(R.string.dummy_group_chat_subject), true); mChatRoom.addListener(mChatRoomCreationListener); Address participants[] = new Address[1]; participants[0] = ca.getAddress(); mChatRoom.addParticipants(participants); } else { LinphoneActivity.instance().goToChat(mChatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, mChatRoom.getLocalAddress().asString()); } } else { ChatRoom chatRoom = lc.getChatRoom(ca.getAddress()); LinphoneActivity.instance().goToChat(chatRoom.getPeerAddress().asStringUriOnly(), mShareInfos, chatRoom.getLocalAddress().asString()); } } } else { addOrRemoveContactFromSelection(ca); } } @Override public void onContactsUpdated() { updateList(); } }