Java tutorial
/* * Copyright 2015 OpenMarket Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package im.vector.adapters; import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.GradientDrawable; import android.support.v4.content.ContextCompat; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import org.matrix.androidsdk.MXDataHandler; import org.matrix.androidsdk.MXSession; import org.matrix.androidsdk.data.Room; import org.matrix.androidsdk.data.RoomState; import org.matrix.androidsdk.data.RoomSummary; import org.matrix.androidsdk.data.RoomTag; import org.matrix.androidsdk.rest.model.Event; import org.matrix.androidsdk.rest.model.User; import org.matrix.androidsdk.util.EventDisplay; import org.matrix.androidsdk.util.Log; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import im.vector.Matrix; import im.vector.PublicRoomsManager; import im.vector.R; import im.vector.VectorApp; import im.vector.util.RiotEventDisplay; import im.vector.util.RoomUtils; import im.vector.util.ThemeUtils; import im.vector.util.VectorUtils; /** * An adapter which can display room information. */ public class VectorRoomSummaryAdapter extends BaseExpandableListAdapter { public interface RoomEventListener { void onPreviewRoom(MXSession session, String roomId); void onRejectInvitation(MXSession session, String roomId); void onGroupCollapsedNotif(int aGroupPosition); void onGroupExpandedNotif(int aGroupPosition); } private final Context mContext; private final LayoutInflater mLayoutInflater; private final int mChildLayoutResourceId; private final int mHeaderLayoutResourceId; private final MXSession mMxSession; private ArrayList<ArrayList<RoomSummary>> mSummaryListByGroupPosition; private int mRoomByAliasGroupPosition = -1; // the user wants to join by room id or alias private int mDirectoryGroupPosition = -1; // public rooms index private int mInvitedGroupPosition = -1; // "Invited" index private int mFavouritesGroupPosition = -1;// "Favourites" index private int mNoTagGroupPosition = -1; // "Rooms" index private int mLowPriorGroupPosition = -1; // "Low Priority" index private final String DBG_CLASS_NAME; // search mode private String mSearchedPattern; // search mode set to true : display nothing if the search pattern is empty // search mode set to false : display all the known entries if the search pattern is empty private final boolean mIsSearchMode; // when set to true, avoid empty history by displaying the directory group private final boolean mDisplayDirectoryGroupWhenEmpty; // force to display the directory group private boolean mForceDirectoryGroupDisplay; // public room search private Integer mPublicRoomsCount; private Integer mMatchedPublicRoomsCount; // the listener private final RoomUtils.MoreActionListener mMoreActionListener; private final RoomEventListener mListener; // drag and drop mode private boolean mIsDragAndDropMode = false; /** * Constructor * * @param aContext the context. * @param session the linked session. * @param isSearchMode true if the adapter is in search mode * @param displayDirectoryGroupWhenEmpty true to avoid empty history * @param aChildLayoutResourceId the room child layout * @param aGroupHeaderLayoutResourceId the room section header layout * @param listener the events listener */ public VectorRoomSummaryAdapter(Context aContext, MXSession session, boolean isSearchMode, boolean displayDirectoryGroupWhenEmpty, int aChildLayoutResourceId, int aGroupHeaderLayoutResourceId, RoomEventListener listener, RoomUtils.MoreActionListener moreActionListener) { // init internal fields mContext = aContext; mLayoutInflater = LayoutInflater.from(mContext); mChildLayoutResourceId = aChildLayoutResourceId; mHeaderLayoutResourceId = aGroupHeaderLayoutResourceId; DBG_CLASS_NAME = getClass().getName(); // get the complete summary list mMxSession = session; mListener = listener; mMoreActionListener = moreActionListener; mIsSearchMode = isSearchMode; mDisplayDirectoryGroupWhenEmpty = displayDirectoryGroupWhenEmpty; } /** * Set to true to always display the directory group. * * @param forceDirectoryGroupDisplay true to always display the directory group. */ public void setForceDirectoryGroupDisplay(boolean forceDirectoryGroupDisplay) { mForceDirectoryGroupDisplay = forceDirectoryGroupDisplay; } /** * Provides the formatted timestamp to display. * null means that the timestamp text must be hidden. * * @param event the event. * @return the formatted timestamp to display. */ private String getFormattedTimestamp(Event event) { String text = AdapterUtils.tsToString(mContext, event.getOriginServerTs(), false); // don't display the today before the time String today = mContext.getString(R.string.today) + " "; if (text.startsWith(today)) { text = text.substring(today.length()); } return text; } /** * Compute the name of the group according to its position. * * @param groupPosition index of the section * @return group title corresponding to the index */ private String getGroupTitle(int groupPosition) { String retValue; if (mRoomByAliasGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_join); } else if (mDirectoryGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_directory); } else if (mFavouritesGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_favourites); } else if (mNoTagGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_conversations); } else if (mLowPriorGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_low_priority); } else if (mInvitedGroupPosition == groupPosition) { retValue = mContext.getResources().getString(R.string.room_recents_invites); } else { // unknown section retValue = "??"; } return retValue; } /** * Fullfill an array list with a pattern. * * @param list the list to fill. * @param value the pattern. * @param count the number of occurences */ private void fillList(ArrayList<RoomSummary> list, RoomSummary value, int count) { for (int i = 0; i < count; i++) { list.add(value); } } /** * Check a room name contains the searched pattern. * * @param room the room. * @return true of the pattern is found. */ private boolean isMatchedPattern(Room room) { boolean res = !mIsSearchMode; if (!TextUtils.isEmpty(mSearchedPattern)) { String roomName = VectorUtils.getRoomDisplayName(mContext, mMxSession, room); res = (!TextUtils.isEmpty(roomName) && (roomName.toLowerCase(VectorApp.getApplicationLocale()).contains(mSearchedPattern))); } return res; } /** * Tell if the group position is the join by * * @param groupPosition the group position to test. * @return true if it is room id group */ public boolean isRoomByIdGroupPosition(int groupPosition) { return (mRoomByAliasGroupPosition == groupPosition); } /** * Test if the group position is the directory one. * * @param groupPosition the group position to test. * @return true if it is directory group. */ public boolean isDirectoryGroupPosition(int groupPosition) { return (mDirectoryGroupPosition == groupPosition); } /** * @return the directory group position */ public int getDirectoryGroupPosition() { return mDirectoryGroupPosition; } /** * @return true if the directory group is displayed */ public boolean isDirectoryGroupDisplayed() { return (-1 != mDirectoryGroupPosition); } @Override public void onGroupCollapsed(int groupPosition) { super.onGroupCollapsed(groupPosition); if (null != mListener) { mListener.onGroupCollapsedNotif(groupPosition); } } @Override public void onGroupExpanded(int groupPosition) { super.onGroupExpanded(groupPosition); if (null != mListener) { mListener.onGroupExpandedNotif(groupPosition); } } /** * Build an array of RoomSummary objects organized according to the room tags (sections). * So far we have 4 sections * - the invited rooms * - the rooms with tags ROOM_TAG_FAVOURITE * - the rooms with tags ROOM_TAG_LOW_PRIORITY * - the rooms with tags ROOM_TAG_NO_TAG (displayed as "ROOMS") * The section indexes: mFavouriteSectionIndex, mNoTagSectionIndex and mFavouriteSectionIndex are * also computed in this method. * * @param aRoomSummaryCollection the complete list of RoomSummary objects * @return an array of summary lists splitted by sections */ private ArrayList<ArrayList<RoomSummary>> buildSummariesByGroups( final Collection<RoomSummary> aRoomSummaryCollection) { ArrayList<ArrayList<RoomSummary>> summaryListByGroupsRetValue = new ArrayList<>(); String roomSummaryId; // init index with default values mRoomByAliasGroupPosition = -1; mDirectoryGroupPosition = -1; mInvitedGroupPosition = -1; mFavouritesGroupPosition = -1; mNoTagGroupPosition = -1; mLowPriorGroupPosition = -1; if (null != aRoomSummaryCollection) { RoomSummary dummyRoomSummary = new RoomSummary(); // Retrieve lists of room IDs(strings) according to their tags final List<String> favouriteRoomIdList = mMxSession.roomIdsWithTag(RoomTag.ROOM_TAG_FAVOURITE); final List<String> lowPriorityRoomIdList = mMxSession.roomIdsWithTag(RoomTag.ROOM_TAG_LOW_PRIORITY); // ArrayLists allocations: will contain the RoomSummary objects deduced from roomIdsWithTag() ArrayList<RoomSummary> inviteRoomSummaryList = new ArrayList<>(); ArrayList<RoomSummary> favouriteRoomSummaryList = new ArrayList<>(favouriteRoomIdList.size()); ArrayList<RoomSummary> lowPriorityRoomSummaryList = new ArrayList<>(); ArrayList<RoomSummary> noTagRoomSummaryList = new ArrayList<>(lowPriorityRoomIdList.size()); fillList(favouriteRoomSummaryList, dummyRoomSummary, favouriteRoomIdList.size()); fillList(lowPriorityRoomSummaryList, dummyRoomSummary, lowPriorityRoomIdList.size()); // Search loop going through all the summaries: // here we translate the roomIds (Strings) to their corresponding RoomSummary objects for (RoomSummary roomSummary : aRoomSummaryCollection) { roomSummaryId = roomSummary.getRoomId(); Room room = mMxSession.getDataHandler().getStore().getRoom(roomSummaryId); // check if the room exists // the user conference rooms are not displayed. if ((null != room) && isMatchedPattern(room) && !room.isConferenceUserRoom()) { // list first the summary if (room.isInvited()) { inviteRoomSummaryList.add(roomSummary); } else { int pos; // search for each room Id in the room Id lists, retrieved from their corresponding tags pos = favouriteRoomIdList.indexOf(roomSummaryId); if (pos >= 0) { // update the favourites list // the favorites are ordered favouriteRoomSummaryList.set(pos, roomSummary); } else if ((pos = lowPriorityRoomIdList.indexOf(roomSummaryId)) >= 0) { // update the low priority list // the low priority are ordered lowPriorityRoomSummaryList.set(pos, roomSummary); } else { // default case: update the no tag list noTagRoomSummaryList.add(roomSummary); } } } else if (null == room) { Log.e(DBG_CLASS_NAME, "buildSummariesBySections " + roomSummaryId + " has no known room"); } } // Adding sections // Note the order here below: first the "invitations", "favourite", then "no tag" and then "low priority" int groupIndex = 0; // in search mode // the public rooms have a dedicated section if (mIsSearchMode || mDisplayDirectoryGroupWhenEmpty || mForceDirectoryGroupDisplay) { // detect if the pattern might a room ID or an alias if (!TextUtils.isEmpty(mSearchedPattern)) { // a room id is !XXX:server.ext // a room alias is #XXX:server.ext boolean isRoomId = false; boolean isRoomAlias = false; if (mSearchedPattern.startsWith("!")) { int sep = mSearchedPattern.indexOf(":"); if (sep > 0) { sep = mSearchedPattern.indexOf(".", sep); } isRoomId = sep > 0; } else if (mSearchedPattern.startsWith("#")) { int sep = mSearchedPattern.indexOf(":"); if (sep > 0) { sep = mSearchedPattern.indexOf(".", sep); } isRoomAlias = sep > 0; } if (isRoomId || isRoomAlias) { mRoomByAliasGroupPosition = groupIndex++; } } mDirectoryGroupPosition = groupIndex++; // create a dummy entry to keep match between section index <-> summaries list summaryListByGroupsRetValue.add(new ArrayList<RoomSummary>()); } // first the invitations if (0 != inviteRoomSummaryList.size()) { // the invitations are sorted from the older to the oldest to the more recent ones Collections.reverse(inviteRoomSummaryList); summaryListByGroupsRetValue.add(inviteRoomSummaryList); mInvitedGroupPosition = groupIndex; groupIndex++; } // favourite while (favouriteRoomSummaryList.remove(dummyRoomSummary)) ; if (0 != favouriteRoomSummaryList.size()) { summaryListByGroupsRetValue.add(favouriteRoomSummaryList); mFavouritesGroupPosition = groupIndex; // save section index groupIndex++; } // no tag if (0 != noTagRoomSummaryList.size()) { summaryListByGroupsRetValue.add(noTagRoomSummaryList); mNoTagGroupPosition = groupIndex; // save section index groupIndex++; } // low priority while (lowPriorityRoomSummaryList.remove(dummyRoomSummary)) ; if (0 != lowPriorityRoomSummaryList.size()) { summaryListByGroupsRetValue.add(lowPriorityRoomSummaryList); mLowPriorGroupPosition = groupIndex; // save section index groupIndex++; } // in avoiding empty history mode // check if there is really nothing else if (mDisplayDirectoryGroupWhenEmpty && !mForceDirectoryGroupDisplay && (groupIndex > 1)) { summaryListByGroupsRetValue.remove(mDirectoryGroupPosition); mRoomByAliasGroupPosition = -1; mDirectoryGroupPosition = -1; mInvitedGroupPosition--; mFavouritesGroupPosition--; mNoTagGroupPosition--; mLowPriorGroupPosition--; } } return summaryListByGroupsRetValue; } /** * Return the summary * * @param aGroupPosition group position * @param aChildPosition child position * @return the corresponding room summary */ public RoomSummary getRoomSummaryAt(int aGroupPosition, int aChildPosition) { return mSummaryListByGroupPosition.get(aGroupPosition).get(aChildPosition); } /** * Reset the count of the unread messages of the room set at this particular child position. * * @param aGroupPosition group position * @param aChildPosition child position * @return true if unread count reset was effective, false if unread count was yet reseted */ public boolean resetUnreadCount(int aGroupPosition, int aChildPosition) { boolean retCode = false; RoomSummary roomSummary = getRoomSummaryAt(aGroupPosition, aChildPosition); if (null != roomSummary) { Room room = this.roomFromRoomSummary(roomSummary); if (null != room) { room.sendReadReceipt(); } } return retCode; } /** * Retrieve a Room from a room summary * * @param roomSummary the room roomId to retrieve. * @return the Room. */ private Room roomFromRoomSummary(RoomSummary roomSummary) { Room roomRetValue; MXSession session; String matrixId; // sanity check if ((null == roomSummary) || (null == (matrixId = roomSummary.getMatrixId()))) { roomRetValue = null; } // get session and check if the session is active else if (null == (session = Matrix.getMXSession(mContext, matrixId)) || (!session.isAlive())) { roomRetValue = null; } else { roomRetValue = session.getDataHandler().getStore().getRoom(roomSummary.getRoomId()); } return roomRetValue; } @Override public boolean hasStableIds() { return false; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } private void refreshSummariesList() { if (null != mMxSession) { // sanity check MXDataHandler dataHandler = mMxSession.getDataHandler(); if ((null == dataHandler) || (null == dataHandler.getStore())) { Log.w(DBG_CLASS_NAME, "## refreshSummariesList(): unexpected null values - return"); return; } // update/retrieve the complete summary list ArrayList<RoomSummary> roomSummariesCompleteList = new ArrayList<>( dataHandler.getStore().getSummaries()); // define comparator logic Comparator<RoomSummary> summaryComparator = new Comparator<RoomSummary>() { public int compare(RoomSummary aLeftObj, RoomSummary aRightObj) { int retValue; long deltaTimestamp; if ((null == aLeftObj) || (null == aLeftObj.getLatestReceivedEvent())) { retValue = 1; } else if ((null == aRightObj) || (null == aRightObj.getLatestReceivedEvent())) { retValue = -1; } else if ((deltaTimestamp = aRightObj.getLatestReceivedEvent().getOriginServerTs() - aLeftObj.getLatestReceivedEvent().getOriginServerTs()) > 0) { retValue = 1; } else if (deltaTimestamp < 0) { retValue = -1; } else { retValue = 0; } return retValue; } }; Collections.sort(roomSummariesCompleteList, summaryComparator); // init data model used to be be displayed in the list view mSummaryListByGroupPosition = buildSummariesByGroups(roomSummariesCompleteList); } } @Override public void notifyDataSetChanged() { if (!mIsDragAndDropMode) { refreshSummariesList(); } super.notifyDataSetChanged(); } @Override public int getGroupCount() { if (null != mSummaryListByGroupPosition) { return mSummaryListByGroupPosition.size(); } return 0; } @Override public Object getGroup(int groupPosition) { return getGroupTitle(groupPosition); } @Override public long getGroupId(int groupPosition) { return getGroupTitle(groupPosition).hashCode(); } @Override public int getChildrenCount(int groupPosition) { // the directory section has always only one entry // same for the join by room alias or ID if ((mDirectoryGroupPosition == groupPosition) || (mRoomByAliasGroupPosition == groupPosition)) { return 1; } return mSummaryListByGroupPosition.get(groupPosition).size(); } @Override public Object getChild(int groupPosition, int childPosition) { return null; } @Override public long getChildId(int groupPosition, int childPosition) { return 0L; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (null == convertView) { convertView = this.mLayoutInflater.inflate(this.mHeaderLayoutResourceId, null); } TextView sectionNameTxtView = convertView.findViewById(R.id.heading); if (null != sectionNameTxtView) { sectionNameTxtView.setText(getGroupTitle(groupPosition)); } ImageView imageView = convertView.findViewById(R.id.heading_image); if (mIsSearchMode) { imageView.setVisibility(View.GONE); } else { if (isExpanded) { imageView.setImageResource(R.drawable.ic_material_expand_less_black); } else { imageView.setImageResource(R.drawable.ic_material_expand_more_black); } } return convertView; } /** * Apply a rounded (sides) rectangle as a background to the view provided in aTargetView. * * @param aTargetView view to apply the background * @param aBackgroundColor background colour */ private static void setUnreadBackground(View aTargetView, int aBackgroundColor) { if (null != aTargetView) { GradientDrawable shape = new GradientDrawable(); shape.setShape(GradientDrawable.RECTANGLE); shape.setCornerRadius(100); shape.setColor(aBackgroundColor); aTargetView.setBackground(shape); } } /** * Compute the View that should be used to render the child, * given its position and its groups position */ @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // sanity check if (null == mSummaryListByGroupPosition) { return null; } if (convertView == null) { convertView = mLayoutInflater.inflate(mChildLayoutResourceId, parent, false); } if (!mMxSession.isAlive()) { return convertView; } int roomNameBlack = ThemeUtils.getColor(mContext, R.attr.riot_primary_text_color); int fushiaColor = ContextCompat.getColor(mContext, R.color.vector_fuchsia_color); int vectorDefaultTimeStampColor = ThemeUtils.getColor(mContext, R.attr.default_text_light_color); int vectorGreenColor = ContextCompat.getColor(mContext, R.color.vector_green_color); int vectorSilverColor = ContextCompat.getColor(mContext, R.color.vector_silver_color); // retrieve the UI items ImageView avatarImageView = convertView.findViewById(R.id.room_avatar); TextView roomNameTxtView = convertView.findViewById(R.id.roomSummaryAdapter_roomName); TextView roomMsgTxtView = convertView.findViewById(R.id.roomSummaryAdapter_roomMessage); View bingUnreadMsgView = convertView.findViewById(R.id.bing_indicator_unread_message); TextView timestampTxtView = convertView.findViewById(R.id.roomSummaryAdapter_ts); View separatorView = convertView.findViewById(R.id.recents_separator); View separatorGroupView = convertView.findViewById(R.id.recents_groups_separator_line); final View actionView = convertView.findViewById(R.id.roomSummaryAdapter_action); final ImageView actionImageView = convertView.findViewById(R.id.roomSummaryAdapter_action_image); TextView unreadCountTxtView = convertView.findViewById(R.id.roomSummaryAdapter_unread_count); View directChatIcon = convertView.findViewById(R.id.room_avatar_direct_chat_icon); View encryptedIcon = convertView.findViewById(R.id.room_avatar_encrypted_icon); View invitationView = convertView.findViewById(R.id.recents_groups_invitation_group); Button preViewButton = convertView.findViewById(R.id.recents_invite_preview_button); Button rejectButton = convertView.findViewById(R.id.recents_invite_reject_button); View showMoreView = convertView.findViewById(R.id.roomSummaryAdapter_show_more_layout); View actionClickArea = convertView.findViewById(R.id.roomSummaryAdapter_action_click_area); // directory management if ((mDirectoryGroupPosition == groupPosition) || (mRoomByAliasGroupPosition == groupPosition)) { // some items are show bingUnreadMsgView.setVisibility(View.INVISIBLE); timestampTxtView.setVisibility(View.GONE); actionImageView.setVisibility(View.GONE); invitationView.setVisibility(View.GONE); separatorView.setVisibility(View.GONE); separatorGroupView.setVisibility(View.VISIBLE); showMoreView.setVisibility(View.VISIBLE); actionClickArea.setVisibility(View.GONE); unreadCountTxtView.setVisibility(View.GONE); directChatIcon.setVisibility(View.GONE); encryptedIcon.setVisibility(View.GONE); if (mDirectoryGroupPosition == groupPosition) { roomNameTxtView.setText(mContext.getResources().getString(R.string.directory_search_results_title)); if (!TextUtils.isEmpty(mSearchedPattern)) { if (null == mMatchedPublicRoomsCount) { roomMsgTxtView .setText(mContext.getResources().getString(R.string.directory_searching_title)); } else { String value = mMatchedPublicRoomsCount.toString(); if (mMatchedPublicRoomsCount >= PublicRoomsManager.PUBLIC_ROOMS_LIMIT) { value = "> " + PublicRoomsManager.PUBLIC_ROOMS_LIMIT; } roomMsgTxtView.setText( mContext.getResources().getQuantityString(R.plurals.directory_search_rooms_for, mMatchedPublicRoomsCount, value, mSearchedPattern)); } } else { if (null == mPublicRoomsCount) { roomMsgTxtView.setText(null); } else { roomMsgTxtView.setText(mContext.getResources().getQuantityString( R.plurals.directory_search_rooms, mPublicRoomsCount, mPublicRoomsCount)); } } avatarImageView.setImageBitmap(VectorUtils.getAvatar(avatarImageView.getContext(), VectorUtils.getAvatarColor(null), null, true)); } else { roomNameTxtView.setText(mSearchedPattern); roomMsgTxtView.setText(""); avatarImageView.setImageBitmap(VectorUtils.getAvatar(avatarImageView.getContext(), VectorUtils.getAvatarColor(null), "@", true)); } return convertView; } showMoreView.setVisibility(View.GONE); RoomSummary childRoomSummary = mSummaryListByGroupPosition.get(groupPosition).get(childPosition); final Room childRoom = mMxSession.getDataHandler().getStore().getRoom(childRoomSummary.getRoomId()); int unreadMsgCount = childRoomSummary.getUnreadEventsCount(); int highlightCount = 0; int notificationCount = 0; if (null != childRoom) { highlightCount = childRoom.getHighlightCount(); notificationCount = childRoom.getNotificationCount(); if (mMxSession.getDataHandler().getBingRulesManager().isRoomMentionOnly(childRoom.getRoomId())) { notificationCount = highlightCount; } } // get last message to be displayed CharSequence lastMsgToDisplay = getChildMessageToDisplay(childRoomSummary); // display the room avatar final String roomName = VectorUtils.getRoomDisplayName(mContext, mMxSession, childRoom); VectorUtils.loadRoomAvatar(mContext, mMxSession, avatarImageView, childRoom); // display the room name roomNameTxtView.setText(roomName); roomNameTxtView.setTextColor(roomNameBlack); roomNameTxtView.setTypeface(null, (0 != unreadMsgCount) ? Typeface.BOLD : Typeface.NORMAL); // display the last message roomMsgTxtView.setText(lastMsgToDisplay); // set the timestamp timestampTxtView.setText(getFormattedTimestamp(childRoomSummary.getLatestReceivedEvent())); timestampTxtView.setTextColor(vectorDefaultTimeStampColor); timestampTxtView.setTypeface(null, Typeface.NORMAL); // set bing view background colour int bingUnreadColor; if (0 != highlightCount) { bingUnreadColor = fushiaColor; } else if (0 != notificationCount) { bingUnreadColor = vectorGreenColor; } else if (0 != unreadMsgCount) { bingUnreadColor = vectorSilverColor; } else { bingUnreadColor = Color.TRANSPARENT; } bingUnreadMsgView.setBackgroundColor(bingUnreadColor); // display the unread badge counter if ((0 != notificationCount)) { unreadCountTxtView.setVisibility(View.VISIBLE); unreadCountTxtView.setText(String.valueOf(notificationCount)); unreadCountTxtView.setTypeface(null, Typeface.BOLD); setUnreadBackground(unreadCountTxtView, bingUnreadColor); } else { unreadCountTxtView.setVisibility(View.GONE); } // some items are shown boolean isInvited = false; if (null != childRoom) { isInvited = childRoom.isInvited(); } if (null != childRoom) { directChatIcon.setVisibility( RoomUtils.isDirectChat(mMxSession, childRoom.getRoomId()) ? View.VISIBLE : View.GONE); encryptedIcon.setVisibility(childRoom.isEncrypted() ? View.VISIBLE : View.GONE); } else { directChatIcon.setVisibility(View.GONE); encryptedIcon.setVisibility(View.GONE); } bingUnreadMsgView.setVisibility(isInvited ? View.INVISIBLE : View.VISIBLE); invitationView.setVisibility(isInvited ? View.VISIBLE : View.GONE); final String fRoomId = childRoomSummary.getRoomId(); if (isInvited) { actionClickArea.setVisibility(View.GONE); preViewButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != mListener) { mListener.onPreviewRoom(mMxSession, fRoomId); } } }); rejectButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (null != mListener) { mListener.onRejectInvitation(mMxSession, fRoomId); } } }); // display an exclamation mark like the webclient unreadCountTxtView.setVisibility(View.VISIBLE); unreadCountTxtView.setText("!"); unreadCountTxtView.setTypeface(null, Typeface.BOLD); setUnreadBackground(unreadCountTxtView, fushiaColor); timestampTxtView.setVisibility(View.GONE); actionImageView.setVisibility(View.GONE); } else { final boolean isFavorite = groupPosition == mFavouritesGroupPosition; final boolean isLowPrior = groupPosition == mLowPriorGroupPosition; actionClickArea.setVisibility(View.VISIBLE); actionClickArea.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { RoomUtils.displayPopupMenu(mContext, mMxSession, childRoom, actionView, isFavorite, isLowPrior, mMoreActionListener); } }); timestampTxtView.setVisibility(mIsSearchMode ? View.INVISIBLE : View.VISIBLE); actionImageView.setVisibility(mIsSearchMode ? View.INVISIBLE : View.VISIBLE); } separatorView.setVisibility(isLastChild ? View.GONE : View.VISIBLE); separatorGroupView .setVisibility((isLastChild && ((groupPosition + 1) < getGroupCount())) ? View.VISIBLE : View.GONE); return convertView; } /** * Get the displayable name of the user whose ID is passed in aUserId. * * @param aMatrixId matrix ID * @param aUserId user ID * @return the user display name */ private String getMemberDisplayNameFromUserId(String aMatrixId, String aUserId) { String displayNameRetValue; MXSession session; if ((null == aMatrixId) || (null == aUserId)) { displayNameRetValue = null; } else if ((null == (session = Matrix.getMXSession(mContext, aMatrixId))) || (!session.isAlive())) { displayNameRetValue = null; } else { User user = session.getDataHandler().getStore().getUser(aUserId); if ((null != user) && !TextUtils.isEmpty(user.displayname)) { displayNameRetValue = user.displayname; } else { displayNameRetValue = aUserId; } } return displayNameRetValue; } /** * Retrieves the text to display for a RoomSummary. * * @param aChildRoomSummary the roomSummary. * @return the text to display. */ private CharSequence getChildMessageToDisplay(RoomSummary aChildRoomSummary) { CharSequence messageToDisplayRetValue = null; EventDisplay eventDisplay; if (null != aChildRoomSummary) { if (aChildRoomSummary.getLatestReceivedEvent() != null) { eventDisplay = new RiotEventDisplay(mContext, aChildRoomSummary.getLatestReceivedEvent(), aChildRoomSummary.getLatestRoomState()); eventDisplay.setPrependMessagesWithAuthor(true); messageToDisplayRetValue = eventDisplay .getTextualDisplay(ThemeUtils.getColor(mContext, R.attr.riot_primary_text_color)); } // check if this is an invite if (aChildRoomSummary.isInvited() && (null != aChildRoomSummary.getInviterUserId())) { RoomState latestRoomState = aChildRoomSummary.getLatestRoomState(); String inviterUserId = aChildRoomSummary.getInviterUserId(); String myName = aChildRoomSummary.getMatrixId(); if (null != latestRoomState) { inviterUserId = latestRoomState.getMemberName(inviterUserId); myName = latestRoomState.getMemberName(myName); } else { inviterUserId = getMemberDisplayNameFromUserId(aChildRoomSummary.getMatrixId(), inviterUserId); myName = getMemberDisplayNameFromUserId(aChildRoomSummary.getMatrixId(), myName); } if (TextUtils.equals(mMxSession.getMyUserId(), aChildRoomSummary.getMatrixId())) { messageToDisplayRetValue = mContext .getString(org.matrix.androidsdk.R.string.notice_room_invite_you, inviterUserId); } else { messageToDisplayRetValue = mContext.getString(org.matrix.androidsdk.R.string.notice_room_invite, inviterUserId, myName); } } } return messageToDisplayRetValue; } /** * Defines the new searched pattern * * @param pattern the new searched pattern */ public void setSearchPattern(String pattern) { String trimmedPattern = pattern; if (null != pattern) { trimmedPattern = pattern.trim().toLowerCase(VectorApp.getApplicationLocale()); trimmedPattern = TextUtils.getTrimmedLength(trimmedPattern) == 0 ? null : trimmedPattern; } if (!TextUtils.equals(trimmedPattern, mSearchedPattern)) { mSearchedPattern = trimmedPattern; mMatchedPublicRoomsCount = null; // refresh the layout this.notifyDataSetChanged(); } } /** * @return the searched pattern */ public String getSearchedPattern() { return mSearchedPattern; } /** * Update the public rooms list count and refresh the display. * * @param roomsListCount the new public rooms count */ public void setPublicRoomsCount(Integer roomsListCount) { if (roomsListCount != mPublicRoomsCount) { mPublicRoomsCount = roomsListCount; super.notifyDataSetChanged(); } } /** * @return the matched public rooms count */ public int getMatchedPublicRoomsCount() { return (null == mMatchedPublicRoomsCount) ? 0 : mMatchedPublicRoomsCount; } /** * Update the matched public rooms list count and refresh the display. * * @param roomsListCount the new public rooms count */ public void setMatchedPublicRoomsCount(Integer roomsListCount) { if (roomsListCount != mMatchedPublicRoomsCount) { mMatchedPublicRoomsCount = roomsListCount; super.notifyDataSetChanged(); } } /** * @return true if the adapter is in drag and drop mode. */ public boolean isInDragAndDropMode() { return mIsDragAndDropMode; } /** * Set the drag and drop mode i.e. there is no automatic room summaries lists refresh. * * @param isDragAndDropMode the drag and drop mode */ public void setIsDragAndDropMode(boolean isDragAndDropMode) { mIsDragAndDropMode = isDragAndDropMode; } /** * Move a childview in the roomSummary dir tree * * @param fromGroupPosition the group position origin * @param fromChildPosition the child position origin * @param toGroupPosition the group position destination * @param toChildPosition the child position destination */ public void moveChildView(int fromGroupPosition, int fromChildPosition, int toGroupPosition, int toChildPosition) { ArrayList<RoomSummary> fromList = mSummaryListByGroupPosition.get(fromGroupPosition); ArrayList<RoomSummary> toList = mSummaryListByGroupPosition.get(toGroupPosition); RoomSummary summary = fromList.get(fromChildPosition); fromList.remove(fromChildPosition); if (toChildPosition >= toList.size()) { toList.add(summary); } else { toList.add(toChildPosition, summary); } } /** * Tell if a group position is the invited one. * * @param groupPos the proup position. * @return true if the group position is the invited one. */ public boolean isInvitedRoomPosition(int groupPos) { return mInvitedGroupPosition == groupPos; } /** * Tell if a group position is the favourite one. * * @param groupPos the proup position. * @return true if the group position is the favourite one. */ public boolean isFavouriteRoomPosition(int groupPos) { return mFavouritesGroupPosition == groupPos; } /** * Tell if a group position is the no tag one. * * @param groupPos the proup position. * @return true if the group position is the no tag one. */ public boolean isNoTagRoomPosition(int groupPos) { return mNoTagGroupPosition == groupPos; } /** * Tell if a group position is the low priority one. * * @param groupPos the proup position. * @return true if the group position is the low priority one. */ public boolean isLowPriorityRoomPosition(int groupPos) { return mLowPriorGroupPosition == groupPos; } }