/**
* 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.connect;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.TextView;
import com.waz.api.IConversation;
import com.waz.api.UpdateListener;
import com.waz.api.User;
import com.waz.zclient.R;
import com.waz.zclient.controllers.accentcolor.AccentColorObserver;
import com.waz.zclient.core.stores.connect.ConnectStoreObserver;
import com.waz.zclient.core.stores.connect.IConnectStore;
import com.waz.zclient.core.stores.conversation.OnConversationLoadedListener;
import com.waz.zclient.pages.BaseFragment;
import com.waz.zclient.pages.main.participants.ProfileAnimation;
import com.waz.zclient.pages.main.participants.ProfileSourceAnimation;
import com.waz.zclient.pages.main.participants.ProfileTabletAnimation;
import com.waz.zclient.pages.main.participants.dialog.DialogLaunchMode;
import com.waz.zclient.ui.theme.ThemeUtils;
import com.waz.zclient.ui.utils.KeyboardUtils;
import com.waz.zclient.ui.views.UserDetailsView;
import com.waz.zclient.ui.views.ZetaButton;
import com.waz.zclient.utils.LayoutSpec;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.views.images.ImageAssetImageView;
import com.waz.zclient.views.menus.FooterMenu;
import com.waz.zclient.views.menus.FooterMenuCallback;
public class PendingConnectRequestFragment extends BaseFragment<PendingConnectRequestFragment.Container> implements UserProfile,
OnConversationLoadedListener,
ConnectStoreObserver,
AccentColorObserver,
UpdateListener {
public static final String TAG = PendingConnectRequestFragment.class.getName();
public static final String ARGUMENT_USER_ID = "ARGUMENT_USER_ID";
public static final String ARGUMENT_CONVERSATION_ID = "ARGUMENT_CONVERSATION_ID";
public static final String ARGUMENT_LOAD_MODE = "ARGUMENT_LOAD_MODE";
public static final String ARGUMENT_USER_REQUESTER = "ARGUMENT_USER_REQUESTER";
public static final String STATE_IS_SHOWING_FOOTER_MENU = "STATE_IS_SHOWING_FOOTER_MENU";
private String userId;
private String conversationId;
private IConversation conversation;
private ConnectRequestLoadMode loadMode;
private IConnectStore.UserRequester userRequester;
private boolean isShowingFooterMenu;
private boolean isBelowUserProfile;
private UserDetailsView userDetailsView;
private ZetaButton unblockButton;
private FooterMenu footerMenu;
private Toolbar toolbar;
private TextView displayNameTextView;
private ImageAssetImageView imageAssetImageViewProfile;
public static PendingConnectRequestFragment newInstance(String userId,
String conversationId,
ConnectRequestLoadMode loadMode,
IConnectStore.UserRequester userRequester) {
PendingConnectRequestFragment newFragment = new PendingConnectRequestFragment();
Bundle args = new Bundle();
args.putString(ARGUMENT_USER_ID, userId);
args.putString(ARGUMENT_CONVERSATION_ID, conversationId);
args.putString(ARGUMENT_USER_REQUESTER, userRequester.toString());
args.putString(ARGUMENT_LOAD_MODE, loadMode.toString());
newFragment.setArguments(args);
return newFragment;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Lifecycle
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
Animation animation = super.onCreateAnimation(transit, enter, nextAnim);
if (getControllerFactory().getConversationScreenController().getPopoverLaunchMode() != DialogLaunchMode.AVATAR &&
getControllerFactory().getConversationScreenController().getPopoverLaunchMode() != DialogLaunchMode.COMMON_USER) {
// No animation when request is shown in conversation list
IConnectStore.UserRequester userRequester = IConnectStore.UserRequester.valueOf(getArguments().getString(ARGUMENT_USER_REQUESTER));
if (userRequester != IConnectStore.UserRequester.CONVERSATION || isBelowUserProfile) {
int centerX = ViewUtils.getOrientationIndependentDisplayWidth(getActivity()) / 2;
int centerY = ViewUtils.getOrientationIndependentDisplayHeight(getActivity()) / 2;
int duration;
int delay = 0;
if (isBelowUserProfile) {
if (LayoutSpec.isTablet(getActivity())) {
animation = new ProfileTabletAnimation(enter,
getResources().getInteger(R.integer.framework_animation_duration_long),
-getResources().getDimensionPixelSize(R.dimen.participant_dialog__initial_width));
} else {
if (enter) {
isBelowUserProfile = false;
duration = getResources().getInteger(R.integer.reopen_profile_source__animation_duration);
delay = getResources().getInteger(R.integer.reopen_profile_source__delay);
} else {
duration = getResources().getInteger(R.integer.reopen_profile_source__animation_duration);
}
animation = new ProfileSourceAnimation(enter, duration, delay, centerX, centerY);
}
} else if (nextAnim != 0) {
if (LayoutSpec.isTablet(getActivity())) {
animation = new ProfileTabletAnimation(enter,
getResources().getInteger(R.integer.framework_animation_duration_long),
getResources().getDimensionPixelSize(R.dimen.participant_dialog__initial_width));
} else {
if (enter) {
duration = getResources().getInteger(R.integer.open_profile__animation_duration);
delay = getResources().getInteger(R.integer.open_profile__delay);
} else {
duration = getResources().getInteger(R.integer.close_profile__animation_duration);
}
animation = new ProfileAnimation(enter, duration, delay, centerX, centerY);
}
}
}
}
return animation;
}
@Override
public View onCreateView(LayoutInflater inflater, final ViewGroup viewContainer, Bundle savedInstanceState) {
if (savedInstanceState != null) {
userId = savedInstanceState.getString(ARGUMENT_USER_ID);
conversationId = savedInstanceState.getString(ARGUMENT_CONVERSATION_ID);
loadMode = ConnectRequestLoadMode.valueOf(savedInstanceState.getString(ARGUMENT_LOAD_MODE));
userRequester = IConnectStore.UserRequester.valueOf(savedInstanceState.getString(ARGUMENT_USER_REQUESTER));
isShowingFooterMenu = savedInstanceState.getBoolean(STATE_IS_SHOWING_FOOTER_MENU);
} else {
userId = getArguments().getString(ARGUMENT_USER_ID);
conversationId = getArguments().getString(ARGUMENT_CONVERSATION_ID);
loadMode = ConnectRequestLoadMode.valueOf(getArguments().getString(ARGUMENT_LOAD_MODE));
userRequester = IConnectStore.UserRequester.valueOf(getArguments().getString(ARGUMENT_USER_REQUESTER));
isShowingFooterMenu = false;
}
View rootView = inflater.inflate(R.layout.fragment_connect_request_pending, viewContainer, false);
userDetailsView = ViewUtils.getView(rootView, R.id.udv__pending_connect__user_details);
unblockButton = ViewUtils.getView(rootView, R.id.zb__connect_request__unblock_button);
footerMenu = ViewUtils.getView(rootView, R.id.fm__footer);
toolbar = ViewUtils.getView(rootView, R.id.t__pending_connect__toolbar);
displayNameTextView = ViewUtils.getView(rootView, R.id.tv__pending_connect_toolbar__title);
imageAssetImageViewProfile = ViewUtils.getView(rootView, R.id.iaiv__pending_connect);
imageAssetImageViewProfile.setDisplayType(ImageAssetImageView.DisplayType.CIRCLE);
imageAssetImageViewProfile.setSaturation(0);
updateToolbarNavigationIcon();
if (userRequester == IConnectStore.UserRequester.PARTICIPANTS) {
toolbar.setBackground(null);
}
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
switch (userRequester) {
case CONVERSATION:
if (LayoutSpec.isTablet(getContext()) && ViewUtils.isInLandscape(getContext())) {
return;
}
getActivity().onBackPressed();
KeyboardUtils.closeKeyboardIfShown(getActivity());
break;
default:
getContainer().dismissUserProfile();
break;
}
}
});
View backgroundContainer = ViewUtils.getView(rootView, R.id.ll__pending_connect__background_container);
if (getControllerFactory().getConversationScreenController().getPopoverLaunchMode() == DialogLaunchMode.AVATAR ||
getControllerFactory().getConversationScreenController().getPopoverLaunchMode() == DialogLaunchMode.COMMON_USER) {
backgroundContainer.setClickable(true);
} else {
backgroundContainer.setBackgroundColor(Color.TRANSPARENT);
}
// Hide views until connection status of user is determined
footerMenu.setVisibility(View.GONE);
unblockButton.setVisibility(View.GONE);
return rootView;
}
@Override
public void onStart() {
super.onStart();
getControllerFactory().getAccentColorController().addAccentColorObserver(this);
getStoreFactory().getConnectStore().addConnectRequestObserver(this);
switch (loadMode) {
case LOAD_BY_CONVERSATION_ID:
getStoreFactory().getConversationStore().loadConversation(conversationId, this);
break;
case LOAD_BY_USER_ID:
getStoreFactory().getConnectStore().loadUser(userId, userRequester);
break;
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(ARGUMENT_USER_ID, userId);
outState.putString(ARGUMENT_CONVERSATION_ID, conversationId);
if (loadMode != null) {
outState.putString(ARGUMENT_LOAD_MODE, loadMode.toString());
}
if (userRequester != null) {
outState.putString(ARGUMENT_USER_REQUESTER, userRequester.toString());
}
// Save if footer menu was visible -> used to toggle accept & footer menu in incoming connect request opened from group participants
outState.putBoolean(STATE_IS_SHOWING_FOOTER_MENU, isShowingFooterMenu);
super.onSaveInstanceState(outState);
}
@Override
public void onStop() {
getStoreFactory().getConnectStore().removeConnectRequestObserver(this);
getControllerFactory().getAccentColorController().removeAccentColorObserver(this);
super.onStop();
}
@Override
public void onDestroyView() {
userDetailsView.recycle();
imageAssetImageViewProfile = null;
unblockButton = null;
footerMenu = null;
displayNameTextView = null;
if (conversation != null) {
conversation.removeUpdateListener(this);
conversation = null;
}
super.onDestroyView();
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// UserProfile
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void isBelowUserProfile(boolean isBelow) {
isBelowUserProfile = isBelow;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// UI
//
//////////////////////////////////////////////////////////////////////////////////////////
private void setFooterForOutgoingConnectRequest(final User user) {
// Show footer
footerMenu.setVisibility(View.VISIBLE);
isShowingFooterMenu = true;
footerMenu.setRightActionText("");
footerMenu.setCallback(new FooterMenuCallback() {
@Override
public void onLeftActionClicked() {
user.cancelConnection();
getActivity().onBackPressed();
}
@Override
public void onRightActionClicked() {
}
});
}
private void setFooterForIncomingConnectRequest(final User user) {
if (userRequester != IConnectStore.UserRequester.PARTICIPANTS) {
return;
}
footerMenu.setVisibility(View.VISIBLE);
footerMenu.setRightActionText(getString(R.string.glyph__minus));
footerMenu.setCallback(new FooterMenuCallback() {
@Override
public void onLeftActionClicked() {
IConversation conversation = user.acceptConnection();
getContainer().onAcceptedConnectRequest(conversation);
}
@Override
public void onRightActionClicked() {
getContainer().showRemoveConfirmation(user);
}
});
footerMenu.setLeftActionText(getString(R.string.glyph__plus));
footerMenu.setLeftActionLabelText(getString(R.string.send_connect_request__connect_button__text));
}
private void setFooterForIgnoredConnectRequest(final User user) {
footerMenu.setVisibility(View.VISIBLE);
footerMenu.setRightActionText("");
footerMenu.setRightActionLabelText("");
footerMenu.setCallback(new FooterMenuCallback() {
@Override
public void onLeftActionClicked() {
IConversation conversation = user.acceptConnection();
getContainer().onAcceptedConnectRequest(conversation);
}
@Override
public void onRightActionClicked() {
}
});
footerMenu.setLeftActionText(getString(R.string.glyph__plus));
footerMenu.setLeftActionLabelText(getString(R.string.send_connect_request__connect_button__text));
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConversationStoreObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onConversationLoaded(IConversation conversation) {
switch (loadMode) {
case LOAD_BY_CONVERSATION_ID:
if (this.conversation != null) {
this.conversation.removeUpdateListener(this);
}
this.conversation = conversation;
if (conversation != null) {
conversation.addUpdateListener(this);
}
getStoreFactory().getConnectStore().loadUser(conversation.getOtherParticipant().getId(),
userRequester);
break;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ConnectStoreObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onConnectUserUpdated(final User user, IConnectStore.UserRequester userRequester) {
if (this.userRequester != userRequester ||
user == null) {
return;
}
switch (loadMode) {
case LOAD_BY_USER_ID:
getStoreFactory().getConversationStore().loadConversation(user.getConversation().getId(),
this);
break;
}
imageAssetImageViewProfile.connectImageAsset(user.getPicture());
userDetailsView.setUser(user);
displayNameTextView.setText(user.getName());
switch (user.getConnectionStatus()) {
case PENDING_FROM_OTHER:
setFooterForIncomingConnectRequest(user);
break;
case IGNORED:
setFooterForIgnoredConnectRequest(user);
break;
case PENDING_FROM_USER:
setFooterForOutgoingConnectRequest(user);
break;
}
}
@Override
public void onInviteRequestSent(IConversation conversation) {
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// AccentColorControllerObserver
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onAccentColorHasChanged(Object sender, int color) {
unblockButton.setIsFilled(false);
unblockButton.setAccentColor(color);
}
private void updateToolbarNavigationIcon() {
updateToolbarNavigationIcon(null);
}
private void updateToolbarNavigationIcon(Configuration newConfig) {
if (LayoutSpec.isPhone(getContext())) {
return;
}
if (userRequester == IConnectStore.UserRequester.CONVERSATION &&
(ViewUtils.isInLandscape(getContext()) ||
(newConfig != null && ViewUtils.isInLandscape(newConfig)))) {
toolbar.setNavigationIcon(null);
} else {
switch (userRequester) {
case CONVERSATION:
if (ThemeUtils.isDarkTheme(getContext())) {
toolbar.setNavigationIcon(R.drawable.ic_action_menu_light);
} else {
toolbar.setNavigationIcon(R.drawable.ic_action_menu_dark);
}
break;
default:
if (ThemeUtils.isDarkTheme(getContext())) {
toolbar.setNavigationIcon(R.drawable.action_back_light);
} else {
toolbar.setNavigationIcon(R.drawable.action_back_dark);
}
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateListener for Conversation
//
//////////////////////////////////////////////////////////////////////////////////////////
@Override
public void updated() {
getContainer().onConversationUpdated(conversation);
}
public interface Container extends UserProfileContainer {
void onAcceptedConnectRequest(IConversation conversation);
void onConversationUpdated(IConversation conversation);
}
}