com.waz.zclient.pages.main.pickuser.PickUserFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.waz.zclient.pages.main.pickuser.PickUserFragment.java

Source

/**
 * Wire
 * Copyright (C) 2016 Wire Swiss GmbH
 *
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */
package com.waz.zclient.pages.main.pickuser;

import android.Manifest;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.waz.api.ContactDetails;
import com.waz.api.ContactMethod;
import com.waz.api.Contacts;
import com.waz.api.IConversation;
import com.waz.api.NetworkMode;
import com.waz.api.User;
import com.waz.api.UserSearchResult;
import com.waz.zclient.BaseActivity;
import com.waz.zclient.OnBackPressedListener;
import com.waz.zclient.R;
import com.waz.zclient.controllers.accentcolor.AccentColorObserver;
import com.waz.zclient.controllers.currentfocus.IFocusController;
import com.waz.zclient.controllers.globallayout.KeyboardVisibilityObserver;
import com.waz.zclient.controllers.navigation.NavigationController;
import com.waz.zclient.controllers.permission.RequestPermissionsObserver;
import com.waz.zclient.controllers.tracking.events.connect.EnteredSearchEvent;
import com.waz.zclient.controllers.tracking.events.connect.OpenedConversationEvent;
import com.waz.zclient.controllers.tracking.events.connect.OpenedGenericInviteMenuEvent;
import com.waz.zclient.controllers.tracking.events.connect.SentConnectRequestEvent;
import com.waz.zclient.controllers.tracking.screens.ApplicationScreen;
import com.waz.zclient.core.api.scala.ModelObserver;
import com.waz.zclient.core.controllers.tracking.attributes.ConversationType;
import com.waz.zclient.core.stores.conversation.ConversationChangeRequester;
import com.waz.zclient.core.stores.conversation.InboxLoadRequester;
import com.waz.zclient.core.stores.conversation.OnInboxLoadedListener;
import com.waz.zclient.core.stores.network.DefaultNetworkAction;
import com.waz.zclient.core.stores.pickuser.PickUserStoreObserver;
import com.waz.zclient.pages.BaseFragment;
import com.waz.zclient.pages.main.participants.dialog.DialogLaunchMode;
import com.waz.zclient.pages.main.participants.views.ChatheadWithTextFooter;
import com.waz.zclient.pages.main.pickuser.controller.IPickUserController;
import com.waz.zclient.pages.main.pickuser.controller.PickUserControllerSearchObserver;
import com.waz.zclient.pages.main.pickuser.controller.PickUserDataState;
import com.waz.zclient.pages.main.pickuser.views.ContactRowView;
import com.waz.zclient.pages.main.pickuser.views.SearchBoxView;
import com.waz.zclient.pages.main.pickuser.views.UserRowView;
import com.waz.zclient.tracking.GlobalTrackingController;
import com.waz.zclient.ui.animation.fragment.FadeAnimation;
import com.waz.zclient.ui.startui.ConversationQuickMenu;
import com.waz.zclient.ui.startui.ConversationQuickMenuCallback;
import com.waz.zclient.ui.text.TypefaceTextView;
import com.waz.zclient.ui.utils.KeyboardUtils;
import com.waz.zclient.ui.views.ZetaButton;
import com.waz.zclient.utils.IntentUtils;
import com.waz.zclient.utils.LayoutSpec;
import com.waz.zclient.utils.PermissionUtils;
import com.waz.zclient.utils.StringUtils;
import com.waz.zclient.utils.TrackingUtils;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.utils.device.DeviceDetector;
import com.waz.zclient.views.DefaultPageTransitionAnimation;
import com.waz.zclient.views.LoadingIndicatorView;
import com.waz.zclient.views.PickableElement;
import hugo.weaving.DebugLog;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class PickUserFragment extends BaseFragment<PickUserFragment.Container> implements View.OnClickListener,
        OnInboxLoadedListener, PickUserStoreObserver, KeyboardVisibilityObserver, AccentColorObserver,
        ConversationQuickMenuCallback, OnBackPressedListener, SearchResultOnItemTouchListener.Callback,
        SearchResultAdapter.Callback, PickUserControllerSearchObserver, RequestPermissionsObserver {
    public static final String TAG = PickUserFragment.class.getName();

    public static final String ARGUMENT_ADD_TO_CONVERSATION = "ARGUMENT_ADD_TO_CONVERSATION";
    public static final String ARGUMENT_GROUP_CONVERSATION = "ARGUMENT_GROUP_CONVERSATION";

    public static final int NUM_SEARCH_RESULTS_LIST = 30;
    public static final int NUM_SEARCH_RESULTS_TOP_USERS = 24;
    public static final int NUM_SEARCH_RESULTS_ADD_TO_CONV = 1000;

    private static final int DEFAULT_SELECTED_INVITE_METHOD = 0;
    private static final int SHOW_KEYBOARD_THRETHOLD = 10;

    private RecyclerView searchResultRecyclerView;
    private SearchResultAdapter searchResultAdapter;

    // Saves user from which a pending connect request is loaded
    private User pendingFromUser;
    private Toolbar toolbar;
    private TextView toolbarHeader;
    private View divider;
    private TypefaceTextView errorMessageViewHeader;
    private LinearLayout errorMessageViewSendInvite;
    private TypefaceTextView errorMessageViewBody;
    private LinearLayout errorMessageViewContainer;
    private ConversationQuickMenu conversationQuickMenu;
    private ZetaButton userSelectionConfirmationButton;
    private View userSelectionConfirmationContainer;
    private View genericInviteContainer;
    private ZetaButton genericInviteButton;
    private SearchBoxView searchBoxView;
    private boolean isKeyboardVisible;
    private boolean searchBoxIsEmpty = true;
    private long showLoadingBarDelay;
    private boolean lastInputIsKeyboardDoneAction;
    private AlertDialog dialog;
    private static final boolean SHOW_INVITE = true;

    final public SearchBoxView.Callback searchBoxViewCallback = new SearchBoxView.Callback() {

        @Override
        public void onRemovedTokenSpan(PickableElement element) {
            User user = getStoreFactory().getPickUserStore().getUser(element.id());
            getControllerFactory().getPickUserController().removeUser(user);
            if (isAddingToConversation()) {
                setConversationQuickMenuVisible(false);
            }
        }

        @Override
        public void onKeyboardDoneAction() {
            getControllerFactory().getPickUserController().notifyKeyboardDoneAction();
        }

        @Override
        public void onFocusChange(boolean hasFocus) {
            setFocusByCurrentPickerDestination();
        }

        @Override
        public void onClearButton() {
            closeStartUI();
        }

        @Override
        public void afterTextChanged(String s) {
            if (getControllerFactory().isTornDown()) {
                return;
            }
            getControllerFactory().getPickUserController().setSearchFilter(searchBoxView.getSearchFilter());
        }
    };

    private final ModelObserver<UserSearchResult> usersSearchModelObserver = new ModelObserver<UserSearchResult>() {
        @Override
        public void updated(UserSearchResult model) {
            if (getContainer() != null) {
                getContainer().getLoadingViewIndicator().hide();
            }
            if (model.getAll().length == 0) {
                PickUserDataState dataState = getDataState(
                        getControllerFactory().getPickUserController().hasSelectedUsers());
                if (dataState == PickUserDataState.SHOW_ALL_USERS_TO_ADD_TO_CONVERSATION) {
                    handleEmptySearchResult(
                            getString(R.string.people_picker__error_message__no_users_to_add_to_conversation), "",
                            false);
                } else {
                    handleEmptySearchResult(getString(R.string.people_picker__error_message__no_results), "",
                            false);
                }
            } else {
                hideErrorMessage();
                searchResultAdapter.setSearchResult(model.getAll(), null, null);
            }
        }
    };

    public static PickUserFragment newInstance(boolean addToConversation) {
        PickUserFragment fragment = new PickUserFragment();
        Bundle args = new Bundle();
        args.putBoolean(ARGUMENT_ADD_TO_CONVERSATION, addToConversation);
        args.putBoolean(ARGUMENT_GROUP_CONVERSATION, false);
        fragment.setArguments(args);
        return fragment;
    }

    public static PickUserFragment newInstance(boolean addToConversation, boolean groupConversation) {
        PickUserFragment fragment = new PickUserFragment();
        Bundle args = new Bundle();
        args.putBoolean(ARGUMENT_ADD_TO_CONVERSATION, addToConversation);
        args.putBoolean(ARGUMENT_GROUP_CONVERSATION, groupConversation);
        fragment.setArguments(args);
        return fragment;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  Lifecycle
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        if (nextAnim == 0 || getContainer() == null || getControllerFactory().isTornDown()) {
            return super.onCreateAnimation(transit, enter, nextAnim);
        }

        if (getControllerFactory().getPickUserController().isHideWithoutAnimations()) {
            return new DefaultPageTransitionAnimation(0,
                    ViewUtils.getOrientationIndependentDisplayHeight(getActivity()), enter, 0, 0, 1f);
        }

        if (enter) {
            // Fade animation in participants dialog on tablet
            if (LayoutSpec.isTablet(getActivity()) && isAddingToConversation()) {
                return new FadeAnimation(getResources()
                        .getInteger(R.integer.open_new_conversation__top_conversation__animation_duration), 0f, 1f);
            }
            return new DefaultPageTransitionAnimation(0,
                    getResources()
                            .getDimensionPixelSize(R.dimen.open_new_conversation__thread_list__max_top_distance),
                    enter, getResources().getInteger(R.integer.framework_animation_duration_long),
                    getResources().getInteger(R.integer.framework_animation_duration_medium), 1f);
        }
        return new DefaultPageTransitionAnimation(0,
                getResources().getDimensionPixelSize(R.dimen.open_new_conversation__thread_list__max_top_distance),
                enter, getResources().getInteger(R.integer.framework_animation_duration_medium), 0, 1f);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup viewContainer, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_pick_user, viewContainer, false);

        toolbarHeader = ViewUtils.getView(rootView, R.id.ttv__pickuser__add_header);
        toolbar = ViewUtils.getView(rootView, R.id.t_pickuser_toolbar);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                closeStartUI();
            }
        });
        divider = ViewUtils.getView(rootView, R.id.v__pickuser__divider);

        searchResultAdapter = new SearchResultAdapter(this);
        searchResultAdapter
                .setTopUsersOnItemTouchListener(new SearchResultOnItemTouchListener(getActivity(), this));

        searchResultRecyclerView = ViewUtils.getView(rootView, R.id.rv__pickuser__header_list_view);
        searchResultRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        searchResultRecyclerView.setAdapter(searchResultAdapter);
        searchResultRecyclerView.addOnItemTouchListener(new SearchResultOnItemTouchListener(getActivity(), this));
        if (isAddingToConversation()) {
            searchResultRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    if (newState == RecyclerView.SCROLL_STATE_DRAGGING
                            && getControllerFactory().getGlobalLayoutController().isKeyboardVisible()) {
                        KeyboardUtils.hideKeyboard(getActivity());
                    }
                }
            });
        }
        searchBoxView = ViewUtils.getView(rootView, R.id.sbv__search_box);
        searchBoxView.applyLightTheme(!getControllerFactory().getThemeController().isDarkTheme());
        searchBoxView.setAccentColor(getControllerFactory().getAccentColorController().getColor());
        searchBoxView.setCallback(searchBoxViewCallback);

        conversationQuickMenu = ViewUtils.getView(rootView, R.id.cqm__pickuser__quick_menu);
        conversationQuickMenu.setCallback(this);
        conversationQuickMenu.setVisibility(View.GONE);

        userSelectionConfirmationContainer = ViewUtils.getView(rootView,
                R.id.fl__pickuser__confirmation_button_container);
        userSelectionConfirmationContainer.setVisibility(View.GONE);
        userSelectionConfirmationButton = ViewUtils.getView(rootView, R.id.zb__pickuser__confirmation_button);

        genericInviteContainer = ViewUtils.getView(rootView, R.id.fl__pickuser__generic_invite__container);
        genericInviteButton = ViewUtils.getView(rootView, R.id.zb__pickuser__generic_invite);
        genericInviteButton.setIsFilled(false);

        // Error message
        errorMessageViewContainer = ViewUtils.getView(rootView, R.id.fl_pickuser__error_message_container);
        errorMessageViewContainer.setVisibility(View.GONE);

        errorMessageViewHeader = ViewUtils.getView(rootView, R.id.ttv_pickuser__error_header);
        errorMessageViewBody = ViewUtils.getView(rootView, R.id.ttv_pickuser__error_body);
        errorMessageViewSendInvite = ViewUtils.getView(rootView, R.id.ll_pickuser__error_invite);

        showLoadingBarDelay = getResources().getInteger(R.integer.people_picker__loading_bar__show_delay);

        if (isAddingToConversation()) {
            genericInviteContainer.setVisibility(View.GONE);
            searchBoxView.setHintText(getString(R.string.pick_user_search__add_to_conversation));
            searchBoxView.showClearButton(false);
            divider.setVisibility(View.VISIBLE);
            toolbar.setVisibility(View.VISIBLE);
            toolbarHeader.setText(getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION)
                    ? getString(R.string.people_picker__toolbar_header__group)
                    : getString(R.string.people_picker__toolbar_header__one_to_one));
            userSelectionConfirmationButton.setText(getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION)
                    ? getString(R.string.people_picker__confirm_button_title__add_to_conversation)
                    : getString(R.string.people_picker__confirm_button_title__create_conversation));
            ViewUtils.setHeight(searchBoxView,
                    getResources().getDimensionPixelSize(R.dimen.searchbox__height__with_toolbar));
        } else {
            // Use constant style for left side start ui
            int textColor;
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                //noinspection deprecation
                textColor = getResources().getColor(R.color.text__primary_dark);
            } else {
                textColor = getResources().getColor(R.color.text__primary_dark, getContext().getTheme());
            }
            errorMessageViewHeader.setTextColor(textColor);
            errorMessageViewBody.setTextColor(textColor);
            TextView errorMessageIcon = ViewUtils.getView(rootView, R.id.gtv_pickuser__error_icon);
            errorMessageIcon.setTextColor(textColor);
            TextView errorMessageSublabel = ViewUtils.getView(rootView, R.id.ttv_pickuser__error_sublabel);
            errorMessageSublabel.setTextColor(textColor);
            searchResultAdapter.setDarkTheme(true);
            searchBoxView.forceDarkTheme();
            searchBoxView.setHintText(getString(R.string.pick_user_search_focus));
            searchBoxView.showClearButton(true);
            toolbar.setVisibility(View.GONE);
            divider.setVisibility(View.GONE);
        }

        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();

        getStoreFactory().getPickUserStore().addPickUserStoreObserver(this);
        getControllerFactory().getGlobalLayoutController().addKeyboardVisibilityObserver(this);
        getControllerFactory().getAccentColorController().addAccentColorObserver(this);
        getControllerFactory().getPickUserController().addPickUserSearchControllerObserver(this);
        getControllerFactory().getRequestPermissionsController().addObserver(this);
        if (isAddingToConversation() && !getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION)) {
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    if (getControllerFactory() == null || getControllerFactory().isTornDown()) {
                        return;
                    }
                    for (User user : getControllerFactory().getPickUserController().getSelectedUsers()) {
                        searchBoxView.addUser(user);
                    }
                }
            });
        } else {
            getControllerFactory().getPickUserController().setSearchFilter("");
        }

        loadStartUi();
        usersSearchModelObserver.resumeListening();
        usersSearchModelObserver.forceUpdate();

        boolean hasShareContactsEnabled = getControllerFactory().getUserPreferencesController()
                .hasShareContactsEnabled();
        boolean hasContactsReadPermission = PermissionUtils.hasSelfPermissions(getContext(),
                Manifest.permission.READ_CONTACTS);
        if (hasShareContactsEnabled && !hasContactsReadPermission) {
            ActivityCompat.requestPermissions(getActivity(), new String[] { Manifest.permission.READ_CONTACTS },
                    PermissionUtils.REQUEST_READ_CONTACTS);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        genericInviteButton.setOnClickListener(this);
        userSelectionConfirmationButton.setOnClickListener(this);
        errorMessageViewSendInvite.setOnClickListener(this);
        if (!isAddingToConversation()) {
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (getStoreFactory() == null || getStoreFactory().isTornDown()) {
                        return;
                    }
                    final int numberOfActiveConversations = getStoreFactory().getConversationStore()
                            .getNumberOfActiveConversations();
                    if (searchBoxView == null || numberOfActiveConversations <= SHOW_KEYBOARD_THRETHOLD) {
                        return;
                    }
                    searchBoxView.setFocus();
                    KeyboardUtils.showKeyboard(getActivity());
                }
            }, getResources().getInteger(R.integer.people_picker__keyboard__show_delay));
        }
    }

    @Override
    public void onPause() {
        genericInviteButton.setOnClickListener(null);
        userSelectionConfirmationButton.setOnClickListener(null);
        errorMessageViewSendInvite.setOnClickListener(null);
        super.onPause();

    }

    @Override
    public void onStop() {
        getContainer().getLoadingViewIndicator().hide();
        getStoreFactory().getPickUserStore().removePickUserStoreObserver(this);
        getControllerFactory().getGlobalLayoutController().removeKeyboardVisibilityObserver(this);
        getControllerFactory().getAccentColorController().removeAccentColorObserver(this);
        getControllerFactory().getPickUserController().removePickUserSearchControllerObserver(this);
        getControllerFactory().getRequestPermissionsController().removeObserver(this);
        usersSearchModelObserver.pauseListening();
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        errorMessageViewHeader = null;
        errorMessageViewSendInvite = null;
        errorMessageViewBody = null;
        errorMessageViewContainer = null;
        searchResultAdapter.reset();
        searchResultRecyclerView = null;
        conversationQuickMenu = null;
        userSelectionConfirmationContainer = null;
        userSelectionConfirmationButton = null;
        genericInviteButton = null;
        genericInviteContainer = null;
        searchBoxView = null;
        toolbar = null;
        toolbarHeader = null;
        super.onDestroyView();
    }

    @Override
    public boolean onBackPressed() {
        if (isKeyboardVisible) {
            KeyboardUtils.hideKeyboard(getActivity());
        } else if (getControllerFactory().getPickUserController().isShowingUserProfile()) {
            getControllerFactory().getPickUserController().hideUserProfile();
            return true;
        }
        return isKeyboardVisible;
    }

    @Override
    public void onConnectRequestInboxConversationsLoaded(List<IConversation> conversations,
            InboxLoadRequester inboxLoadRequester) {
        for (IConversation conversation : conversations) {
            if (conversation.getId().equals(pendingFromUser.getConversation().getId())) {
                getContainer().showIncomingPendingConnectRequest(conversation);
                return;
            }
        }
    }

    @Override
    public void onTopUsersUpdated(User[] users) {
        if (isAddingToConversation()) {
            return;
        }
        getContainer().getLoadingViewIndicator().hide();
        PickUserDataState dataState = getDataState(
                getControllerFactory().getPickUserController().hasSelectedUsers());
        switch (dataState) {
        case SHOW_ALL_USERS_TO_ADD_TO_CONVERSATION:
            if (users == null || users.length == 0) {
                handleEmptySearchResult(
                        getString(R.string.people_picker__error_message__no_users_to_add_to_conversation), "",
                        false);
            } else {
                hideErrorMessage();
                searchResultAdapter.setSearchResult(users, null, null);
            }
            break;
        case SHOW_TOP_USERS_AS_LIST:
            if (users == null || users.length == 0) {
                if (TextUtils.isEmpty(getControllerFactory().getPickUserController().getSearchFilter())) {
                    UserSearchResult usersSearchResult = getStoreFactory().getZMessagingApiStore().getApi().search()
                            .getConnectionsByName("", NUM_SEARCH_RESULTS_ADD_TO_CONV, new String[0]);
                    usersSearchModelObserver.setAndUpdate(usersSearchResult);
                } else {
                    handleEmptySearchResult(getString(R.string.people_picker__error_message__no_results), "",
                            false);
                }
            } else {
                hideErrorMessage();
                searchResultAdapter.setSearchResult(users, null, null);
            }
            break;
        case SHOW_TOP_USERS_AND_RECOMMENDED:
            searchResultAdapter.setTopUsers(users);
            getStoreFactory().getPickUserStore().loadContacts();
            break;
        }
    }

    @Override
    public void onSearchResultsUpdated(User[] connectedUsers, User[] otherUsers, IConversation[] conversations) {
        getContainer().getLoadingViewIndicator().hide();

        String errorHeader = getString(R.string.people_picker__error_message__no_results);
        String errorBody;
        if (isAddingToConversation()) {
            errorBody = getString(
                    R.string.people_picker__error_message__no_results__shared_contacts__add_to_conversation);
        } else {
            errorBody = getControllerFactory().getPickUserController().searchInputIsInvalidEmail()
                    ? getString(
                            R.string.people_picker__error_message__no_results__invalid_email__no_shared_contacts)
                    : getString(R.string.people_picker__error_message__no_results__no_shared_contacts);
        }

        switch (getDataState(getControllerFactory().getPickUserController().hasSelectedUsers())) {
        case SHOW_SEARCH_RESULTS_TO_ADD_TO_CONVERSATION:
            if (connectedUsers.length == 0) {
                handleEmptySearchResult(errorHeader, errorBody, !lastInputIsKeyboardDoneAction);
            } else {
                hideErrorMessage();
                searchResultAdapter.setSearchResult(connectedUsers, null, null);
            }
            break;
        case SHOW_SEARCH_RESULTS:
            if (getControllerFactory().getPickUserController().hasSelectedUsers()) {
                // Hide group conversations if there are selected users
                if (connectedUsers.length == 0) {
                    handleEmptySearchResult(errorHeader, errorBody, !lastInputIsKeyboardDoneAction);
                } else {
                    hideErrorMessage();
                    searchResultAdapter.setSearchResult(connectedUsers, null, null);
                }
            } else {
                if (connectedUsers.length == 0 && otherUsers.length == 0 && conversations.length == 0
                        && !searchResultAdapter.hasContacts()) {
                    handleEmptySearchResult(errorHeader, errorBody, !lastInputIsKeyboardDoneAction);
                } else {
                    hideErrorMessage();
                    searchResultAdapter.setSearchResult(connectedUsers, otherUsers, conversations);
                }
            }
            break;
        }
    }

    @Override
    public void onContactsUpdated(Contacts contacts) {
        if (contacts == null || contacts.size() == 0) {
            return;
        }
        hideErrorMessage();
        searchResultAdapter.setContacts(contacts);
    }

    @Override
    public void onSearchContactsUpdated(Contacts contacts) {
        if (contacts == null) {
            return;
        }
        searchResultAdapter.setContacts(contacts);
    }

    @Override
    public void onKeyboardVisibilityChanged(boolean keyboardIsVisible, int keyboardHeight, View currentFocus) {
        int color;
        isKeyboardVisible = keyboardIsVisible;
        if (keyboardIsVisible || !searchBoxIsEmpty) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
                //noinspection deprecation
                color = getResources().getColor(R.color.people_picker__loading__color);
            } else {
                color = getResources().getColor(R.color.people_picker__loading__color, getContext().getTheme());
            }
        } else {
            color = getControllerFactory().getAccentColorController().getColor();
        }
        getContainer().getLoadingViewIndicator().setColor(color);

        if (isAddingToConversation()) {
            return;
        }

        int inviteVisibility = keyboardIsVisible
                || getControllerFactory().getPickUserController().hasSelectedUsers() ? View.GONE : View.VISIBLE;
        genericInviteContainer.setVisibility(inviteVisibility);
    }

    @Override
    public void onAccentColorHasChanged(Object sender, int color) {
        conversationQuickMenu.setAccentColor(color);
        userSelectionConfirmationButton.setAccentColor(color);
        searchResultAdapter.setAccentColor(color);
        genericInviteButton.setAccentColor(color, true);
        searchBoxView.setAccentColor(color);
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    //
    // ConversationQuickMenuCallback
    //
    //////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public void onConversationButtonClicked() {
        KeyboardUtils.hideKeyboard(getActivity());
        List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
        getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION);
    }

    @Override
    public void onVideoCallButtonClicked() {
        KeyboardUtils.hideKeyboard(getActivity());
        List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
        if (users.size() > 1) {
            throw new IllegalStateException(
                    "A video call cannot be started with more than one user. The button should not be visible "
                            + "if multiple users are selected.");
        }
        getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION_FOR_VIDEO_CALL);
    }

    @Override
    public void onCallButtonClicked() {
        KeyboardUtils.hideKeyboard(getActivity());
        List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
        getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION_FOR_CALL);
        // TODO: Uncomment when call issue is resolved with https://wearezeta.atlassian.net/browse/CM-675
        //getStoreFactory().getGroupCallingStore().startCall();
    }

    @Override
    public void onCameraButtonClicked() {
        KeyboardUtils.hideKeyboard(getActivity());
        List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
        getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION_FOR_CAMERA);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    //  PickUserControllerSearchObserver - Search actions
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public void onSearchBoxIsEmpty() {
        searchBoxIsEmpty = true;
        lastInputIsKeyboardDoneAction = false;
        setConversationQuickMenuVisible(false);
        loadStartUi();
    }

    @Override
    public void onSearchBoxHasNewSearchFilter(String filter) {
        searchBoxIsEmpty = false;
        lastInputIsKeyboardDoneAction = false;
        loadStartUi();
    }

    @Override
    public void onKeyboardDoneAction() {
        lastInputIsKeyboardDoneAction = true;

        List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
        int minUsers = 1;
        if (isAddingToConversation() && !getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION)) {
            minUsers = 2;
        }
        if (users.size() >= minUsers) {
            KeyboardUtils.hideKeyboard(getActivity());
            getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION);
        }

        if (searchResultRecyclerView != null && searchResultRecyclerView.getVisibility() != View.VISIBLE
                && errorMessageViewContainer.getVisibility() != View.VISIBLE) {
            showErrorMessage();
        }
    }

    @Override
    public void onSelectedUserAdded(List<User> selectedUsers, User addedUser) {
        changeUserSelectedState(addedUser, true);
        updateConversationButtonLabel();
        conversationQuickMenu.showVideoCallButton(shouldVideoCallButtonBeDisplayed());
        searchBoxView.addUser(addedUser);
    }

    private boolean shouldVideoCallButtonBeDisplayed() {
        return getControllerFactory().getPickUserController().getSelectedUsers().size() == 1
                && DeviceDetector.isVideoCallingEnabled();
    }

    @Override
    public void onSelectedUserRemoved(List<User> selectedUsers, User removedUser) {
        changeUserSelectedState(removedUser, false);
        updateConversationButtonLabel();
        conversationQuickMenu.showVideoCallButton(shouldVideoCallButtonBeDisplayed());
        searchBoxView.removeUser(removedUser);
    }

    private void changeUserSelectedState(User user, boolean selected) {

        changeUserSelectedState(searchResultRecyclerView, user, selected);

        if (!searchResultAdapter.hasTopUsers()) {
            return;
        }
        for (int i = 0; i < searchResultRecyclerView.getChildCount(); i++) {
            View rowView = searchResultRecyclerView.getChildAt(i);
            if (rowView instanceof RecyclerView) {
                changeUserSelectedState(((RecyclerView) rowView), user, selected);
            }
        }
    }

    private void changeUserSelectedState(RecyclerView rv, User user, boolean selected) {
        for (int i = 0; i < rv.getChildCount(); i++) {
            View rowView = rv.getChildAt(i);
            if (rowView instanceof UserRowView) {
                UserRowView userRowView = (UserRowView) rowView;
                if (userRowView.getUser() != null && userRowView.getUser().equals(user)) {
                    userRowView.setSelected(selected);
                }
            }
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    //
    //  SearchResultOnItemTouchListener.Callback
    //
    //////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public void onUserClicked(User user, int position, View anchorView) {
        if (user == null || user.isMe() || getControllerFactory() == null || getControllerFactory().isTornDown()) {
            return;
        }

        TrackingUtils.onUserSelectedInStartUI(
                ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class), user,
                anchorView instanceof ChatheadWithTextFooter, isAddingToConversation(), position,
                searchResultAdapter);

        // Selecting user from search results toggles user token and confirmation button
        if (user.getConnectionStatus() == User.ConnectionStatus.ACCEPTED) {
            if (anchorView.isSelected()) {
                getControllerFactory().getPickUserController().addUser(user);
            } else {
                getControllerFactory().getPickUserController().removeUser(user);
            }
            setConversationQuickMenuVisible(getControllerFactory().getPickUserController().hasSelectedUsers());
            return;
        }

        if (anchorView instanceof ContactRowView
                && user.getConnectionStatus() == User.ConnectionStatus.UNCONNECTED) {
            return;
        }

        showUser(user, anchorView);

    }

    @Override
    public void onUserDoubleClicked(User user, int position, View anchorView) {
        if (!(anchorView instanceof ChatheadWithTextFooter)) {
            return;
        }

        if (user == null || user.isMe() || user.getConnectionStatus() != User.ConnectionStatus.ACCEPTED
                || getControllerFactory().getPickUserController().hasSelectedUsers()) {
            return;
        }

        ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                .tagEvent(new OpenedConversationEvent(ConversationType.ONE_TO_ONE_CONVERSATION.name(),
                        OpenedConversationEvent.Context.TOPUSER_DOUBLETAP, (position + 1)));
        getStoreFactory().getConversationStore().setCurrentConversation(user.getConversation(),
                ConversationChangeRequester.START_CONVERSATION);
    }

    @Override
    public void onConversationClicked(IConversation conversation, int position) {
        KeyboardUtils.hideKeyboard(getActivity());
        ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                .tagEvent(new OpenedConversationEvent(ConversationType.GROUP_CONVERSATION.name(),
                        OpenedConversationEvent.Context.SEARCH,
                        searchResultAdapter.getConversationInternalPosition(position)));
        getStoreFactory().getConversationStore().setCurrentConversation(conversation,
                ConversationChangeRequester.START_CONVERSATION);
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    //
    //  SearchResultAdapter.Callback
    //
    //////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public Set<User> getSelectedUsers() {
        if (getControllerFactory() == null || getControllerFactory().isTornDown()) {
            return null;
        }
        return new HashSet<>(getControllerFactory().getPickUserController().getSelectedUsers());
    }

    @Override
    public void onContactListUserClicked(User user) {
        if (getStoreFactory() == null || getStoreFactory().isTornDown() || user == null) {
            return;
        }

        // ACCEPTED user connection status handled by onUserClicked callback
        switch (user.getConnectionStatus()) {
        case UNCONNECTED:
            User me = getStoreFactory().getProfileStore().getSelfUser();
            String myName = me != null ? me.getName() : "";
            String message = getString(R.string.connect__message, user.getName(), myName);
            user.connect(message);
            ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                    .tagEvent(new SentConnectRequestEvent(SentConnectRequestEvent.EventContext.INVITE_CONTACT_LIST,
                            user.getCommonConnectionsCount()));
            break;
        }
    }

    @Override
    public void onContactListContactClicked(final ContactDetails contactDetails) {
        getStoreFactory().getNetworkStore().doIfHasInternetOrNotifyUser(new DefaultNetworkAction() {
            @Override
            public void execute(NetworkMode networkMode) {
                final int contactMethodsCount = contactDetails.getContactMethods().size();
                final ContactMethod[] contactMethods = contactDetails.getContactMethods()
                        .toArray(new ContactMethod[contactMethodsCount]);

                if (contactMethodsCount == 1 && contactMethods[0].getKind() == ContactMethod.Kind.SMS) {
                    // Launch SMS app directly if contact only has phone numner
                    final String number = contactMethods[0].getStringRepresentation();
                    sendSMSInvite(number);
                    ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                            .tagEvent(new OpenedGenericInviteMenuEvent(
                                    OpenedGenericInviteMenuEvent.EventContext.ADDRESSBOOK));
                    return;
                }

                final CharSequence[] itemNames = new CharSequence[contactMethodsCount];
                for (int i = 0; i < contactMethodsCount; i++) {
                    ContactMethod contactMethod = contactMethods[i];
                    itemNames[i] = contactMethod.getStringRepresentation();
                }

                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

                builder.setTitle(
                        getResources().getString(R.string.people_picker__contact_list__invite_dialog__title))
                        .setPositiveButton(getResources().getText(R.string.confirmation_menu__confirm_done),
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {
                                        ListView lv = dialog.getListView();
                                        int selected = lv.getCheckedItemPosition();
                                        ContactMethod selectedContactMethod = null;
                                        if (selected >= 0) {
                                            selectedContactMethod = contactMethods[selected];
                                        }
                                        if (selectedContactMethod == null) {
                                            return;
                                        }

                                        if (selectedContactMethod.getKind() == ContactMethod.Kind.SMS) {
                                            final String number = String.valueOf(itemNames[selected]);
                                            sendSMSInvite(number);
                                            ((BaseActivity) getActivity())
                                                    .injectJava(GlobalTrackingController.class)
                                                    .tagEvent(new OpenedGenericInviteMenuEvent(
                                                            OpenedGenericInviteMenuEvent.EventContext.ADDRESSBOOK));
                                        } else {
                                            selectedContactMethod.invite(" ", null);
                                            Toast.makeText(getActivity(),
                                                    getResources().getString(
                                                            R.string.people_picker__invite__sent_feedback),
                                                    Toast.LENGTH_LONG).show();
                                            boolean fromSearch = TextUtils.isEmpty(getControllerFactory()
                                                    .getPickUserController().getSearchFilter());
                                            TrackingUtils.tagSentInviteToContactEvent(
                                                    ((BaseActivity) getActivity())
                                                            .injectJava(GlobalTrackingController.class),
                                                    selectedContactMethod.getKind(),
                                                    contactDetails.hasBeenInvited(), fromSearch);
                                        }
                                    }
                                })
                        .setNegativeButton(getResources().getText(R.string.confirmation_menu__cancel),
                                new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialogInterface, int i) {
                                        dialogInterface.cancel();
                                    }
                                })
                        .setSingleChoiceItems(itemNames, DEFAULT_SELECTED_INVITE_METHOD, null);

                dialog = builder.create();
                dialog.show();

                ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                        .onApplicationScreen(ApplicationScreen.SEND_PERSONAL_INVITE_MENU);
            }
        });
    }

    private void sendSMSInvite(String number) {
        User me = getStoreFactory().getProfileStore().getSelfUser();
        if (me != null) {
            String smsBody;
            String username = me.getUsername();
            if (TextUtils.isEmpty(username)) {
                smsBody = getString(R.string.people_picker__invite__share_text__body, me.getName());
            } else {
                smsBody = getString(R.string.people_picker__invite__share_text__body,
                        StringUtils.formatHandle(username));
            }
            Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("sms", number, ""));
            intent.putExtra("sms_body", smsBody);
            startActivity(intent);
        }
    }

    @Override
    public int getDestination() {
        return IPickUserController.STARTUI;
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    //
    //  List and grid helpers
    //
    //////////////////////////////////////////////////////////////////////////////////////////

    @DebugLog
    public void loadStartUi() {
        if (searchResultAdapter.getItemCount() == 0) {
            getContainer().getLoadingViewIndicator().show(LoadingIndicatorView.SPINNER);
        } else {
            getContainer().getLoadingViewIndicator().show(LoadingIndicatorView.INFINITE_LOADING_BAR,
                    showLoadingBarDelay);
        }

        String filter = getControllerFactory().getPickUserController().getSearchFilter();
        boolean hasSelectedUsers = getControllerFactory().getPickUserController().hasSelectedUsers();
        switch (getDataState(hasSelectedUsers)) {
        case SHOW_ALL_USERS_TO_ADD_TO_CONVERSATION:
            filter = "";
        case SHOW_SEARCH_RESULTS_TO_ADD_TO_CONVERSATION:
            String[] excludedUsers = getStoreFactory().getPickUserStore().getExcludedUsers();
            UserSearchResult usersSearchResult = getStoreFactory().getZMessagingApiStore().getApi().search()
                    .getConnectionsByName(filter, NUM_SEARCH_RESULTS_ADD_TO_CONV, excludedUsers);
            usersSearchModelObserver.setAndUpdate(usersSearchResult);
            break;
        case SHOW_SEARCH_RESULTS:
            getStoreFactory().getPickUserStore().loadSearchByFilter(filter, NUM_SEARCH_RESULTS_LIST, false);
            if (!hasSelectedUsers) {
                getStoreFactory().getPickUserStore().searchContacts(filter);
            }
            ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                    .tagEvent(new EnteredSearchEvent(isAddingToConversation(), filter));
            break;
        case SHOW_TOP_USERS_AS_LIST:
        case SHOW_TOP_USERS_AND_RECOMMENDED:
            boolean excludeConversationParticipants = isAddingToConversation()
                    && getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION);
            getStoreFactory().getPickUserStore().loadTopUserList(NUM_SEARCH_RESULTS_TOP_USERS,
                    excludeConversationParticipants);
            break;
        }
    }

    private void handleEmptySearchResult(String errorHeader, String errorBody, boolean showBlankScreen) {
        setErrorMessage(errorHeader, errorBody);
        if (showBlankScreen) {
            errorMessageViewContainer.setVisibility(View.INVISIBLE);
            searchResultRecyclerView.setClickable(false);
            searchResultRecyclerView.setVisibility(View.GONE);
        } else {
            showErrorMessage();
        }
    }

    private void setErrorMessage(String header, String body) {
        errorMessageViewHeader.setText(header);
        if (body != null) {
            errorMessageViewBody.setText(body);
            errorMessageViewBody.setVisibility(View.VISIBLE);
        } else {
            errorMessageViewBody.setVisibility(View.GONE);
        }

        if (SHOW_INVITE && !isAddingToConversation()) {
            errorMessageViewSendInvite.setVisibility(View.VISIBLE);
        } else {
            errorMessageViewSendInvite.setVisibility(View.GONE);
        }
    }

    private void showErrorMessage() {
        errorMessageViewContainer.setVisibility(View.VISIBLE);
        // Set isClickable as ListView continues to receive click events with GONE visibility
        searchResultRecyclerView.setClickable(false);
        searchResultRecyclerView.setVisibility(View.GONE);
    }

    private void hideErrorMessage() {
        errorMessageViewContainer.setVisibility(View.GONE);
        searchResultRecyclerView.setClickable(true);
        searchResultRecyclerView.setVisibility(View.VISIBLE);

        errorMessageViewHeader.setText("");
    }

    private IPickUserController.Destination getCurrentPickerDestination() {
        return getContainer().getCurrentPickerDestination();
    }

    private void sendGenericInvite(final boolean fromSearch) {
        if (getControllerFactory() == null || getControllerFactory().isTornDown() || getStoreFactory() == null
                || getStoreFactory().isTornDown()) {
            return;
        }
        User self = getStoreFactory().getProfileStore().getSelfUser();
        String name = self != null && self.getDisplayName() != null ? self.getDisplayName() : "";
        String username = self != null && self.getUsername() != null ? self.getUsername() : "";
        Intent sharingIntent = IntentUtils.getInviteIntent(
                getString(R.string.people_picker__invite__share_text__header, name),
                getString(R.string.people_picker__invite__share_text__body, StringUtils.formatHandle(username)));
        startActivity(Intent.createChooser(sharingIntent,
                getString(R.string.people_picker__invite__share_details_dialog)));
        OpenedGenericInviteMenuEvent.EventContext eventContext = fromSearch
                ? OpenedGenericInviteMenuEvent.EventContext.NO_RESULTS
                : OpenedGenericInviteMenuEvent.EventContext.BANNER;
        ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                .tagEvent(new OpenedGenericInviteMenuEvent(eventContext));
        ((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class)
                .onApplicationScreen(ApplicationScreen.SEND_GENERIC_INVITE_MENU);
    }

    private void showUser(User user, View anchorView) {
        switch (user.getConnectionStatus()) {
        case ACCEPTED:
            if (isAddingToConversation()) {
                ArrayList<User> users = new ArrayList<>();
                users.add(user);
                getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION);
            } else {
                // Go to 1:1 conversation
                IConversation conversation = user.getConversation();
                if (conversation != null) {
                    KeyboardUtils.hideKeyboard(getActivity());
                    getStoreFactory().getConversationStore().setCurrentConversation(conversation,
                            ConversationChangeRequester.START_CONVERSATION);
                }
            }
            break;
        case PENDING_FROM_USER:
        case BLOCKED:
        case IGNORED:
        case CANCELLED:
        case UNCONNECTED:
            KeyboardUtils.hideKeyboard(getActivity());
            getControllerFactory().getConversationScreenController()
                    .setPopoverLaunchedMode(DialogLaunchMode.SEARCH);
            getControllerFactory().getPickUserController().showUserProfile(user, anchorView);
            break;
        case PENDING_FROM_OTHER:
            // Show inbox
            KeyboardUtils.hideKeyboard(getActivity());
            // Load inbox requests to retrieve conversation
            pendingFromUser = user;
            getStoreFactory().getConversationStore().loadConnectRequestInboxConversations(this,
                    InboxLoadRequester.INBOX_SHOW_SPECIFIC);
            break;
        }
    }

    private void setConversationQuickMenuVisible(boolean show) {
        if (getView() == null || getControllerFactory() == null || getControllerFactory().isTornDown()) {
            return;
        }
        if (isAddingToConversation()) {
            int numberOfSelectedUsers = getControllerFactory().getPickUserController().getSelectedUsers().size();
            boolean visible = getArguments().getBoolean(ARGUMENT_GROUP_CONVERSATION) ? numberOfSelectedUsers > 0
                    : numberOfSelectedUsers > 1;
            userSelectionConfirmationContainer.setVisibility(visible ? View.VISIBLE : View.GONE);
        } else {
            boolean visible = show || getControllerFactory().getPickUserController().hasSelectedUsers();
            conversationQuickMenu.setVisibility(visible ? View.VISIBLE : View.GONE);
            genericInviteContainer.setVisibility(visible || isKeyboardVisible ? View.GONE : View.VISIBLE);

        }
    }

    private void updateConversationButtonLabel() {
        String label = getControllerFactory().getPickUserController().getSelectedUsers().size() > 1
                ? getString(R.string.conversation_quick_menu__conversation_button__group_label)
                : getString(R.string.conversation_quick_menu__conversation_button__single_label);
        conversationQuickMenu.setConversationButtonText(label);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
        case R.id.zb__pickuser__confirmation_button:
            KeyboardUtils.hideKeyboard(getActivity());
            List<User> users = getControllerFactory().getPickUserController().getSelectedUsers();
            getContainer().onSelectedUsers(users, ConversationChangeRequester.START_CONVERSATION);
            break;
        case R.id.zb__pickuser__generic_invite:
            sendGenericInvite(false);
            break;
        case R.id.ll_pickuser__error_invite:
            sendGenericInvite(true);
            break;
        }
    }

    private void setFocusByCurrentPickerDestination() {
        // Don't trigger setting focus in closed split mode on tablet portrait, search is not visible then
        if (LayoutSpec.isTablet(getActivity()) && ViewUtils.isInPortrait(getActivity()) && getControllerFactory()
                .getNavigationController().getPagerPosition() == NavigationController.SECOND_PAGE) {
            return;
        }

        if (getCurrentPickerDestination() == IPickUserController.Destination.CONVERSATION_LIST
                && (LayoutSpec.isTablet(getActivity()) || getControllerFactory().getNavigationController()
                        .getPagerPosition() == NavigationController.FIRST_PAGE)) {
            getControllerFactory().getFocusController().setFocus(IFocusController.CONVERSATION_LIST_SEARCHBOX);
        } else if (getCurrentPickerDestination() == IPickUserController.Destination.PARTICIPANTS) {
            getControllerFactory().getFocusController().setFocus(IFocusController.PARTICIPANTS_SEARCHBOX);
        }
    }

    private PickUserDataState getDataState(boolean hasSelectedUsers) {
        PickUserDataState dataState = PickUserDataState.SHOW_TOP_USERS_AND_RECOMMENDED;

        if (!TextUtils.isEmpty(getControllerFactory().getPickUserController().getSearchFilter())) {
            if (isAddingToConversation()) {
                dataState = PickUserDataState.SHOW_SEARCH_RESULTS_TO_ADD_TO_CONVERSATION;
            } else {
                dataState = PickUserDataState.SHOW_SEARCH_RESULTS;
            }
        } else if (isAddingToConversation()) {
            dataState = PickUserDataState.SHOW_ALL_USERS_TO_ADD_TO_CONVERSATION;
        } else if (hasSelectedUsers) {
            dataState = PickUserDataState.SHOW_TOP_USERS_AS_LIST;
        }

        return dataState;
    }

    private boolean isAddingToConversation() {
        return getArguments().getBoolean(ARGUMENT_ADD_TO_CONVERSATION);
    }

    private void closeStartUI() {
        KeyboardUtils.hideKeyboard(getActivity());
        getControllerFactory().getPickUserController().setSearchFilter("");
        getControllerFactory().getPickUserController().hidePickUser(getCurrentPickerDestination(), true);
    }

    public interface Container {

        void showIncomingPendingConnectRequest(IConversation conversation);

        void onSelectedUsers(List<User> users, ConversationChangeRequester requester);

        LoadingIndicatorView getLoadingViewIndicator();

        IPickUserController.Destination getCurrentPickerDestination();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, int[] grantResults) {
        if (requestCode == PermissionUtils.REQUEST_READ_CONTACTS && grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

            //Changing the value of the shareContacts seems to be the
            //only way to trigger a refresh on the sync engine...
            boolean oldConfig = getControllerFactory().getUserPreferencesController().hasShareContactsEnabled();
            getControllerFactory().getUserPreferencesController().setShareContactsEnabled(!oldConfig);
            getControllerFactory().getUserPreferencesController().setShareContactsEnabled(oldConfig);
        }
    }
}