/**
* 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.participants;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import com.waz.api.CoreList;
import com.waz.api.IConversation;
import com.waz.api.Message;
import com.waz.api.OtrClient;
import com.waz.api.User;
import com.waz.api.UsersList;
import com.waz.zclient.BaseActivity;
import com.waz.zclient.R;
import com.waz.zclient.controllers.accentcolor.AccentColorObserver;
import com.waz.zclient.controllers.tracking.events.group.OpenedGroupActionEvent;
import com.waz.zclient.controllers.tracking.events.otr.ViewedOtherOtrClientsEvent;
import com.waz.zclient.core.api.scala.ModelObserver;
import com.waz.zclient.core.stores.conversation.ConversationChangeRequester;
import com.waz.zclient.core.stores.participants.ParticipantsStoreObserver;
import com.waz.zclient.pages.BaseFragment;
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.views.ParticipantDetailsTab;
import com.waz.zclient.pages.main.participants.views.ParticipantOtrDeviceAdapter;
import com.waz.zclient.pages.main.participants.views.TabbedParticipantPagerAdapter;
import com.waz.zclient.tracking.GlobalTrackingController;
import com.waz.zclient.ui.views.tab.TabIndicatorLayout;
import com.waz.zclient.utils.ViewUtils;
import com.waz.zclient.views.menus.FooterMenuCallback;
public class TabbedParticipantBodyFragment extends BaseFragment<TabbedParticipantBodyFragment.Container> implements
ParticipantsStoreObserver,
AccentColorObserver,
ParticipantOtrDeviceAdapter.ViewHolder.ViewHolderClicks,
TabbedParticipantPagerAdapter.Callback,
ViewPager.OnPageChangeListener,
ConversationScreenControllerObserver {
public static final String TAG = TabbedParticipantBodyFragment.class.getName();
private static final String ARG__FIRST__PAGE = "ARG__FIRST__PAGE";
public static final int USER_PAGE = 0;
public static final int DEVICE_PAGE = 1;
private ViewPager viewPager;
private final ParticipantOtrDeviceAdapter participantOtrDeviceAdapter;
private CallbackImpl callbacks;
private final ModelObserver<User> userModelObserver = new ModelObserver<User>() {
@Override
public void updated(User user) {
otrClientsModelObserver.setAndUpdate(user.getOtrClients());
participantOtrDeviceAdapter.setUserDisplayName(user != null ? user.getDisplayName() : null);
participantOtrDeviceAdapter.notifyDataSetChanged();
}
};
private final ModelObserver<CoreList<OtrClient>> otrClientsModelObserver = new ModelObserver<CoreList<OtrClient>>() {
@Override
public void updated(CoreList<OtrClient> model) {
participantOtrDeviceAdapter.setOtrClients(model);
}
};
private final ModelObserver<User> userModelObserverForTabs = new ModelObserver<User>() {
@Override
public void updated(User user) {
callbacks = new CallbackImpl(user);
updateViews(user);
}
};
public static TabbedParticipantBodyFragment newInstance(int firstPage) {
TabbedParticipantBodyFragment fragment = new TabbedParticipantBodyFragment();
Bundle bundle = new Bundle();
bundle.putInt(ARG__FIRST__PAGE, firstPage);
fragment.setArguments(bundle);
return fragment;
}
public TabbedParticipantBodyFragment() {
participantOtrDeviceAdapter = new ParticipantOtrDeviceAdapter(this);
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
final Fragment parent = getParentFragment();
// Apply the workaround only if this is a child fragment, and the parent
// is being removed.
if (!enter && parent != null && parent.isRemoving()) {
// This is a workaround for the bug where child fragments disappear when
// the parent is removed (as all children are first removed from the parent)
// See https://code.google.com/p/android/issues/detail?id=55228
Animation doNothingAnim = new AlphaAnimation(1, 1);
doNothingAnim.setDuration(ViewUtils.getNextAnimationDuration(parent));
return doNothingAnim;
} else {
return super.onCreateAnimation(transit, enter, nextAnim);
}
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_participants_single_tabbed, viewGroup, false);
TabIndicatorLayout tabIndicatorLayout = ViewUtils.getView(view, R.id.til_single_participant_tabs);
int color;
if (getControllerFactory().getThemeController().isDarkTheme()) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
color = getResources().getColor(R.color.text__secondary_dark);
} else {
color = getResources().getColor(R.color.text__secondary_dark, getContext().getTheme());
}
} else {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
//noinspection deprecation
color = getResources().getColor(R.color.text__secondary_light);
} else {
color = getResources().getColor(R.color.text__secondary_light, getContext().getTheme());
}
}
if (tabIndicatorLayout != null) {
tabIndicatorLayout.setPrimaryColor(color);
}
viewPager = ViewUtils.getView(view, R.id.vp_single_participant_viewpager);
viewPager.setAdapter(new TabbedParticipantPagerAdapter(getActivity(), participantOtrDeviceAdapter, this));
viewPager.addOnPageChangeListener(this);
tabIndicatorLayout.setViewPager(viewPager);
if (savedInstanceState == null) {
if (getControllerFactory().getConversationScreenController().shouldShowDevicesTab()) {
viewPager.setCurrentItem(1);
getControllerFactory().getConversationScreenController().setShowDevicesTab(null);
} else {
int firstPage = getArguments().getInt(ARG__FIRST__PAGE);
viewPager.setCurrentItem(firstPage);
}
}
return view;
}
@Override
public void onStart() {
super.onStart();
getStoreFactory().getParticipantsStore().addParticipantsStoreObserver(this);
getControllerFactory().getAccentColorController().addAccentColorObserver(this);
getControllerFactory().getConversationScreenController().addConversationControllerObservers(this);
updateUser();
}
@Override
public void onStop() {
getControllerFactory().getConversationScreenController().removeConversationControllerObservers(this);
getControllerFactory().getAccentColorController().removeAccentColorObserver(this);
getStoreFactory().getParticipantsStore().removeParticipantsStoreObserver(this);
super.onStop();
}
@Override
public void onDestroyView() {
viewPager.removeOnPageChangeListener(this);
viewPager = null;
super.onDestroyView();
}
@Override
public void onOtrClientClick(OtrClient otrClient) {
if (callbacks == null) {
return;
}
callbacks.showOtrDetails(otrClient);
}
@Override
public void onOtrHeaderClick() {
getContainer().onOpenUrl(getResources().getString(R.string.url_otr_learn_why));
}
@Override
public void finishUpdate() {
userModelObserverForTabs.forceUpdate();
}
@Override
public void conversationUpdated(IConversation conversation) {
updateUser();
}
@Override
public void participantsUpdated(UsersList participants) {
updateUser();
}
@Override
public void otherUserUpdated(User otherUser) {
updateUser();
}
@Override
public void onAccentColorHasChanged(Object sender, int color) {
participantOtrDeviceAdapter.setAccentColor(color);
}
private void updateViews(User user) {
if (viewPager == null) {
return;
}
View view = viewPager.findViewWithTag(TabbedParticipantPagerAdapter.ParticipantTabs.DETAILS);
if (view instanceof ParticipantDetailsTab) {
ParticipantDetailsTab tab = (ParticipantDetailsTab) view;
tab.setUser(user);
final IConversation conversation = getStoreFactory().getConversationStore().getCurrentConversation();
if (conversation != null) {
if (conversation.getType() == IConversation.Type.ONE_TO_ONE) {
tab.updateFooterMenu(R.string.glyph__add_people,
R.string.conversation__action__create_group,
R.string.glyph__more,
R.string.empty_string,
callbacks);
} else {
tab.updateFooterMenu(R.string.glyph__conversation,
R.string.empty_string,
R.string.glyph__minus,
R.string.empty_string,
callbacks);
}
}
}
}
private void updateUser() {
IConversation conversation = getStoreFactory().getConversationStore().getCurrentConversation();
if (conversation == null) {
userModelObserver.clear();
userModelObserverForTabs.clear();
otrClientsModelObserver.clear();
return;
}
User updatedUser;
if (conversation.getType() == IConversation.Type.ONE_TO_ONE) {
updatedUser = conversation.getOtherParticipant();
} else {
updatedUser = getStoreFactory().getSingleParticipantStore().getUser();
}
userModelObserver.setAndUpdate(updatedUser);
userModelObserverForTabs.setAndUpdate(updatedUser);
}
@Override
public void onShowParticipants(View anchorView, boolean isSingleConversation, boolean isMemberOfConversation, boolean showDeviceTabIfSingle) {
if (getControllerFactory().getConversationScreenController().shouldShowDevicesTab()) {
viewPager.setCurrentItem(1);
getControllerFactory().getConversationScreenController().setShowDevicesTab(null);
}
if (isSingleConversation && showDeviceTabIfSingle) {
viewPager.setCurrentItem(1);
}
}
@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) {
}
@Override
public void onShowOtrClient(OtrClient otrClient, User user) {
}
@Override
public void onShowCurrentOtrClient() {
}
@Override
public void onHideOtrClient() {
}
@Override
public void onShowLikesList(Message message) {
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == 0 || getControllerFactory() == null || getControllerFactory().isTornDown()) {
return;
}
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new ViewedOtherOtrClientsEvent());
}
@Override
public void onPageScrollStateChanged(int state) {
}
public interface MenuActions {
void showOtrDetails(OtrClient otrClient);
}
public interface Container {
void showRemoveConfirmation(User user);
void onOpenUrl(String url);
}
private class CallbackImpl implements FooterMenuCallback,
MenuActions {
final User user;
CallbackImpl(User user) {
this.user = user;
}
@Override
public void onLeftActionClicked() {
if (getStoreFactory() == null || getStoreFactory().isTornDown() ||
getControllerFactory() == null || getControllerFactory().isTornDown()) {
return;
}
IConversation conversation = getStoreFactory().getConversationStore().getCurrentConversation();
if (conversation == null) {
return;
}
if (conversation.getType() == IConversation.Type.ONE_TO_ONE) {
((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class).tagEvent(new OpenedGroupActionEvent());
getControllerFactory().getConversationScreenController().addPeopleToConversation();
} else {
getControllerFactory().getConversationScreenController().hideParticipants(true, false);
// Go to conversation with this user
getStoreFactory().getConversationStore().setCurrentConversation(user.getConversation(),
ConversationChangeRequester.START_CONVERSATION);
}
}
@Override
public void onRightActionClicked() {
if (getStoreFactory() == null || getStoreFactory().isTornDown() ||
getControllerFactory() == null || getControllerFactory().isTornDown()) {
return;
}
IConversation conversation = getStoreFactory().getConversationStore().getCurrentConversation();
if (conversation == null) {
return;
}
if (conversation.getType() == IConversation.Type.ONE_TO_ONE) {
getControllerFactory().getConversationScreenController().showConversationMenu(
IConversationScreenController.CONVERSATION_DETAILS,
conversation,
null);
} else {
getContainer().showRemoveConfirmation(user);
}
}
@Override
public void showOtrDetails(OtrClient otrClient) {
if (getControllerFactory() == null || getControllerFactory().isTornDown()) {
return;
}
getControllerFactory().getConversationScreenController().showOtrClient(otrClient, user);
}
}
}