Home | History | Annotate | Download | only in conversationlist
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.messaging.ui.conversationlist;
     17 
     18 import android.support.v4.util.ArrayMap;
     19 import android.text.TextUtils;
     20 import android.view.ActionMode;
     21 import android.view.ActionMode.Callback;
     22 import android.view.Menu;
     23 import android.view.MenuItem;
     24 
     25 import com.android.messaging.R;
     26 import com.android.messaging.datamodel.data.ConversationListData;
     27 import com.android.messaging.datamodel.data.ConversationListItemData;
     28 import com.android.messaging.util.Assert;
     29 
     30 import java.util.Collection;
     31 import java.util.HashSet;
     32 
     33 public class MultiSelectActionModeCallback implements Callback {
     34     private HashSet<String> mBlockedSet;
     35 
     36     public interface Listener {
     37         void onActionBarDelete(Collection<SelectedConversation> conversations);
     38         void onActionBarArchive(Iterable<SelectedConversation> conversations,
     39                 boolean isToArchive);
     40         void onActionBarNotification(Iterable<SelectedConversation> conversations,
     41                 boolean isNotificationOn);
     42         void onActionBarAddContact(final SelectedConversation conversation);
     43         void onActionBarBlock(final SelectedConversation conversation);
     44         void onActionBarHome();
     45     }
     46 
     47     static class SelectedConversation {
     48         public final String conversationId;
     49         public final long timestamp;
     50         public final String icon;
     51         public final String otherParticipantNormalizedDestination;
     52         public final CharSequence participantLookupKey;
     53         public final boolean isGroup;
     54         public final boolean isArchived;
     55         public final boolean notificationEnabled;
     56         public SelectedConversation(ConversationListItemData data) {
     57             conversationId = data.getConversationId();
     58             timestamp = data.getTimestamp();
     59             icon = data.getIcon();
     60             otherParticipantNormalizedDestination = data.getOtherParticipantNormalizedDestination();
     61             participantLookupKey = data.getParticipantLookupKey();
     62             isGroup = data.getIsGroup();
     63             isArchived = data.getIsArchived();
     64             notificationEnabled = data.getNotificationEnabled();
     65         }
     66     }
     67 
     68     private final ArrayMap<String, SelectedConversation> mSelectedConversations;
     69 
     70     private Listener mListener;
     71     private MenuItem mArchiveMenuItem;
     72     private MenuItem mUnarchiveMenuItem;
     73     private MenuItem mAddContactMenuItem;
     74     private MenuItem mBlockMenuItem;
     75     private MenuItem mNotificationOnMenuItem;
     76     private MenuItem mNotificationOffMenuItem;
     77     private boolean mHasInflated;
     78 
     79     public MultiSelectActionModeCallback(final Listener listener) {
     80         mListener = listener;
     81         mSelectedConversations = new ArrayMap<>();
     82 
     83     }
     84 
     85     @Override
     86     public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
     87         actionMode.getMenuInflater().inflate(R.menu.conversation_list_fragment_select_menu, menu);
     88         mArchiveMenuItem = menu.findItem(R.id.action_archive);
     89         mUnarchiveMenuItem = menu.findItem(R.id.action_unarchive);
     90         mAddContactMenuItem = menu.findItem(R.id.action_add_contact);
     91         mBlockMenuItem = menu.findItem(R.id.action_block);
     92         mNotificationOffMenuItem = menu.findItem(R.id.action_notification_off);
     93         mNotificationOnMenuItem = menu.findItem(R.id.action_notification_on);
     94         mHasInflated = true;
     95         updateActionIconsVisiblity();
     96         return true;
     97     }
     98 
     99     @Override
    100     public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
    101         return true;
    102     }
    103 
    104     @Override
    105     public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
    106         switch(menuItem.getItemId()) {
    107             case R.id.action_delete:
    108                 mListener.onActionBarDelete(mSelectedConversations.values());
    109                 return true;
    110             case R.id.action_archive:
    111                 mListener.onActionBarArchive(mSelectedConversations.values(), true);
    112                 return true;
    113             case R.id.action_unarchive:
    114                 mListener.onActionBarArchive(mSelectedConversations.values(), false);
    115                 return true;
    116             case R.id.action_notification_off:
    117                 mListener.onActionBarNotification(mSelectedConversations.values(), false);
    118                 return true;
    119             case R.id.action_notification_on:
    120                 mListener.onActionBarNotification(mSelectedConversations.values(), true);
    121                 return true;
    122             case R.id.action_add_contact:
    123                 Assert.isTrue(mSelectedConversations.size() == 1);
    124                 mListener.onActionBarAddContact(mSelectedConversations.valueAt(0));
    125                 return true;
    126             case R.id.action_block:
    127                 Assert.isTrue(mSelectedConversations.size() == 1);
    128                 mListener.onActionBarBlock(mSelectedConversations.valueAt(0));
    129                 return true;
    130             case android.R.id.home:
    131                 mListener.onActionBarHome();
    132                 return true;
    133             default:
    134                 return false;
    135         }
    136     }
    137 
    138     @Override
    139     public void onDestroyActionMode(ActionMode actionMode) {
    140         mListener = null;
    141         mSelectedConversations.clear();
    142         mHasInflated = false;
    143     }
    144 
    145     public void toggleSelect(final ConversationListData listData,
    146                              final ConversationListItemData conversationListItemData) {
    147         Assert.notNull(conversationListItemData);
    148         mBlockedSet = listData.getBlockedParticipants();
    149         final String id = conversationListItemData.getConversationId();
    150         if (mSelectedConversations.containsKey(id)) {
    151             mSelectedConversations.remove(id);
    152         } else {
    153             mSelectedConversations.put(id, new SelectedConversation(conversationListItemData));
    154         }
    155 
    156         if (mSelectedConversations.isEmpty()) {
    157             mListener.onActionBarHome();
    158         } else {
    159             updateActionIconsVisiblity();
    160         }
    161     }
    162 
    163     public boolean isSelected(final String selectedId) {
    164         return mSelectedConversations.containsKey(selectedId);
    165     }
    166 
    167     private void updateActionIconsVisiblity() {
    168         if (!mHasInflated) {
    169             return;
    170         }
    171 
    172         if (mSelectedConversations.size() == 1) {
    173             final SelectedConversation conversation = mSelectedConversations.valueAt(0);
    174             // The look up key is a key given to us by contacts app, so if we have a look up key,
    175             // we know that the participant is already in contacts.
    176             final boolean isInContacts = !TextUtils.isEmpty(conversation.participantLookupKey);
    177             mAddContactMenuItem.setVisible(!conversation.isGroup && !isInContacts);
    178             // ParticipantNormalizedDestination is always null for group conversations.
    179             final String otherParticipant = conversation.otherParticipantNormalizedDestination;
    180             mBlockMenuItem.setVisible(otherParticipant != null
    181                     && !mBlockedSet.contains(otherParticipant));
    182         } else {
    183             mBlockMenuItem.setVisible(false);
    184             mAddContactMenuItem.setVisible(false);
    185         }
    186 
    187         boolean hasCurrentlyArchived = false;
    188         boolean hasCurrentlyUnarchived = false;
    189         boolean hasCurrentlyOnNotification = false;
    190         boolean hasCurrentlyOffNotification = false;
    191         final Iterable<SelectedConversation> conversations = mSelectedConversations.values();
    192         for (final SelectedConversation conversation : conversations) {
    193             if (conversation.notificationEnabled) {
    194                 hasCurrentlyOnNotification = true;
    195             } else {
    196                 hasCurrentlyOffNotification = true;
    197             }
    198 
    199             if (conversation.isArchived) {
    200                 hasCurrentlyArchived = true;
    201             } else {
    202                 hasCurrentlyUnarchived = true;
    203             }
    204 
    205             // If we found at least one of each example we don't need to keep looping.
    206             if (hasCurrentlyOffNotification && hasCurrentlyOnNotification &&
    207                     hasCurrentlyArchived && hasCurrentlyUnarchived) {
    208                 break;
    209             }
    210         }
    211         // If we have notification off conversations we show on button, if we have notification on
    212         // conversation we show off button. We can show both if we have a mixture.
    213         mNotificationOffMenuItem.setVisible(hasCurrentlyOnNotification);
    214         mNotificationOnMenuItem.setVisible(hasCurrentlyOffNotification);
    215 
    216         mArchiveMenuItem.setVisible(hasCurrentlyUnarchived);
    217         mUnarchiveMenuItem.setVisible(hasCurrentlyArchived);
    218     }
    219 }
    220