/**
* 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.conversationlist;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;
import com.waz.api.ConversationsList;
import com.waz.api.CredentialsUpdateListener;
import com.waz.api.IConversation;
import com.waz.api.ImageAsset;
import com.waz.api.Message;
import com.waz.api.OtrClient;
import com.waz.api.SyncState;
import com.waz.api.User;
import com.waz.zclient.BaseActivity;
import com.waz.zclient.LaunchActivity;
import com.waz.zclient.OnBackPressedListener;
import com.waz.zclient.R;
import com.waz.zclient.controllers.accentcolor.AccentColorObserver;
import com.waz.zclient.controllers.confirmation.ConfirmationCallback;
import com.waz.zclient.controllers.confirmation.ConfirmationObserver;
import com.waz.zclient.controllers.confirmation.ConfirmationRequest;
import com.waz.zclient.controllers.confirmation.IConfirmationController;
import com.waz.zclient.controllers.confirmation.TwoButtonConfirmationCallback;
import com.waz.zclient.controllers.currentfocus.IFocusController;
import com.waz.zclient.controllers.navigation.NavigationControllerObserver;
import com.waz.zclient.controllers.navigation.Page;
import com.waz.zclient.controllers.tracking.events.connect.BlockingEvent;
import com.waz.zclient.controllers.tracking.events.connect.OpenedConversationEvent;
import com.waz.zclient.controllers.tracking.events.conversation.ArchivedConversationEvent;
import com.waz.zclient.controllers.tracking.events.conversation.DeleteConversationEvent;
import com.waz.zclient.controllers.tracking.events.conversation.UnarchivedConversationEvent;
import com.waz.zclient.controllers.tracking.events.group.CreatedGroupConversationEvent;
import com.waz.zclient.controllers.tracking.events.group.LeaveGroupConversationEvent;
import com.waz.zclient.controllers.usernames.UsernamesControllerObserver;
import com.waz.zclient.core.controllers.tracking.attributes.ConversationType;
import com.waz.zclient.core.controllers.tracking.events.onboarding.KeptGeneratedUsernameEvent;
import com.waz.zclient.core.controllers.tracking.events.onboarding.OpenedUsernameSettingsEvent;
import com.waz.zclient.core.controllers.tracking.events.onboarding.SeenUsernameTakeOverScreenEvent;
import com.waz.zclient.core.stores.connect.IConnectStore;
import com.waz.zclient.core.stores.conversation.ConversationChangeRequester;
import com.waz.zclient.core.stores.conversation.ConversationStoreObserver;
import com.waz.zclient.core.stores.conversation.InboxLoadRequester;
import com.waz.zclient.core.stores.conversation.OnInboxLoadedListener;
import com.waz.zclient.fragments.ArchiveListFragment;
import com.waz.zclient.fragments.ConversationListFragment;
import com.waz.zclient.fragments.NormalConversationListFragment;
import com.waz.zclient.media.SoundController;
import com.waz.zclient.newreg.fragments.FirstTimeAssignUsernameFragment;
import com.waz.zclient.pages.BaseFragment;
import com.waz.zclient.pages.main.connect.BlockedUserProfileFragment;
import com.waz.zclient.pages.main.connect.ConnectRequestLoadMode;
import com.waz.zclient.pages.main.connect.PendingConnectRequestManagerFragment;
import com.waz.zclient.pages.main.connect.SendConnectRequestFragment;
import com.waz.zclient.pages.main.conversation.controller.ConversationScreenControllerObserver;
import com.waz.zclient.pages.main.conversation.controller.IConversationScreenController;
import com.waz.zclient.pages.main.participants.OptionsMenuControl;
import com.waz.zclient.pages.main.participants.OptionsMenuFragment;
import com.waz.zclient.pages.main.participants.dialog.ParticipantsDialogFragment;
import com.waz.zclient.pages.main.pickuser.PickUserFragment;
import com.waz.zclient.pages.main.pickuser.controller.IPickUserController;
import com.waz.zclient.pages.main.pickuser.controller.PickUserControllerScreenObserver;
import com.waz.zclient.pages.main.profile.ZetaPreferencesActivity;
import com.waz.zclient.pages.main.profile.camera.CameraContext;
import com.waz.zclient.pages.main.profile.camera.CameraFragment;
import com.waz.zclient.tracking.GlobalTrackingController;
import com.waz.zclient.ui.animation.interpolators.penner.Expo;
import com.waz.zclient.ui.animation.interpolators.penner.Quart;
import com.waz.zclient.ui.optionsmenu.OptionsMenu;
import com.waz.zclient.ui.optionsmenu.OptionsMenuItem;
import com.waz.zclient.ui.utils.KeyboardUtils;
import com.waz.zclient.utils.IntentUtils;
import com.waz.zclient.utils.LayoutSpec;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.views.LoadingIndicatorView;
import com.waz.zclient.views.menus.ConfirmationMenu;
import java.util.List;
public class ConversationListManagerFragment extends BaseFragment<ConversationListManagerFragment.Container> implements
PickUserControllerScreenObserver,
ConversationStoreObserver,
OnInboxLoadedListener,
OnBackPressedListener,
ConversationListFragment.Container,
OptionsMenuFragment.Container,
PickUserFragment.Container,
CameraFragment.Container,
SendConnectRequestFragment.Container,
BlockedUserProfileFragment.Container,
ParticipantsDialogFragment.Container,
PendingConnectRequestManagerFragment.Container,
ConversationScreenControllerObserver,
NavigationControllerObserver,
UsernamesControllerObserver,
ConfirmationObserver,
AccentColorObserver,
FirstTimeAssignUsernameFragment.Container {
public static final String TAG = ConversationListManagerFragment.class.getName();
private LoadingIndicatorView startuiLoadingIndicatorView;
private LoadingIndicatorView listLoadingIndicatorView;
private FrameLayout mainContainer;
private OptionsMenuControl optionsMenuControl;
private ConfirmationMenu confirmationMenu;
//////////////////////////////////////////////////////////////////////////////////////////
//
// Lifecycle
//
//////////////////////////////////////////////////////////////////////////////////////////
public static Fragment newInstance() {
Fragment fragment = new ConversationListManagerFragment();
Bundle arguments = new Bundle();
fragment.setArguments(arguments);
return fragment;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_conversation_list_manager, container, false);
mainContainer = ViewUtils.getView(view, R.id.fl__conversation_list_main);
startuiLoadingIndicatorView = ViewUtils.getView(view, R.id.liv__conversations__loading_indicator);
listLoadingIndicatorView = ViewUtils.getView(view, R.id.lbv__conversation_list__loading_indicator);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
startuiLoadingIndicatorView.setColor(getResources().getColor(R.color.people_picker__loading__color));
} else {
startuiLoadingIndicatorView.setColor(getResources().getColor(R.color.people_picker__loading__color, getContext().getTheme()));
}
listLoadingIndicatorView.setColor(getControllerFactory().getAccentColorController().getColor());
confirmationMenu = ViewUtils.getView(view, R.id.cm__confirm_action_light);
confirmationMenu.setVisibility(View.GONE);
confirmationMenu.resetFullScreenPadding();
optionsMenuControl = new OptionsMenuControl();
if (savedInstanceState == null) {
// When re-starting app to open into specific page, child fragments may exist despite savedInstanceState == null
if (getControllerFactory().getPickUserController().isShowingUserProfile()) {
getControllerFactory().getPickUserController().hideUserProfile();
}
if (getControllerFactory().getPickUserController().isShowingPickUser(
IPickUserController.Destination.CONVERSATION_LIST)) {
getControllerFactory().getPickUserController().hidePickUser(IPickUserController.Destination.CONVERSATION_LIST, false);
Fragment pickUserFragment = getChildFragmentManager().findFragmentByTag(PickUserFragment.TAG);
if (pickUserFragment != null) {
getChildFragmentManager().popBackStack(PickUserFragment.TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
getChildFragmentManager().beginTransaction()
.add(R.id.fl__conversation_list_main,
ConversationListFragment.newNormalInstance(),
NormalConversationListFragment.TAG())
.add(R.id.fl__conversation_list__settings_box,
OptionsMenuFragment.newInstance(true),
OptionsMenuFragment.TAG)
.commit();
}
return view;
}
@Override
public void onStart() {
super.onStart();
getControllerFactory().getCameraController().addCameraActionObserver(this);
getControllerFactory().getAccentColorController().addAccentColorObserver(this);
getControllerFactory().getPickUserController().addPickUserScreenControllerObserver(this);
getStoreFactory().getConversationStore().addConversationStoreObserverAndUpdate(this);
getControllerFactory().getConversationScreenController().addConversationControllerObservers(this);
getControllerFactory().getNavigationController().addNavigationControllerObserver(this);
getControllerFactory().getConfirmationController().addConfirmationObserver(this);
String page = getActivity().getIntent().getStringExtra(LaunchActivity.APP_PAGE);
if (page == null) {
return;
}
getActivity().setIntent(IntentUtils.resetAppPage(getActivity().getIntent()));
switch (page) {
case IntentUtils.LOCALYTICS_DEEPLINK_SEARCH:
getControllerFactory().getPickUserController().showPickUser(IPickUserController.Destination.CONVERSATION_LIST, null);
break;
case IntentUtils.LOCALYTICS_DEEPLINK_SETTINGS:
startActivity(ZetaPreferencesActivity.getDefaultIntent(getActivity()));
break;
case IntentUtils.LOCALYTICS_DEEPLINK_PROFILE:
getControllerFactory().getPickUserController().showUserProfile(getStoreFactory().getProfileStore().getSelfUser(),
ViewUtils.getView(getActivity(),
R.id.gtv__list_actions__settings));
break;
}
}
@Override
public void onViewStateRestored(Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
loadPage();
}
@Override
public void onStop() {
getControllerFactory().getCameraController().removeCameraActionObserver(this);
getStoreFactory().getConversationStore().removeConversationStoreObserver(this);
getControllerFactory().getPickUserController().removePickUserScreenControllerObserver(this);
getControllerFactory().getAccentColorController().removeAccentColorObserver(this);
getControllerFactory().getConversationScreenController().removeConversationControllerObservers(this);
getControllerFactory().getNavigationController().removeNavigationControllerObserver(this);
getControllerFactory().getConfirmationController().removeConfirmationObserver(this);
getControllerFactory().getUsernameController().removeUsernamesObserver(this);
super.onStop();
}
@Override
public void onDestroyView() {
mainContainer = null;
startuiLoadingIndicatorView = null;
listLoadingIndicatorView = null;
confirmationMenu = null;
super.onDestroyView();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.fl__left__camera);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConversationStoreObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onConversationListUpdated(@NonNull final ConversationsList conversationsList) {
if (!Page.CONVERSATION_LIST.equals(getControllerFactory().getNavigationController().getCurrentPage())) {
return;
}
if (conversationsList.size() > 0) {
listLoadingIndicatorView.setType(LoadingIndicatorView.INFINITE_LOADING_BAR);
getControllerFactory().getNavigationController().setPagerEnabled(true);
} else {
listLoadingIndicatorView.setType(LoadingIndicatorView.SPINNER);
getControllerFactory().getNavigationController().setPagerEnabled(false);
}
}
@Override
public void onConversationListStateHasChanged(ConversationsList.ConversationsListState state) {
}
@Override
public void onCurrentConversationHasChanged(IConversation fromConversation,
IConversation toConversation,
ConversationChangeRequester conversationChangerSender) {
switch (conversationChangerSender) {
case START_CONVERSATION:
case START_CONVERSATION_FOR_CALL:
case START_CONVERSATION_FOR_VIDEO_CALL:
case START_CONVERSATION_FOR_CAMERA:
case NOTIFICATION:
case SHARING:
stripToConversationList();
break;
case INCOMING_CALL:
stripToConversationList();
animateOnIncomingCall();
break;
}
}
private void stripToConversationList() {
if (LayoutSpec.isTablet(getActivity())) {
return;
}
// Hide possibly open self profile
getControllerFactory().getPickUserController().hideUserProfile();
// Hide possibly open start ui
if (!getControllerFactory().getPickUserController()
.hidePickUser(getCurrentPickerDestination(), false)) {
getControllerFactory().getNavigationController().setLeftPage(Page.CONVERSATION_LIST, TAG);
}
}
@Override
public void onConversationSyncingStateHasChanged(SyncState syncState) {
if (syncState == null) {
syncState = SyncState.FAILED;
}
switch (syncState) {
case SYNCING:
case WAITING:
listLoadingIndicatorView.show();
return;
case COMPLETED:
listLoadingIndicatorView.hide();
getControllerFactory().getLoadTimeLoggerController().loginSuccess();
break;
case FAILED:
default:
listLoadingIndicatorView.hide();
}
}
@Override
public void onMenuConversationHasChanged(IConversation fromConversation) {
}
private void animateOnIncomingCall() {
int duration = getResources().getInteger(R.integer.calling_animation_duration_medium);
int resetDelay = getResources().getInteger(R.integer.calling_animation_duration_long);
final View rootView = getView();
if (rootView != null) {
rootView.animate()
.alpha(0)
.setInterpolator(new Quart.EaseOut())
.setDuration(duration)
.start();
}
// Reset to showing conversation list
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
getControllerFactory().getPickUserController().hidePickUserWithoutAnimations(
getCurrentPickerDestination());
if (rootView != null) {
rootView.setAlpha(1);
}
}
}, resetDelay);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// NavigationControllerObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onPageVisible(Page page) {
if (page != Page.ARCHIVE) {
closeArchive();
}
if (page == Page.CONVERSATION_LIST) {
getControllerFactory().getNavigationController().setPagerEnabled(false);
getControllerFactory().getUsernameController().addUsernamesObserverAndUpdate(this);
} else {
getControllerFactory().getUsernameController().removeUsernamesObserver(this);
}
}
@Override
public void onPageStateHasChanged(Page page) {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// PickUserFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void showIncomingPendingConnectRequest(IConversation conversation) {
getControllerFactory().getPickUserController().hidePickUser(getCurrentPickerDestination(), false);
getStoreFactory().getConversationStore().setCurrentConversation(conversation,
ConversationChangeRequester.INBOX);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// PickUserFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onSelectedUsers(List<User> users, ConversationChangeRequester requester) {
// TODO https://wearezeta.atlassian.net/browse/AN-3730
getControllerFactory().getPickUserController().hidePickUser(getCurrentPickerDestination(), true);
if (users.size() == 1) {
User user = users.get(0);
IConversation conversation = user.getConversation();
if (conversation != null) {
getStoreFactory().getConversationStore().setCurrentConversation(conversation,
requester);
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new OpenedConversationEvent(ConversationType.ONE_TO_ONE_CONVERSATION.name(),
OpenedConversationEvent.Context.OPEN_BUTTON,
-1));
} else {
getStoreFactory().getConversationStore().createGroupConversation(users, requester);
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new CreatedGroupConversationEvent(false,
(users.size() + 1)));
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new OpenedConversationEvent(ConversationType.GROUP_CONVERSATION.name(),
OpenedConversationEvent.Context.OPEN_BUTTON,
-1));
}
}
@Override
public LoadingIndicatorView getLoadingViewIndicator() {
return startuiLoadingIndicatorView;
}
@Override
public IPickUserController.Destination getCurrentPickerDestination() {
return IPickUserController.Destination.CONVERSATION_LIST;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// OnBackPressedListener
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public boolean onBackPressed() {
if (closeMenu()) {
return true;
}
PickUserFragment pickUserFragment = (PickUserFragment) getChildFragmentManager().findFragmentByTag(
PickUserFragment.TAG);
if (pickUserFragment != null &&
pickUserFragment.onBackPressed()) {
return true;
}
ArchiveListFragment archiveListFragment = (ArchiveListFragment) getChildFragmentManager()
.findFragmentByTag(ArchiveListFragment.TAG());
if (archiveListFragment != null &&
archiveListFragment.onBackPressed()) {
return true;
}
if (getControllerFactory().getPickUserController().isShowingPickUser(getCurrentPickerDestination())) {
getControllerFactory().getPickUserController().hidePickUser(getCurrentPickerDestination(), true);
return true;
}
return getChildFragmentManager().findFragmentByTag(FirstTimeAssignUsernameFragment.TAG) != null;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// PickUserControllerScreenObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onShowPickUser(IPickUserController.Destination destination, View anchorView) {
if (!getCurrentPickerDestination().equals(destination)) {
onHidePickUser(getCurrentPickerDestination(), true);
return;
}
Page page = getControllerFactory().getNavigationController().getCurrentLeftPage();
switch (page) {
// TODO: START is set as left page on tablet, fix
case START:
case CONVERSATION_LIST:
Fragment fragment = getChildFragmentManager().findFragmentByTag(PickUserFragment.TAG);
if (fragment == null ||
!(fragment instanceof PickUserFragment)) {
getControllerFactory().getOnboardingController().incrementPeoplePickerShowCount();
PickUserFragment pickUserFragment = PickUserFragment.newInstance(false);
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_from_bottom_pick_user,
R.anim.open_new_conversation__thread_list_out,
R.anim.open_new_conversation__thread_list_in,
R.anim.slide_out_to_bottom_pick_user)
.replace(R.id.fl__conversation_list_main, pickUserFragment, PickUserFragment.TAG)
.addToBackStack(PickUserFragment.TAG)
.commit();
}
break;
case PICK_USER:
break;
}
getControllerFactory().getNavigationController().setLeftPage(Page.PICK_USER, TAG);
}
@Override
public void onHidePickUser(IPickUserController.Destination destination, boolean closeWithoutSelectingPeople) {
if (!destination.equals(getCurrentPickerDestination())) {
return;
}
Page page = getControllerFactory().getNavigationController().getCurrentLeftPage();
switch (page) {
case SEND_CONNECT_REQUEST:
case BLOCK_USER:
case PENDING_CONNECT_REQUEST:
getControllerFactory().getPickUserController().hideUserProfile();
case PICK_USER:
getChildFragmentManager().popBackStackImmediate(PickUserFragment.TAG,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
KeyboardUtils.hideKeyboard(getActivity());
break;
}
getControllerFactory().getNavigationController().setLeftPage(Page.CONVERSATION_LIST, TAG);
getControllerFactory().getFocusController().setFocus(IFocusController.CONVERSATION_CURSOR);
}
private void togglePeoplePicker(boolean show) {
if (show) {
mainContainer.animate()
.alpha(1)
.scaleY(1)
.scaleX(1)
.setInterpolator(new Expo.EaseOut())
.setDuration(getResources().getInteger(R.integer.reopen_profile_source__animation_duration))
.setStartDelay(getResources().getInteger(R.integer.reopen_profile_source__delay))
.start();
} else {
mainContainer.animate()
.alpha(0)
.scaleY(2)
.scaleX(2)
.setInterpolator(new Expo.EaseIn())
.setDuration(getResources().getInteger(R.integer.reopen_profile_source__animation_duration))
.setStartDelay(0)
.start();
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// UserProfileContainer
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void dismissUserProfile() {
getControllerFactory().getPickUserController().hideUserProfile();
}
@Override
public void dismissSingleUserProfile() {
dismissUserProfile();
}
@Override
public void showRemoveConfirmation(User user) {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// SendConnectRequestFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onConnectRequestWasSentToUser() {
getControllerFactory().getPickUserController().hideUserProfile();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// PendingConnectRequestManagerFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onAcceptedConnectRequest(IConversation conversation) {
getStoreFactory().getConversationStore().setCurrentConversation(conversation,
ConversationChangeRequester.START_CONVERSATION);
}
@Override
public void onAcceptedPendingOutgoingConnectRequest(IConversation conversation) {
getStoreFactory().getConversationStore().setCurrentConversation(conversation,
ConversationChangeRequester.CONNECT_REQUEST_ACCEPTED);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// BlockedUserProfileFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onUnblockedUser(IConversation restoredConversationWithUser) {
getControllerFactory().getPickUserController().hideUserProfile();
getStoreFactory().getConversationStore().setCurrentConversation(restoredConversationWithUser,
ConversationChangeRequester.START_CONVERSATION);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// PickUserControllerScreenObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onShowUserProfile(User user, View anchorView) {
if (getControllerFactory().getPickUserController().isShowingUserProfile()) {
return;
}
if (LayoutSpec.isPhone(getActivity())) {
openUserProfileFragmentPhone(user);
}
}
private void openUserProfileFragmentPhone(User user) {
if (user == null) {
return;
}
Fragment fragment;
String tag;
switch (user.getConnectionStatus()) {
case CANCELLED:
case UNCONNECTED:
if (user.isConnected()) {
return;
}
fragment = SendConnectRequestFragment.newInstance(user.getId(), IConnectStore.UserRequester.SEARCH);
tag = SendConnectRequestFragment.TAG;
getControllerFactory().getNavigationController().setLeftPage(Page.SEND_CONNECT_REQUEST, TAG);
break;
case PENDING_FROM_OTHER:
case PENDING_FROM_USER:
case IGNORED:
fragment = PendingConnectRequestManagerFragment.newInstance(user.getId(),
null,
ConnectRequestLoadMode.LOAD_BY_USER_ID,
IConnectStore.UserRequester.SEARCH);
tag = PendingConnectRequestManagerFragment.TAG;
getControllerFactory().getNavigationController().setLeftPage(Page.PENDING_CONNECT_REQUEST, TAG);
break;
case BLOCKED:
fragment = BlockedUserProfileFragment.newInstance(user.getId(), IConnectStore.UserRequester.SEARCH);
tag = BlockedUserProfileFragment.TAG;
getControllerFactory().getNavigationController().setLeftPage(Page.PENDING_CONNECT_REQUEST, TAG);
break;
default:
return;
}
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.fragment_animation__send_connect_request__fade_in,
R.anim.fragment_animation__send_connect_request__zoom_exit,
R.anim.fragment_animation__send_connect_request__zoom_enter,
R.anim.fragment_animation__send_connect_request__fade_out)
.replace(R.id.fl__conversation_list__profile_overlay,
fragment,
tag)
.addToBackStack(tag)
.commit();
togglePeoplePicker(false);
}
@Override
public void onHideUserProfile() {
// Profiles are handled in dialog on tablet
if (LayoutSpec.isTablet(getActivity())) {
return;
}
getControllerFactory().getNavigationController().setLeftPage(Page.PICK_USER, TAG);
getChildFragmentManager().popBackStackImmediate();
togglePeoplePicker(true);
}
/**
* Decides based on state returned from PickUserController whether to show START UI or CONVERSATIONLIST
*/
private void loadPage() {
Page page = getControllerFactory().getNavigationController().getCurrentLeftPage();
switch (page) {
// TODO: START is set as left page on tablet, fix
case START:
case CONVERSATION_LIST:
break;
case PICK_USER:
getControllerFactory().getPickUserController().showPickUser(IPickUserController.Destination.CONVERSATION_LIST, null);
break;
case BLOCK_USER:
case PENDING_CONNECT_REQUEST:
case SEND_CONNECT_REQUEST:
togglePeoplePicker(false);
break;
case COMMON_USER_PROFILE:
togglePeoplePicker(false);
break;
}
}
@Override
public void onOpenCamera(CameraContext cameraContext) {
}
@Override
public void onCloseCamera(CameraContext cameraContext) {
}
@Override
public void onOpenUrl(String url) {
getContainer().onOpenUrl(url);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// CameraFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onBitmapSelected(final ImageAsset imageAsset,
final boolean imageFromCamera,
CameraContext cameraContext) {
}
@Override
public void onCameraNotAvailable() {
}
private void showNoNetworkError() {
ViewUtils.showAlertDialog(getActivity(),
R.string.alert_dialog__no_network__header,
R.string.profile_pic__no_network__message,
R.string.alert_dialog__confirmation,
null, true);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// AccentColorObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onAccentColorHasChanged(Object sender, int color) {
listLoadingIndicatorView.setColor(color);
confirmationMenu.setButtonColor(color);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConfirmationObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onRequestConfirmation(ConfirmationRequest confirmationRequest, @IConfirmationController.ConfirmationMenuRequester int requester) {
if (LayoutSpec.isPhone(getActivity()) ||
requester != IConfirmationController.CONVERSATION_LIST) {
return;
}
confirmationMenu.onRequestConfirmation(confirmationRequest);
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// SlidingListener
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onOptionMenuStateHasChanged(OptionsMenu.State state) {
switch (state) {
case OPEN:
break;
case OPENING:
if (LayoutSpec.isPhone(getActivity())) {
getControllerFactory().getNavigationController().setLeftPage(Page.CONVERSATION_MENU_OVER_CONVERSATION_LIST,
TAG);
}
break;
case CLOSING:
break;
case CLOSED:
if (LayoutSpec.isPhone(getActivity())) {
getControllerFactory().getNavigationController().setLeftPage(Page.CONVERSATION_LIST, TAG);
}
break;
}
}
@Override
public void onOptionsItemClicked(IConversation conversation, User user, OptionsMenuItem item) {
switch (item) {
case ARCHIVE:
getStoreFactory().getConversationStore().archive(conversation, true);
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new ArchivedConversationEvent(conversation.getType().toString()));
break;
case UNARCHIVE:
getStoreFactory().getConversationStore().archive(conversation, false);
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new UnarchivedConversationEvent(conversation.getType().toString()));
break;
case SILENCE:
conversation.setMuted(true);
break;
case UNSILENCE:
conversation.setMuted(false);
break;
case LEAVE:
leaveConversation(conversation);
break;
case DELETE:
deleteConversation(conversation);
break;
case BLOCK:
showBlockConfirmation(user);
break;
case UNBLOCK:
user.unblock();
break;
case CALL:
callConversation(conversation);
break;
case PICTURE:
sendPictureToConversation(conversation);
break;
}
closeMenu();
}
@Override
public OptionsMenuControl getOptionsMenuControl() {
return optionsMenuControl;
}
private boolean closeMenu() {
return optionsMenuControl.close();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConversationScreenControllerObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onShowParticipants(View anchorView, boolean isSingleConversation, boolean isMemberOfConversation, boolean showDeviceTabIfSingle) {
}
@Override
public void onHideParticipants(boolean backOrButtonPressed,
boolean hideByConversationChange,
boolean isSingleConversation) {
}
@Override
public void onShowEditConversationName(boolean show) {
}
@Override
public void setListOffset(int offset) {
}
@Override
public void onHeaderViewMeasured(int participantHeaderHeight) {
}
@Override
public void onScrollParticipantsList(int verticalOffset, boolean scrolledToBottom) {
}
@Override
public void onConversationLoaded() {
}
@Override
public void onShowUser(User user) {
}
@Override
public void onHideUser() {
}
@Override
public void onAddPeopleToConversation() {
}
@Override
public void onShowConversationMenu(@IConversationScreenController.ConversationMenuRequester int requester,
IConversation conversation,
View anchorView) {
if ((requester != IConversationScreenController.CONVERSATION_LIST_SWIPE &&
requester != IConversationScreenController.CONVERSATION_LIST_LONG_PRESS) ||
getControllerFactory() == null ||
getControllerFactory().isTornDown()) {
return;
}
optionsMenuControl.createMenu(conversation,
requester,
getControllerFactory().getThemeController().getOptionsDarkTheme());
optionsMenuControl.open();
}
@Override
public void onShowOtrClient(OtrClient otrClient, User user) {
}
@Override
public void onShowCurrentOtrClient() {
}
@Override
public void onHideOtrClient() {
}
@Override
public void onShowLikesList(Message message) {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConversationListFragment.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
public void leaveConversation(final IConversation conversation) {
closeMenu();
ConfirmationCallback callback = new TwoButtonConfirmationCallback() {
@Override
public void positiveButtonClicked(boolean checkboxIsSelected) {
if (getStoreFactory() == null ||
getControllerFactory() == null ||
getStoreFactory().isTornDown() ||
getControllerFactory().isTornDown()) {
return;
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new LeaveGroupConversationEvent(true,
getStoreFactory().getConversationStore().getCurrentConversation().getUsers().size()));
getStoreFactory().getConversationStore().leave(conversation);
getStoreFactory().getConversationStore().setCurrentConversationToNext(
ConversationChangeRequester.LEAVE_CONVERSATION);
}
@Override
public void negativeButtonClicked() {
if (getControllerFactory() == null ||
getControllerFactory().isTornDown()) {
return;
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new LeaveGroupConversationEvent(false,
getStoreFactory().getConversationStore().getCurrentConversation().getUsers().size()));
}
@Override
public void onHideAnimationEnd(boolean confirmed, boolean canceled, boolean checkboxIsSelected) {
}
};
String header = getString(R.string.confirmation_menu__meta_remove);
String text = getString(R.string.confirmation_menu__meta_remove_text);
String confirm = getString(R.string.confirmation_menu__confirm_leave);
String cancel = getString(R.string.confirmation_menu__cancel);
ConfirmationRequest request = new ConfirmationRequest.Builder()
.withHeader(header)
.withMessage(text)
.withPositiveButton(confirm)
.withNegativeButton(cancel)
.withConfirmationCallback(callback)
.withWireTheme(getControllerFactory().getThemeController().getOptionsDarkTheme())
.build();
getControllerFactory().getConfirmationController().requestConfirmation(request,
IConfirmationController.CONVERSATION_LIST);
SoundController ctrl = inject(SoundController.class);
if (ctrl != null) {
ctrl.playAlert();
}
}
public void callConversation(final IConversation conversation) {
getStoreFactory().getConversationStore().setCurrentConversation(conversation, ConversationChangeRequester.CONVERSATION_LIST);
getControllerFactory().getCallingController().startCall(false);
}
public void sendPictureToConversation(final IConversation conversation) {
getStoreFactory().getConversationStore().setCurrentConversation(conversation, ConversationChangeRequester.CONVERSATION_LIST);
getControllerFactory().getCameraController().openCamera(CameraContext.MESSAGE);
}
public void deleteConversation(final IConversation conversation) {
closeMenu();
ConfirmationCallback callback = new TwoButtonConfirmationCallback() {
@Override
public void positiveButtonClicked(boolean checkboxIsSelected) {
}
@Override
public void negativeButtonClicked() {
}
@Override
public void onHideAnimationEnd(boolean confirmed, boolean canceled, boolean checkboxIsSelected) {
if (getStoreFactory() == null ||
getStoreFactory().isTornDown() ||
getControllerFactory() == null ||
getControllerFactory().isTornDown()) {
return;
}
if (!confirmed) {
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new DeleteConversationEvent(ConversationType.getValue(conversation),
DeleteConversationEvent.Context.LIST,
DeleteConversationEvent.Response.CANCEL));
return;
}
boolean deleteCurrentConversation = getStoreFactory().getConversationStore().getCurrentConversation() != null &&
conversation.getId().equals(getStoreFactory().getConversationStore().getCurrentConversation().getId());
getStoreFactory().getConversationStore().deleteConversation(conversation, checkboxIsSelected);
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new DeleteConversationEvent(ConversationType.getValue(
conversation),
DeleteConversationEvent.Context.LIST,
DeleteConversationEvent.Response.DELETE));
if (deleteCurrentConversation) {
getStoreFactory().getConversationStore().setCurrentConversationToNext(ConversationChangeRequester.DELETE_CONVERSATION);
}
}
};
String header = getString(R.string.confirmation_menu__meta_delete);
String text = getString(R.string.confirmation_menu__meta_delete_text);
String confirm = getString(R.string.confirmation_menu__confirm_delete);
String cancel = getString(R.string.confirmation_menu__cancel);
String checkboxLabel = "";
if (conversation.getType() == IConversation.Type.GROUP) {
checkboxLabel = getString(R.string.confirmation_menu__delete_conversation__checkbox__label);
}
ConfirmationRequest request = new ConfirmationRequest.Builder()
.withHeader(header)
.withMessage(text)
.withPositiveButton(confirm)
.withNegativeButton(cancel)
.withConfirmationCallback(callback)
.withCheckboxLabel(checkboxLabel)
.withWireTheme(getControllerFactory().getThemeController().getOptionsDarkTheme())
.build();
getControllerFactory().getConfirmationController().requestConfirmation(request,
IConfirmationController.CONVERSATION_LIST);
SoundController ctrl = inject(SoundController.class);
if (ctrl != null) {
ctrl.playAlert();
}
}
private void showBlockConfirmation(final User user) {
ConfirmationCallback callback = new TwoButtonConfirmationCallback() {
@Override
public void positiveButtonClicked(boolean checkboxIsSelected) {
if (getStoreFactory() == null ||
getControllerFactory() == null ||
getStoreFactory().isTornDown() ||
getControllerFactory().isTornDown()) {
return;
}
boolean blockingCurrentConversation = user.getConversation().getId().equals(getStoreFactory().getConversationStore().getCurrentConversation().getId());
getStoreFactory().getConnectStore().blockUser(user);
if (blockingCurrentConversation) {
getStoreFactory().getConversationStore().setCurrentConversationToNext(ConversationChangeRequester.BLOCK_USER);
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new BlockingEvent(BlockingEvent.ConformationResponse.BLOCK));
}
@Override
public void negativeButtonClicked() {
if (getControllerFactory() == null ||
getControllerFactory().isTornDown()) {
return;
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new BlockingEvent(BlockingEvent.ConformationResponse.CANCEL));
}
@Override
public void onHideAnimationEnd(boolean confirmed, boolean canceled, boolean checkboxIsSelected) {
}
};
String header = getString(R.string.confirmation_menu__block_header);
String text = getString(R.string.confirmation_menu__block_text_with_name, user.getDisplayName());
String confirm = getString(R.string.confirmation_menu__confirm_block);
String cancel = getString(R.string.confirmation_menu__cancel);
ConfirmationRequest request = new ConfirmationRequest.Builder()
.withHeader(header)
.withMessage(text)
.withPositiveButton(confirm)
.withNegativeButton(cancel)
.withConfirmationCallback(callback)
.withWireTheme(getControllerFactory().getThemeController().getOptionsDarkTheme())
.build();
getControllerFactory().getConfirmationController().requestConfirmation(request,
IConfirmationController.CONVERSATION_LIST);
SoundController ctrl = inject(SoundController.class);
if (ctrl != null) {
ctrl.playAlert();
}
}
@Override
public void onConnectRequestInboxConversationsLoaded(List<IConversation> conversations,
InboxLoadRequester inboxLoadRequester) {
}
public void hideFirstAssignUsernameScreen() {
if (getChildFragmentManager().findFragmentByTag(FirstTimeAssignUsernameFragment.TAG) != null) {
getChildFragmentManager().popBackStackImmediate(FirstTimeAssignUsernameFragment.TAG,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// FirstTimeAssignUsername.Container
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onChooseUsernameChosen() {
getControllerFactory().getUsernameController().closeFirstAssignUsernameScreen();
hideFirstAssignUsernameScreen();
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new OpenedUsernameSettingsEvent());
startActivity(ZetaPreferencesActivity.getUsernameEditPreferencesIntent(getActivity()));
}
@Override
public void onKeepUsernameChosen(String username) {
getControllerFactory().getUsernameController().closeFirstAssignUsernameScreen();
hideFirstAssignUsernameScreen();
getStoreFactory().getZMessagingApiStore().getApi().getSelf().setUsername(username, new CredentialsUpdateListener() {
@Override
public void onUpdated() {
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new KeptGeneratedUsernameEvent(true));
}
@Override
public void onUpdateFailed(int code, String message, String label) {
Toast.makeText(getActivity(), getString(R.string.username__set__toast_error), Toast.LENGTH_SHORT).show();
getControllerFactory().getUsernameController().logout();
getControllerFactory().getUsernameController().setUser(getStoreFactory().getZMessagingApiStore().getApi().getSelf());
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new KeptGeneratedUsernameEvent(false));
}
});
}
@Override
public void onValidUsernameGenerated(String name, String generatedUsername) {
showFirstAssignUsernameScreen(name, generatedUsername);
}
@Override
public void onUsernameAttemptsExhausted(String name) {
}
@Override
public void onCloseFirstAssignUsernameScreen() {
hideFirstAssignUsernameScreen();
}
private void showFirstAssignUsernameScreen(String name, String username) {
// Check if username screen is already shown
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.fl__conversation_list_main);
if (fragment instanceof FirstTimeAssignUsernameFragment) {
return;
}
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.fade_in,
R.anim.fade_out,
R.anim.fade_in,
R.anim.fade_out)
.replace(R.id.fl__conversation_list_main, FirstTimeAssignUsernameFragment.newInstance(name, username), FirstTimeAssignUsernameFragment.TAG)
.addToBackStack(FirstTimeAssignUsernameFragment.TAG)
.commitAllowingStateLoss();
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new SeenUsernameTakeOverScreenEvent());
}
@Override
public void showArchive() {
Page page = getControllerFactory().getNavigationController().getCurrentLeftPage();
switch (page) {
case START:
case CONVERSATION_LIST:
Fragment fragment = getChildFragmentManager().findFragmentByTag(ArchiveListFragment.TAG());
if (fragment == null ||
!(fragment instanceof ArchiveListFragment)) {
ConversationListFragment archiveFragment = ConversationListFragment.newArchiveInstance();
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(R.anim.slide_in_from_bottom_pick_user,
R.anim.open_new_conversation__thread_list_out,
R.anim.open_new_conversation__thread_list_in,
R.anim.slide_out_to_bottom_pick_user)
.replace(R.id.fl__conversation_list_main, archiveFragment, ArchiveListFragment.TAG())
.addToBackStack(ArchiveListFragment.TAG())
.commit();
}
break;
case ARCHIVE:
break;
}
getControllerFactory().getNavigationController().setLeftPage(Page.ARCHIVE, TAG);
}
@Override
public void closeArchive() {
getChildFragmentManager().popBackStackImmediate(ArchiveListFragment.TAG(),
FragmentManager.POP_BACK_STACK_INCLUSIVE);
Page page = getControllerFactory().getNavigationController().getCurrentLeftPage();
if (page == Page.ARCHIVE) {
getControllerFactory().getNavigationController().setLeftPage(Page.CONVERSATION_LIST, TAG);
}
}
public interface Container {
void onOpenUrl(String url);
}
}