/** * 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.Bundle; import android.support.annotation.NonNull; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.waz.api.ConversationsList; import com.waz.api.IConversation; import com.waz.api.SyncState; import com.waz.api.UpdateListener; import com.waz.api.User; import com.waz.zclient.BaseActivity; import com.waz.zclient.OnBackPressedListener; import com.waz.zclient.R; import com.waz.zclient.core.stores.conversation.ConversationChangeRequester; import com.waz.zclient.core.stores.conversation.ConversationStoreObserver; import com.waz.zclient.core.stores.singleparticipants.SingleParticipantStoreObserver; import com.waz.zclient.pages.BaseFragment; import com.waz.zclient.pages.main.conversation.controller.IConversationScreenController; import com.waz.zclient.tracking.GlobalTrackingController; import com.waz.zclient.ui.optionsmenu.OptionsMenu; import com.waz.zclient.ui.optionsmenu.OptionsMenuItem; import com.waz.zclient.ui.theme.OptionsTheme; import com.waz.zclient.utils.TrackingUtils; import com.waz.zclient.utils.ViewUtils; import java.util.ArrayList; import java.util.List; public class OptionsMenuFragment extends BaseFragment<OptionsMenuFragment.Container> implements SingleParticipantStoreObserver, ConversationStoreObserver, OptionsMenuControl.Callback, OptionsMenu.Callback { public static final String TAG = OptionsMenuFragment.class.getName(); private static final String ARGUMENT_IN_LIST = "ARGUMENT_IN_LIST "; private static final String ARGUMENT_CONVERSATION_ID = "ARGUMENT_CONVERSATION_ID"; private static final String ARGUMENT_WIRE_THEME = "ARGUMENT_WIRE_THEME"; private OptionsMenu optionsMenu; private @IConversationScreenController.ConversationMenuRequester int requester; private IConversation conversation; private User user; private boolean inConversationList; private OptionsTheme optionsTheme; public static OptionsMenuFragment newInstance(boolean inConversationList) { OptionsMenuFragment fragment = new OptionsMenuFragment(); Bundle args = new Bundle(); args.putBoolean(ARGUMENT_IN_LIST, inConversationList); args.putString(ARGUMENT_CONVERSATION_ID, ""); fragment.setArguments(args); return fragment; } public static OptionsMenuFragment newInstance(boolean inConversationList, String conversationId) { OptionsMenuFragment fragment = new OptionsMenuFragment(); Bundle args = new Bundle(); args.putBoolean(ARGUMENT_IN_LIST, inConversationList); args.putString(ARGUMENT_CONVERSATION_ID, conversationId); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); inConversationList = getArguments().getBoolean(ARGUMENT_IN_LIST); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View view = inflater.inflate(R.layout.fragment_conversation_option_menu, container, false); optionsMenu = ViewUtils.getView(view, R.id.om__participant); if (savedInstanceState != null) { switch (OptionsTheme.Type.values()[savedInstanceState.getInt(ARGUMENT_WIRE_THEME)]) { case DARK: optionsTheme = getControllerFactory().getThemeController().getOptionsDarkTheme(); break; case LIGHT: optionsTheme = getControllerFactory().getThemeController().getOptionsLightTheme(); break; } } else { optionsTheme = getControllerFactory().getThemeController().getOptionsLightTheme(); } return view; } @Override public void onStart() { super.onStart(); getStoreFactory().getConversationStore().addConversationStoreObserver(this); String conversationId = getArguments().getString(ARGUMENT_CONVERSATION_ID); if (!TextUtils.isEmpty(conversationId)) { getStoreFactory() .getZMessagingApiStore() .getApi() .getConversations() .getConversation(conversationId, new ConversationsList.ConversationCallback() { @Override public void onConversationsFound(Iterable<IConversation> iterable) { // use only the first one connectConversation(iterable.iterator().next()); } }); getStoreFactory().getConversationStore().loadMenuConversation(conversationId); } getContainer().getOptionsMenuControl().setCallback(this); } @Override public void onResume() { super.onResume(); optionsMenu.setCallback(this); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(ARGUMENT_WIRE_THEME, optionsTheme.getType().ordinal()); if (conversation != null) { getArguments().putString(ARGUMENT_CONVERSATION_ID, conversation.getId()); } else { getArguments().putString(ARGUMENT_CONVERSATION_ID, ""); } } @Override public void onPause() { optionsMenu.setCallback(null); super.onPause(); } @Override public void onStop() { getContainer().getOptionsMenuControl().setCallback(null); getStoreFactory().getConversationStore().removeConversationStoreObserver(this); getStoreFactory().getSingleParticipantStore().removeSingleParticipantObserver(this); disconnectConversation(); disconnectUser(); super.onStop(); } ////////////////////////////////////////////////////////////////////////////////////////// // // ConversationStoreStoreObserver // ////////////////////////////////////////////////////////////////////////////////////////// @Override public void onConversationListUpdated(@NonNull ConversationsList conversationsList) { } @Override public void onConversationListStateHasChanged(ConversationsList.ConversationsListState state) { } @Override public void onCurrentConversationHasChanged(IConversation fromConversation, IConversation toConversation, ConversationChangeRequester conversationChangerSender) { } @Override public void onConversationSyncingStateHasChanged(SyncState syncState) { } @Override public void onMenuConversationHasChanged(final IConversation conversation) { List<OptionsMenuItem> items = new ArrayList<>(); switch (conversation.getType()) { case GROUP: if (conversation.isMemberOfConversation()) { // silence/unsilence if (conversation.isMuted()) { items.add(OptionsMenuItem.UNSILENCE); } else { items.add(OptionsMenuItem.SILENCE); } if (inConversationList) { items.add(OptionsMenuItem.CALL); items.add(OptionsMenuItem.PICTURE); } else { //in ParticipantsFragment items.add(OptionsMenuItem.RENAME); } } // archive if (conversation.isArchived()) { items.add(OptionsMenuItem.UNARCHIVE); } else { items.add(OptionsMenuItem.ARCHIVE); } items.add(OptionsMenuItem.DELETE); // leave if (conversation.isMemberOfConversation()) { items.add(OptionsMenuItem.LEAVE); } optionsMenu.setMenuItems(items, optionsTheme); break; case ONE_TO_ONE: items.add(OptionsMenuItem.CALL); items.add(OptionsMenuItem.PICTURE); connectUser(conversation.getOtherParticipant()); break; case WAIT_FOR_CONNECTION: connectUser(conversation.getOtherParticipant()); } } ////////////////////////////////////////////////////////////////////////////////////////// // // SingleParticipantsStoreObserver // ////////////////////////////////////////////////////////////////////////////////////////// @Override public void onUserUpdated(final User user) { if (user == null || conversation == null) { return; } List<OptionsMenuItem> items = new ArrayList<>(); switch (user.getConnectionStatus()) { case ACCEPTED: case BLOCKED: if (conversation.isMuted()) { items.add(OptionsMenuItem.UNSILENCE); } else { items.add(OptionsMenuItem.SILENCE); } break; } if (requester != IConversationScreenController.USER_PROFILE_SEARCH && requester != IConversationScreenController.USER_PROFILE_PARTICIPANTS) { if (conversation.isArchived()) { items.add(OptionsMenuItem.UNARCHIVE); } else { items.add(OptionsMenuItem.ARCHIVE); } } switch (user.getConnectionStatus()) { case ACCEPTED: items.add(OptionsMenuItem.DELETE); items.add(OptionsMenuItem.BLOCK); if (inConversationList) { items.add(OptionsMenuItem.CALL); items.add(OptionsMenuItem.PICTURE); } break; case BLOCKED: items.add(OptionsMenuItem.UNBLOCK); break; case PENDING_FROM_USER: items.add(OptionsMenuItem.BLOCK); break; } optionsMenu.setMenuItems(items, optionsTheme); } @Override public void onOptionsMenuStateHasChanged(OptionsMenu.State state) { getContainer().onOptionMenuStateHasChanged(state); } @Override public void onOptionsMenuItemClicked(OptionsMenuItem optionsMenuItem) { getContainer().onOptionsItemClicked(conversation, user, optionsMenuItem); if (getControllerFactory() == null || getControllerFactory().isTornDown()) { return; } TrackingUtils.tagOptionsMenuSelectedEvent(((BaseActivity) getActivity()).injectJava(GlobalTrackingController.class), optionsMenuItem, conversation.getType(), inConversationList, (requester == IConversationScreenController.CONVERSATION_LIST_SWIPE)); } @Override public boolean onOptionsMenuItemLongClicked(OptionsMenuItem optionsMenuItem) { return false; } @Override public void onOpenRequest() { optionsMenu.open(); } @Override public boolean onCloseRequest() { return optionsMenu.close(); } @Override public void onCreateMenu(IConversation conversation, @IConversationScreenController.ConversationMenuRequester int requester, OptionsTheme optionsTheme) { this.optionsTheme = optionsTheme; this.requester = requester; connectConversation(conversation); } private void connectConversation(IConversation conversation) { this.conversation = conversation; this.conversation.addUpdateListener(conversationUpdateListener); conversationUpdateListener.updated(); optionsMenu.setTitle(conversation.getName()); optionsMenu.setConversationDetails(conversation); } private void disconnectConversation() { if (this.conversation != null) { this.conversation.removeUpdateListener(conversationUpdateListener); this.conversation = null; } } private void connectUser(User user) { this.user = user; this.user.addUpdateListener(userUpdateListener); userUpdateListener.updated(); } private void disconnectUser() { if (this.user != null) { this.user.removeUpdateListener(userUpdateListener); this.user = null; } } private UpdateListener userUpdateListener = new UpdateListener() { @Override public void updated() { if (user != null) { onUserUpdated(user); } } }; private UpdateListener conversationUpdateListener = new UpdateListener() { @Override public void updated() { if (conversation != null) { onMenuConversationHasChanged(conversation); } } }; public interface Container extends OnBackPressedListener { void onOptionMenuStateHasChanged(OptionsMenu.State state); void onOptionsItemClicked(IConversation conversation, User user, OptionsMenuItem item); OptionsMenuControl getOptionsMenuControl(); } }