/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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.xabber.android.ui.adapter.contactlist;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Handler;
import android.support.v7.widget.RecyclerView;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import com.xabber.android.R;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.account.AccountItem;
import com.xabber.android.data.account.AccountManager;
import com.xabber.android.data.account.CommonState;
import com.xabber.android.data.account.StatusMode;
import com.xabber.android.data.entity.AccountJid;
import com.xabber.android.data.entity.BaseEntity;
import com.xabber.android.data.entity.UserJid;
import com.xabber.android.data.extension.avatar.AvatarManager;
import com.xabber.android.data.extension.blocking.BlockingManager;
import com.xabber.android.data.extension.muc.MUCManager;
import com.xabber.android.data.extension.muc.RoomChat;
import com.xabber.android.data.extension.muc.RoomContact;
import com.xabber.android.data.log.LogManager;
import com.xabber.android.data.message.AbstractChat;
import com.xabber.android.data.message.ChatContact;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.android.data.roster.GroupManager;
import com.xabber.android.data.roster.RosterContact;
import com.xabber.android.data.roster.RosterManager;
import com.xabber.android.data.roster.ShowOfflineMode;
import com.xabber.android.ui.activity.AccountActivity;
import com.xabber.android.ui.activity.ManagedActivity;
import com.xabber.android.ui.adapter.ComparatorByChat;
import com.xabber.android.ui.adapter.UpdatableAdapter;
import com.xabber.android.ui.helper.ContextMenuHelper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
/**
* Adapter for contact list in the main activity.
*
* @author alexander.ivanov
*/
public class ContactListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements Runnable, Filterable, UpdatableAdapter, ContactListItemViewHolder.ContactClickListener,
AccountGroupViewHolder.AccountGroupClickListener, GroupViewHolder.GroupClickListener {
private static final String LOG_TAG = ContactListAdapter.class.getSimpleName();
/**
* Number of milliseconds between lazy refreshes.
*/
private static final long REFRESH_INTERVAL = 1000;
/**
* View type used for contact items.
*/
private static final int TYPE_CONTACT = 0;
/**
* View type used for groups and accounts expanders.
*/
private static final int TYPE_GROUP = 1;
private static final int TYPE_ACCOUNT = 2;
private static final int TYPE_ACCOUNT_TOP_SEPARATOR = 3;
private static final int TYPE_ACCOUNT_BOTTOM_SEPARATOR = 4;
private final ArrayList<Object> baseEntities = new ArrayList<>();
/**
* Handler for deferred refresh.
*/
private final Handler handler;
/**
* Lock for refresh requests.
*/
private final Object refreshLock;
/**
* Layout inflater
*/
private final LayoutInflater layoutInflater;
private final ManagedActivity activity;
private final int[] accountSubgroupColors;
private final int activeChatsColor;
private final ContactItemInflater contactItemInflater;
private final int accountElevation;
protected Locale locale = Locale.getDefault();
private AccountGroupViewHolder.AccountGroupClickListener accountGroupClickListener;
/**
* Whether refresh was requested.
*/
private boolean refreshRequested;
/**
* Whether refresh is in progress.
*/
private boolean refreshInProgress;
/**
* Minimal time when next refresh can be executed.
*/
private Date nextRefresh;
/**
* Contact filter.
*/
private ContactFilter contactFilter;
/**
* Filter string. Can be <code>null</code> if filter is disabled.
*/
private String filterString;
private final ContactListAdapterListener listener;
private boolean hasActiveChats = false;
private int[] accountGroupColors;
public ContactListAdapter(ManagedActivity activity, ContactListAdapterListener listener) {
this.activity = activity;
this.accountGroupClickListener = null;
layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resources resources = activity.getResources();
accountGroupColors = resources.getIntArray(getThemeResource(R.attr.contact_list_account_group_background));
accountSubgroupColors = resources.getIntArray(getThemeResource(R.attr.contact_list_subgroup_background));
TypedValue typedValue = new TypedValue();
TypedArray a = activity.obtainStyledAttributes(typedValue.data, new int[] { R.attr.contact_list_active_chat_subgroup_background });
activeChatsColor = a.getColor(0, 0);
a.recycle();
contactItemInflater = new ContactItemInflater(activity);
accountElevation = activity.getResources().getDimensionPixelSize(R.dimen.account_group_elevation);
this.listener = listener;
handler = new Handler();
refreshLock = new Object();
refreshRequested = false;
refreshInProgress = false;
nextRefresh = new Date();
}
/**
* Requests refresh in some time in future.
*/
public void refreshRequest() {
synchronized (refreshLock) {
if (refreshRequested) {
return;
}
if (refreshInProgress) {
refreshRequested = true;
} else {
long delay = nextRefresh.getTime() - new Date().getTime();
handler.postDelayed(this, delay > 0 ? delay : 0);
}
}
}
/**
* Remove refresh requests.
*/
public void removeRefreshRequests() {
synchronized (refreshLock) {
refreshRequested = false;
refreshInProgress = false;
handler.removeCallbacks(this);
}
}
@Override
public void onChange() {
synchronized (refreshLock) {
refreshRequested = false;
refreshInProgress = true;
handler.removeCallbacks(this);
}
final Collection<RosterContact> allRosterContacts = RosterManager.getInstance().getAllContacts();
Map<AccountJid, Collection<UserJid>> blockedContacts = new TreeMap<>();
for (AccountJid account : AccountManager.getInstance().getEnabledAccounts()) {
blockedContacts.put(account, BlockingManager.getInstance().getBlockedContacts(account));
}
final Collection<RosterContact> rosterContacts = new ArrayList<>();
for (RosterContact contact : allRosterContacts) {
if (blockedContacts.containsKey(contact.getAccount())) {
if (!blockedContacts.get(contact.getAccount()).contains(contact.getUser())) {
rosterContacts.add(contact);
}
}
}
final boolean showOffline = SettingsManager.contactsShowOffline();
final boolean showGroups = SettingsManager.contactsShowGroups();
final boolean showEmptyGroups = SettingsManager.contactsShowEmptyGroups();
final boolean showActiveChats = SettingsManager.contactsShowActiveChats();
final boolean stayActiveChats = SettingsManager.contactsStayActiveChats();
final boolean showAccounts = SettingsManager.contactsShowAccounts();
final Comparator<AbstractContact> comparator = SettingsManager.contactsOrder();
final CommonState commonState = AccountManager.getInstance().getCommonState();
final AccountJid selectedAccount = AccountManager.getInstance().getSelectedAccount();
/**
* Groups.
*/
final Map<String, GroupConfiguration> groups;
/**
* Contacts.
*/
final List<AbstractContact> contacts;
/**
* List of active chats.
*/
final GroupConfiguration activeChats;
/**
* Whether there is at least one contact.
*/
boolean hasContacts = false;
/**
* Whether there is at least one visible contact.
*/
boolean hasVisibleContacts = false;
final Map<AccountJid, AccountConfiguration> accounts = new TreeMap<>();
for (AccountJid account : AccountManager.getInstance().getEnabledAccounts()) {
accounts.put(account, null);
}
/**
* List of rooms and active chats grouped by users inside accounts.
*/
final Map<AccountJid, Map<UserJid, AbstractChat>> abstractChats = new TreeMap<>();
for (AbstractChat abstractChat : MessageManager.getInstance().getChats()) {
if ((abstractChat instanceof RoomChat || abstractChat.isActive())
&& accounts.containsKey(abstractChat.getAccount())) {
final AccountJid account = abstractChat.getAccount();
Map<UserJid, AbstractChat> users = abstractChats.get(account);
if (users == null) {
users = new TreeMap<>();
abstractChats.put(account, users);
}
users.put(abstractChat.getUser(), abstractChat);
}
}
if (filterString == null) {
// Create arrays.
if (showAccounts) {
groups = null;
contacts = null;
for (Entry<AccountJid, AccountConfiguration> entry : accounts.entrySet()) {
entry.setValue(new AccountConfiguration(entry.getKey(),
GroupManager.IS_ACCOUNT, GroupManager.getInstance()));
}
} else {
if (showGroups) {
groups = new TreeMap<>();
contacts = null;
} else {
groups = null;
contacts = new ArrayList<>();
}
}
if (showActiveChats) {
activeChats = new GroupConfiguration(GroupManager.NO_ACCOUNT,
GroupManager.ACTIVE_CHATS, GroupManager.getInstance());
} else {
activeChats = null;
}
// Build structure.
for (RosterContact rosterContact : rosterContacts) {
if (!rosterContact.isEnabled()) {
continue;
}
hasContacts = true;
final boolean online = rosterContact.getStatusMode().isOnline();
final AccountJid account = rosterContact.getAccount();
final Map<UserJid, AbstractChat> users = abstractChats.get(account);
final AbstractChat abstractChat;
if (users == null) {
abstractChat = null;
} else {
abstractChat = users.remove(rosterContact.getUser());
}
if (showActiveChats && abstractChat != null && abstractChat.isActive()) {
activeChats.setNotEmpty();
hasVisibleContacts = true;
if (activeChats.isExpanded()) {
activeChats.addAbstractContact(rosterContact);
}
activeChats.increment(online);
if (!stayActiveChats || (!showAccounts && !showGroups)) {
continue;
}
}
if (selectedAccount != null && !selectedAccount.equals(account)) {
continue;
}
if (ContactListGroupUtils.addContact(rosterContact, online, accounts, groups,
contacts, showAccounts, showGroups, showOffline)) {
hasVisibleContacts = true;
}
}
for (Map<UserJid, AbstractChat> users : abstractChats.values())
for (AbstractChat abstractChat : users.values()) {
final AbstractContact abstractContact;
if (abstractChat instanceof RoomChat) {
abstractContact = new RoomContact((RoomChat) abstractChat);
} else {
abstractContact = new ChatContact(abstractChat);
}
if (showActiveChats && abstractChat.isActive()) {
activeChats.setNotEmpty();
hasVisibleContacts = true;
if (activeChats.isExpanded()) {
activeChats.addAbstractContact(abstractContact);
}
activeChats.increment(false);
if (!stayActiveChats || (!showAccounts && !showGroups)) {
continue;
}
}
if (selectedAccount != null && !selectedAccount.equals(abstractChat.getAccount())) {
continue;
}
final String group;
final boolean online;
if (abstractChat instanceof RoomChat) {
group = GroupManager.IS_ROOM;
online = abstractContact.getStatusMode().isOnline();
} else if (MUCManager.getInstance().isMucPrivateChat(abstractChat.getAccount(), abstractChat.getUser())) {
group = GroupManager.IS_ROOM;
online = abstractContact.getStatusMode().isOnline();
} else {
group = GroupManager.NO_GROUP;
online = false;
}
hasVisibleContacts = true;
ContactListGroupUtils.addContact(abstractContact, group, online, accounts, groups, contacts,
showAccounts, showGroups);
}
hasActiveChats = activeChats != null && activeChats.getTotal() > 0;
// Remove empty groups, sort and apply structure.
baseEntities.clear();
if (hasVisibleContacts) {
if (showActiveChats) {
if (!activeChats.isEmpty()) {
if (showAccounts || showGroups) {
baseEntities.add(activeChats);
}
activeChats.sortAbstractContacts(ComparatorByChat.COMPARATOR_BY_CHAT);
baseEntities.addAll(activeChats.getAbstractContacts());
}
}
if (showAccounts) {
boolean isFirst = baseEntities.isEmpty();
for (AccountConfiguration rosterAccount : accounts.values()) {
if (isFirst) {
isFirst = false;
} else {
baseEntities.add(new AccountTopSeparator(null, null));
}
baseEntities.add(rosterAccount);
if (showGroups) {
if (rosterAccount.isExpanded()) {
for (GroupConfiguration rosterConfiguration : rosterAccount
.getSortedGroupConfigurations()) {
if (showEmptyGroups || !rosterConfiguration.isEmpty()) {
baseEntities.add(rosterConfiguration);
rosterConfiguration.sortAbstractContacts(comparator);
baseEntities.addAll(rosterConfiguration.getAbstractContacts());
}
}
}
} else {
rosterAccount.sortAbstractContacts(comparator);
baseEntities.addAll(rosterAccount.getAbstractContacts());
}
if (rosterAccount.getTotal() > 0 && !rosterAccount.isExpanded()) {
baseEntities.add(new AccountBottomSeparator(rosterAccount.getAccount(), null));
}
}
} else {
if (showGroups) {
for (GroupConfiguration rosterConfiguration : groups.values()) {
if (showEmptyGroups || !rosterConfiguration.isEmpty()) {
baseEntities.add(rosterConfiguration);
rosterConfiguration.sortAbstractContacts(comparator);
baseEntities.addAll(rosterConfiguration.getAbstractContacts());
}
}
} else {
Collections.sort(contacts, comparator);
baseEntities.addAll(contacts);
}
}
}
} else { // Search
final ArrayList<AbstractContact> baseEntities = getSearchResults(rosterContacts, comparator, abstractChats);
this.baseEntities.clear();
this.baseEntities.addAll(baseEntities);
hasVisibleContacts = baseEntities.size() > 0;
}
notifyDataSetChanged();
listener.onContactListChanged(commonState, hasContacts, hasVisibleContacts, filterString != null);
synchronized (refreshLock) {
nextRefresh = new Date(new Date().getTime() + REFRESH_INTERVAL);
refreshInProgress = false;
handler.removeCallbacks(this); // Just to be sure.
if (refreshRequested) {
handler.postDelayed(this, REFRESH_INTERVAL);
}
}
}
private ArrayList<AbstractContact> getSearchResults(Collection<RosterContact> rosterContacts,
Comparator<AbstractContact> comparator,
Map<AccountJid, Map<UserJid, AbstractChat>> abstractChats) {
final ArrayList<AbstractContact> baseEntities = new ArrayList<>();
// Build structure.
for (RosterContact rosterContact : rosterContacts) {
if (!rosterContact.isEnabled()) {
continue;
}
final AccountJid account = rosterContact.getAccount();
final Map<UserJid, AbstractChat> users = abstractChats.get(account);
if (users != null) {
users.remove(rosterContact.getUser());
}
if (rosterContact.getName().toLowerCase(locale).contains(filterString)) {
baseEntities.add(rosterContact);
}
}
for (Map<UserJid, AbstractChat> users : abstractChats.values()) {
for (AbstractChat abstractChat : users.values()) {
final AbstractContact abstractContact;
if (abstractChat instanceof RoomChat) {
abstractContact = new RoomContact((RoomChat) abstractChat);
} else {
abstractContact = new ChatContact(abstractChat);
}
if (abstractContact.getName().toLowerCase(locale).contains(filterString)) {
baseEntities.add(abstractContact);
}
}
}
Collections.sort(baseEntities, comparator);
return baseEntities;
}
@Override
public void run() {
onChange();
}
private int getThemeResource(int themeResourceId) {
TypedValue typedValue = new TypedValue();
TypedArray a = activity.obtainStyledAttributes(typedValue.data, new int[] {themeResourceId});
final int accountGroupColorsResourceId = a.getResourceId(0, 0);
a.recycle();
return accountGroupColorsResourceId;
}
@Override
public int getItemCount() {
return baseEntities.size();
}
public Object getItem(int position) {
return baseEntities.get(position);
}
@Override
public int getItemViewType(int position) {
Object object = getItem(position);
if (object instanceof AbstractContact) {
return TYPE_CONTACT;
} else if (object instanceof AccountConfiguration) {
return TYPE_ACCOUNT;
} else if (object instanceof GroupConfiguration) {
return TYPE_GROUP;
} else if (object instanceof AccountTopSeparator) {
return TYPE_ACCOUNT_TOP_SEPARATOR;
} else if (object instanceof AccountBottomSeparator) {
return TYPE_ACCOUNT_BOTTOM_SEPARATOR;
} else {
throw new IllegalStateException();
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_CONTACT:
return new ContactListItemViewHolder(layoutInflater
.inflate(R.layout.item_contact, parent, false), this);
case TYPE_GROUP:
return new GroupViewHolder(layoutInflater
.inflate(R.layout.item_base_group, parent, false), this);
case TYPE_ACCOUNT:
return new AccountGroupViewHolder(layoutInflater
.inflate(R.layout.contact_list_account_group_item, parent, false), this);
case TYPE_ACCOUNT_TOP_SEPARATOR:
return new TopSeparatorHolder(layoutInflater
.inflate(R.layout.account_group_item_top_separator, parent, false));
case TYPE_ACCOUNT_BOTTOM_SEPARATOR:
return new BottomSeparatorHolder(layoutInflater
.inflate(R.layout.account_group_item_bottom_separator, parent, false));
default:
throw new IllegalStateException();
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final int viewType = getItemViewType(position);
final Object item = getItem(position);
switch (viewType) {
case TYPE_CONTACT:
contactItemInflater.bindViewHolder((ContactListItemViewHolder) holder, (AbstractContact) item);
break;
case TYPE_ACCOUNT:
bindAccount((AccountGroupViewHolder)holder, (AccountConfiguration) item);
break;
case TYPE_GROUP:
bindGroup((GroupViewHolder) holder, (GroupConfiguration) item);
break;
case TYPE_ACCOUNT_TOP_SEPARATOR:
break;
case TYPE_ACCOUNT_BOTTOM_SEPARATOR:
bindBottomSeparator((BottomSeparatorHolder) holder,
(AccountBottomSeparator) item);
break;
default:
throw new IllegalStateException();
}
}
private void bindBottomSeparator(BottomSeparatorHolder holder, AccountBottomSeparator accountBottomSeparator) {
final int level = AccountManager.getInstance().getColorLevel(accountBottomSeparator.getAccount());
holder.bottomLayer.setBackgroundDrawable(new ColorDrawable(accountSubgroupColors[level]));
holder.topLayer.setBackgroundDrawable(new ColorDrawable(accountSubgroupColors[level]));
AccountItem accountItem = AccountManager.getInstance().getAccount(accountBottomSeparator.getAccount());
StatusMode statusMode = null;
if (accountItem != null) {
statusMode = accountItem.getDisplayStatusMode();
}
if (statusMode == StatusMode.unavailable || statusMode == StatusMode.connection) {
holder.offlineShadowBottom.setVisibility(View.VISIBLE);
holder.offlineShadowTop.setVisibility(View.VISIBLE);
} else {
holder.offlineShadowBottom.setVisibility(View.GONE);
holder.offlineShadowTop.setVisibility(View.GONE);
}
}
private void bindAccount(AccountGroupViewHolder viewHolder, AccountConfiguration configuration) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
viewHolder.itemView.setElevation(accountElevation);
}
final AccountJid account = configuration.getAccount();
final int level = AccountManager.getInstance().getColorLevel(account);
viewHolder.itemView.setBackgroundColor(accountGroupColors[level]);
viewHolder.name.setText(GroupManager.getInstance().getGroupName(account, configuration.getGroup()));
viewHolder.smallRightText.setText(configuration.getOnline() + "/" + configuration.getTotal());
AccountItem accountItem = AccountManager.getInstance().getAccount(account);
if (accountItem == null) {
LogManager.e(LOG_TAG, "accountItem is null " + account);
return;
}
String statusText = accountItem.getStatusText().trim();
if (statusText.isEmpty()) {
statusText = activity.getString(accountItem.getDisplayStatusMode().getStringID());
}
viewHolder.secondLineMessage.setText(statusText);
if (SettingsManager.contactsShowAvatars()) {
viewHolder.avatar.setVisibility(View.VISIBLE);
viewHolder.avatar.setImageDrawable(AvatarManager.getInstance().getAccountAvatar(account));
} else {
viewHolder.avatar.setVisibility(View.GONE);
}
viewHolder.statusIcon.setImageLevel(accountItem.getDisplayStatusMode().getStatusLevel());
ShowOfflineMode showOfflineMode = configuration.getShowOfflineMode();
if (showOfflineMode == ShowOfflineMode.normal) {
if (SettingsManager.contactsShowOffline()) {
showOfflineMode = ShowOfflineMode.always;
} else {
showOfflineMode = ShowOfflineMode.never;
}
}
viewHolder.smallRightIcon.setImageLevel(showOfflineMode.ordinal());
StatusMode statusMode = accountItem.getDisplayStatusMode();
if (statusMode == StatusMode.unavailable || statusMode == StatusMode.connection) {
viewHolder.offlineShadow.setVisibility(View.VISIBLE);
} else {
viewHolder.offlineShadow.setVisibility(View.GONE);
}
}
private void bindGroup(GroupViewHolder viewHolder, GroupConfiguration configuration) {
final int level = AccountManager.getInstance().getColorLevel(configuration.getAccount());
final String name = GroupManager.getInstance().getGroupName(configuration.getAccount(), configuration.getGroup());
viewHolder.indicator.setImageLevel(configuration.isExpanded() ? 1 : 0);
viewHolder.groupOfflineIndicator.setImageLevel(configuration.getShowOfflineMode().ordinal());
int color;
viewHolder.groupOfflineIndicator.setVisibility(View.GONE);
viewHolder.offlineShadow.setVisibility(View.GONE);
if (configuration.getGroup().equals(GroupManager.ACTIVE_CHATS)) {
color = activeChatsColor;
viewHolder.name.setText(name);
} else {
viewHolder.name.setText(String.format("%s (%d/%d)", name, configuration.getOnline(), configuration.getTotal()));
color = accountSubgroupColors[level];
viewHolder.groupOfflineIndicator.setVisibility(View.VISIBLE);
AccountItem accountItem = AccountManager.getInstance().getAccount(configuration.getAccount());
if (accountItem != null) {
StatusMode statusMode = accountItem.getDisplayStatusMode();
if (statusMode == StatusMode.unavailable || statusMode == StatusMode.connection) {
viewHolder.offlineShadow.setVisibility(View.VISIBLE);
}
}
}
viewHolder.itemView.setBackgroundDrawable(new ColorDrawable(color));
}
@Override
public void onContactClick(int adapterPosition) {
if (adapterPosition >= 0 && adapterPosition < baseEntities.size()) {
listener.onContactClick((AbstractContact) baseEntities.get(adapterPosition));
}
}
@Override
public void onContactAvatarClick(int adapterPosition) {
contactItemInflater.onAvatarClick((BaseEntity) getItem(adapterPosition));
}
@Override
public void onContactCreateContextMenu(int adapterPosition, ContextMenu menu) {
AbstractContact abstractContact = (AbstractContact) getItem(adapterPosition);
ContextMenuHelper.createContactContextMenu(activity, this, abstractContact, menu);
}
@Override
public void onAccountAvatarClick(int adapterPosition) {
activity.startActivity(AccountActivity.createIntent(activity,
((AccountConfiguration)getItem(adapterPosition)).getAccount()));
}
@Override
public void onAccountMenuClick(int adapterPosition, View view) {
listener.onAccountMenuClick(
((AccountConfiguration)baseEntities.get(adapterPosition)).getAccount(), view);
}
@Override
public void onAccountGroupClick(int adapterPosition) {
toggleGroupExpand(adapterPosition);
}
@Override
public void onAccountGroupCreateContextMenu(int adapterPosition, ContextMenu menu) {
AccountConfiguration accountConfiguration = (AccountConfiguration) getItem(adapterPosition);
ContextMenuHelper.createAccountContextMenu(activity, this, accountConfiguration.getAccount(), menu);
}
@Override
public void onGroupClick(int adapterPosition) {
toggleGroupExpand(adapterPosition);
}
@Override
public void onGroupCreateContextMenu(int adapterPosition, ContextMenu menu) {
GroupConfiguration groupConfiguration = (GroupConfiguration) getItem(adapterPosition);
ContextMenuHelper.createGroupContextMenu(activity, this,
groupConfiguration.getAccount(), groupConfiguration.getGroup(), menu);
}
private void toggleGroupExpand(int adapterPosition) {
GroupConfiguration groupConfiguration = (GroupConfiguration) getItem(adapterPosition);
GroupManager.getInstance().setExpanded(groupConfiguration.getAccount(), groupConfiguration.getGroup(),
!groupConfiguration.isExpanded());
onChange();
}
/**
* Listener for contact list appearance changes.
*
* @author alexander.ivanov
*/
public interface ContactListAdapterListener {
void onContactListChanged(CommonState commonState, boolean hasContacts,
boolean hasVisibleContacts, boolean isFilterEnabled);
void onContactClick(AbstractContact contact);
void onAccountMenuClick(AccountJid accountJid, View view);
}
@Override
public Filter getFilter() {
if (contactFilter == null) {
contactFilter = new ContactFilter();
}
return contactFilter;
}
private class ContactFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (constraint == null || constraint.length() == 0) {
filterString = null;
} else {
filterString = constraint.toString().toLowerCase(locale);
}
onChange();
}
}
public boolean isHasActiveChats() {
return hasActiveChats;
}
}