im.vector.activity.HomeActivity.java Source code

Java tutorial

Introduction

Here is the source code for im.vector.activity.HomeActivity.java

Source

/*
 * Copyright 2014 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.activity;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.Toast;

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.fragments.IconAndTextDialogFragment;
import org.matrix.androidsdk.listeners.MXEventListener;
import org.matrix.androidsdk.rest.callback.ApiCallback;
import org.matrix.androidsdk.rest.callback.SimpleApiCallback;
import org.matrix.androidsdk.rest.client.LoginRestClient;
import org.matrix.androidsdk.rest.model.Event;
import org.matrix.androidsdk.rest.model.MatrixError;
import org.matrix.androidsdk.rest.model.PublicRoom;
import org.matrix.androidsdk.rest.model.RoomMember;
import org.matrix.androidsdk.rest.model.login.Credentials;
import org.matrix.androidsdk.util.EventUtils;
import org.matrix.androidsdk.util.JsonUtils;
import im.vector.Matrix;
import im.vector.MyPresenceManager;
import im.vector.R;
import im.vector.ViewedRoomTracker;
import im.vector.adapters.ConsoleRoomSummaryAdapter;
import im.vector.adapters.DrawerAdapter;
import im.vector.fragments.AccountsSelectionDialogFragment;
import im.vector.fragments.ContactsListDialogFragment;
import im.vector.fragments.RoomCreationDialogFragment;
import im.vector.gcm.GcmRegistrationManager;
import im.vector.util.RageShake;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * Displays the main screen of the app, with rooms the user has joined and the ability to create
 * new rooms.
 */
public class HomeActivity extends MXCActionBarActivity {

    private static final String LOG_TAG = "HomeActivity";

    private ExpandableListView mMyRoomList = null;

    private static final String PUBLIC_ROOMS_LIST_LIST = "PUBLIC_ROOMS_LIST_LIST";

    private static final String TAG_FRAGMENT_CONTACTS_LIST = "org.matrix.console.HomeActivity.TAG_FRAGMENT_CONTACTS_LIST";
    private static final String TAG_FRAGMENT_CREATE_ROOM_DIALOG = "org.matrix.console.HomeActivity.TAG_FRAGMENT_CREATE_ROOM_DIALOG";

    private static final String TAG_FRAGMENT_ROOM_OPTIONS = "org.matrix.console.HomeActivity.TAG_FRAGMENT_ROOM_OPTIONS";

    public static final String EXTRA_JUMP_TO_ROOM_ID = "org.matrix.console.HomeActivity.EXTRA_JUMP_TO_ROOM_ID";
    public static final String EXTRA_JUMP_MATRIX_ID = "org.matrix.console.HomeActivity.EXTRA_JUMP_MATRIX_ID";
    public static final String EXTRA_ROOM_INTENT = "org.matrix.console.HomeActivity.EXTRA_ROOM_INTENT";

    private ArrayList<String> mHomeServerNames = null;
    private ArrayList<List<PublicRoom>> mPublicRoomsListList = null;

    private boolean mIsPaused = false;

    private ArrayList<Integer> mExpandedGroups = null;

    private String mAutomaticallyOpenedRoomId = null;
    private String mAutomaticallyOpenedMatrixId = null;
    private Intent mOpenedRoomIntent = null;

    private boolean refreshOnChunkEnd = false;

    // sliding menu
    private final Integer[] mSlideMenuTitleIds = new Integer[] {
            //R.string.action_search_contact,
            //R.string.action_search_room,
            R.string.create_room, R.string.join_room,
            // R.string.action_mark_all_as_read,
            R.string.action_add_account, R.string.action_remove_account, R.string.action_settings,
            R.string.action_disconnect, R.string.action_logout, R.string.send_bug_report, };

    // sliding menu
    private final Integer[] mSlideMenuResourceIds = new Integer[] {
            //R.drawable.ic_material_search, // R.string.action_search_contact,
            //R.drawable.ic_material_find_in_page, // R.string.action_search_room,
            R.drawable.vector_create, //R.string.create_room,
            R.drawable.ic_material_group, // R.string.join_room,
            //R.drawable.ic_material_done_all, // R.string.action_mark_all_as_read,
            R.drawable.ic_material_person_add, // R.string.action_add_account,
            R.drawable.ic_material_remove_circle_outline, // R.string.action_remove_account,
            R.drawable.vector_settings, //  R.string.action_settings,
            R.drawable.ic_material_clear, // R.string.action_disconnect,
            R.drawable.ic_material_exit_to_app, // R.string.action_logout,
            R.drawable.ic_material_bug_report, // R.string.send_bug_report,
    };

    private HashMap<MXSession, MXEventListener> mListenersBySession = new HashMap<MXSession, MXEventListener>();
    private ConsoleRoomSummaryAdapter mAdapter;
    private EditText mSearchRoomEditText;

    private void refreshPublicRoomsList() {
        refreshPublicRoomsList(new ArrayList<MXSession>(Matrix.getInstance(getApplicationContext()).getSessions()),
                new ArrayList<String>(), 0, new ArrayList<List<PublicRoom>>());
    }

    private void refreshPublicRoomsList(final ArrayList<MXSession> sessions,
            final ArrayList<String> checkedHomeServers, final int index,
            final ArrayList<List<PublicRoom>> publicRoomsListList) {
        // sanity checks
        if ((null == sessions) || (index >= sessions.size())) {
            mAdapter.setPublicRoomsList(publicRoomsListList, checkedHomeServers);
            mPublicRoomsListList = publicRoomsListList;
            mHomeServerNames = checkedHomeServers;
            return;
        }

        final MXSession session = sessions.get(index);
        final String homeServer = session.getCredentials().homeServer;

        // the home server has already been checked ?
        if (checkedHomeServers.indexOf(homeServer) >= 0) {
            // jump to the next session
            refreshPublicRoomsList(sessions, checkedHomeServers, index + 1, publicRoomsListList);
        } else {
            // use any session to get the public rooms list
            session.getEventsApiClient().loadPublicRooms(new SimpleApiCallback<List<PublicRoom>>(this) {
                @Override
                public void onSuccess(List<PublicRoom> publicRooms) {
                    checkedHomeServers.add(homeServer);
                    publicRoomsListList.add(publicRooms);

                    // jump to the next session
                    refreshPublicRoomsList(sessions, checkedHomeServers, index + 1, publicRoomsListList);
                }
            });
        }
    }

    private void joinPublicRoom(final String homeServerURL, final PublicRoom publicRoom) {

        Collection<MXSession> sessions = Matrix.getMXSessions(HomeActivity.this);
        ArrayList<MXSession> matchedSessions = new ArrayList<MXSession>();

        for (MXSession session : sessions) {
            if (session.getCredentials().homeServer.equals(homeServerURL)) {
                matchedSessions.add(session);
            }
        }

        if (matchedSessions.size() == 1) {
            CommonActivityUtils.goToRoomPage(matchedSessions.get(0), publicRoom.roomId, HomeActivity.this, null);
        } else if (matchedSessions.size() > 1) {

            FragmentManager fm = getSupportFragmentManager();

            AccountsSelectionDialogFragment fragment = (AccountsSelectionDialogFragment) fm
                    .findFragmentByTag(TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
            if (fragment != null) {
                fragment.dismissAllowingStateLoss();
            }

            fragment = AccountsSelectionDialogFragment.newInstance(matchedSessions);

            fragment.setListener(new AccountsSelectionDialogFragment.AccountsListener() {
                @Override
                public void onSelected(final MXSession session) {

                    HomeActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            CommonActivityUtils.goToRoomPage(session, publicRoom.roomId, HomeActivity.this, null);
                        }
                    });
                }
            });

            fragment.show(fm, TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);

        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        if (CommonActivityUtils.shouldRestartApp()) {
            Log.e(LOG_TAG, "Restart the application.");
            CommonActivityUtils.restartApp(this);
        }

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        mMyRoomList = (ExpandableListView) findViewById(R.id.listView_myRooms);
        // the chevron is managed in the header view
        mMyRoomList.setGroupIndicator(null);
        mAdapter = new ConsoleRoomSummaryAdapter(this, Matrix.getMXSessions(this), R.layout.adapter_item_my_rooms,
                R.layout.adapter_room_section_header);

        if (null != savedInstanceState) {
            if (savedInstanceState.containsKey(PUBLIC_ROOMS_LIST_LIST)) {
                Serializable map = savedInstanceState.getSerializable(PUBLIC_ROOMS_LIST_LIST);

                if (null != map) {
                    HashMap<String, List<PublicRoom>> hash = (HashMap<String, List<PublicRoom>>) map;
                    mPublicRoomsListList = new ArrayList<List<PublicRoom>>(hash.values());
                    mHomeServerNames = new ArrayList<>(hash.keySet());
                }
            }
        }

        final Intent intent = getIntent();
        if (intent.hasExtra(EXTRA_JUMP_TO_ROOM_ID)) {
            mAutomaticallyOpenedRoomId = intent.getStringExtra(EXTRA_JUMP_TO_ROOM_ID);
        }

        if (intent.hasExtra(EXTRA_JUMP_MATRIX_ID)) {
            mAutomaticallyOpenedMatrixId = intent.getStringExtra(EXTRA_JUMP_MATRIX_ID);
        }

        if (intent.hasExtra(EXTRA_ROOM_INTENT)) {
            mOpenedRoomIntent = intent.getParcelableExtra(EXTRA_ROOM_INTENT);
        }

        String action = intent.getAction();
        String type = intent.getType();

        // send files from external application
        if ((Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) && type != null) {
            this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    CommonActivityUtils.sendFilesTo(HomeActivity.this, intent);
                }
            });
        }

        mMyRoomList.setAdapter(mAdapter);
        Collection<MXSession> sessions = Matrix.getMXSessions(HomeActivity.this);

        // check if  there is some valid session
        // the home activity could be relaunched after an application crash
        // so, reload the sessions before displaying the hidtory
        if (sessions.size() == 0) {
            Log.e(LOG_TAG, "Weird : onCreate : no session");

            if (null != Matrix.getInstance(this).getDefaultSession()) {
                Log.e(LOG_TAG, "No loaded session : reload them");
                startActivity(new Intent(HomeActivity.this, SplashActivity.class));
                HomeActivity.this.finish();
                return;
            }
        }

        for (MXSession session : sessions) {
            addSessionListener(session);
        }

        mMyRoomList.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
            @Override
            public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition,
                    long id) {

                if (mAdapter.isRecentsGroupIndex(groupPosition)) {
                    String roomId = null;
                    MXSession session = null;

                    RoomSummary roomSummary = mAdapter.getRoomSummaryAt(groupPosition, childPosition);
                    session = Matrix.getInstance(HomeActivity.this).getSession(roomSummary.getMatrixId());

                    roomId = roomSummary.getRoomId();
                    Room room = session.getDataHandler().getRoom(roomId);
                    // cannot join a leaving room
                    if ((null == room) || room.isLeaving()) {
                        roomId = null;
                    }

                    if (mAdapter.resetUnreadCount(groupPosition, roomId)) {
                        session.getDataHandler().getStore().flushSummary(roomSummary);
                    }

                    if (null != roomId) {
                        CommonActivityUtils.goToRoomPage(session, roomId, HomeActivity.this, null);
                    }

                } else if (mAdapter.isPublicsGroupIndex(groupPosition)) {
                    joinPublicRoom(mAdapter.getHomeServerURLAt(groupPosition),
                            mAdapter.getPublicRoomAt(groupPosition, childPosition));
                }

                return true;
            }
        });

        mMyRoomList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {

                if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                    long packedPos = ((ExpandableListView) parent).getExpandableListPosition(position);
                    final int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos);

                    if (mAdapter.isRecentsGroupIndex(groupPosition)) {
                        final int childPosition = ExpandableListView.getPackedPositionChild(packedPos);

                        FragmentManager fm = HomeActivity.this.getSupportFragmentManager();
                        IconAndTextDialogFragment fragment = (IconAndTextDialogFragment) fm
                                .findFragmentByTag(TAG_FRAGMENT_ROOM_OPTIONS);

                        if (fragment != null) {
                            fragment.dismissAllowingStateLoss();
                        }

                        final Integer[] lIcons = new Integer[] { R.drawable.ic_material_exit_to_app };
                        final Integer[] lTexts = new Integer[] { R.string.action_leave };

                        fragment = IconAndTextDialogFragment.newInstance(lIcons, lTexts, null,
                                HomeActivity.this.getResources().getColor(R.color.vector_title_color));
                        fragment.setOnClickListener(new IconAndTextDialogFragment.OnItemClickListener() {
                            @Override
                            public void onItemClick(IconAndTextDialogFragment dialogFragment, int position) {
                                Integer selectedVal = lTexts[position];

                                if (selectedVal == R.string.action_leave) {
                                    HomeActivity.this.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            final RoomSummary roomSummary = mAdapter.getRoomSummaryAt(groupPosition,
                                                    childPosition);
                                            final MXSession roomSession = Matrix.getInstance(HomeActivity.this)
                                                    .getSession(roomSummary.getMatrixId());

                                            String roomId = roomSummary.getRoomId();
                                            Room room = roomSession.getDataHandler().getRoom(roomId);

                                            if (null != room) {
                                                room.leave(new SimpleApiCallback<Void>(HomeActivity.this) {
                                                    @Override
                                                    public void onSuccess(Void info) {
                                                        mAdapter.removeRoomSummary(groupPosition, roomSummary);
                                                        mAdapter.notifyDataSetChanged();
                                                    }
                                                });
                                            }
                                        }
                                    });
                                }
                            }
                        });

                        fragment.show(fm, TAG_FRAGMENT_ROOM_OPTIONS);

                        return true;
                    }
                }

                return false;
            }
        });

        mMyRoomList.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener() {
            @Override
            public void onGroupExpand(int groupPosition) {
                if (mAdapter.isPublicsGroupIndex(groupPosition)) {
                    refreshPublicRoomsList();
                }
            }
        });

        mMyRoomList.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
            @Override
            public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
                return mAdapter.getGroupCount() < 2;
            }
        });

        mSearchRoomEditText = (EditText) this.findViewById(R.id.editText_search_room);
        mSearchRoomEditText.addTextChangedListener(new TextWatcher() {
            public void afterTextChanged(android.text.Editable s) {
                mAdapter.setSearchedPattern(s.toString());
                mMyRoomList.smoothScrollToPosition(0);
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }
        });
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Always call the superclass so it can save the view hierarchy state
        super.onSaveInstanceState(savedInstanceState);

        if (null != mPublicRoomsListList) {
            HashMap<String, List<PublicRoom>> hash = new HashMap<String, List<PublicRoom>>();

            for (int index = 0; index < mHomeServerNames.size(); index++) {
                hash.put(mHomeServerNames.get(index), mPublicRoomsListList.get(index));
            }

            savedInstanceState.putSerializable(PUBLIC_ROOMS_LIST_LIST, hash);
        }
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
    }

    public ArrayList<Integer> getExpandedGroupsList() {
        ArrayList<Integer> expList = new ArrayList<Integer>();

        int groupCount = mMyRoomList.getExpandableListAdapter().getGroupCount();

        for (int groupindex = 0; groupindex < groupCount; groupindex++) {
            if (mMyRoomList.isGroupExpanded(groupindex)) {
                expList.add(groupindex);
            }
        }

        return expList;
    }

    public void expandGroupIndexes(ArrayList<Integer> indexesList) {
        if (null == indexesList) {
            expandAllGroups();
        } else {

            int groupCount = mMyRoomList.getExpandableListAdapter().getGroupCount();

            for (Integer group : indexesList) {
                // check bounds else it could trigger weird UI effect (a list section is duplicated).
                if (group < groupCount) {
                    mMyRoomList.expandGroup(group);
                }
            }
        }
    }

    private void expandAllGroups() {
        final int groupCount = mMyRoomList.getExpandableListAdapter().getGroupCount();

        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
            mMyRoomList.expandGroup(groupIndex);
        }
    }

    private void collapseAllGroups() {
        final int groupCount = mMyRoomList.getExpandableListAdapter().getGroupCount();

        for (int groupIndex = 0; groupIndex < groupCount; groupIndex++) {
            mMyRoomList.collapseGroup(groupIndex);
        }
    }

    private void toggleSearchButton() {
        if (mSearchRoomEditText.getVisibility() == View.GONE) {
            mSearchRoomEditText.setVisibility(View.VISIBLE);

            // need to collapse/expand the groups to avoid invalid refreshes
            collapseAllGroups();
            mAdapter.setDisplayAllGroups(true);
            expandAllGroups();
        } else {
            // need to collapse/expand the groups to avoid invalid refreshes
            collapseAllGroups();
            mAdapter.setDisplayAllGroups(false);
            expandAllGroups();

            mSearchRoomEditText.setVisibility(View.GONE);

            expandAllGroups();

            // force to hide the keyboard
            mSearchRoomEditText.postDelayed(new Runnable() {
                public void run() {
                    InputMethodManager keyboard = (InputMethodManager) getSystemService(
                            getApplication().INPUT_METHOD_SERVICE);
                    keyboard.hideSoftInputFromWindow(mSearchRoomEditText.getWindowToken(), 0);
                }
            }, 200);
        }

        mSearchRoomEditText.setText("");
    }

    /**
     * Add a MXEventListener to the session listeners.
     * @param session the sessions.
     */
    private void addSessionListener(final MXSession session) {
        MXEventListener listener = new MXEventListener() {
            private boolean mInitialSyncComplete = false;

            @Override
            public void onPresencesSyncComplete() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.notifyDataSetChanged();
                    }
                });
            }

            @Override
            public void onInitialSyncComplete() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mInitialSyncComplete = true;

                        Collection<RoomSummary> summaries = session.getDataHandler().getStore().getSummaries();

                        Log.e(LOG_TAG, ">>> onInitialSyncComplete : summaries " + summaries.size());

                        for (RoomSummary summary : summaries) {
                            addSummary(summary);
                        }

                        // highlighted public rooms
                        mAdapter.highlightRoom("Matrix HQ");
                        mAdapter.highlightRoom("#matrix:matrix.org");
                        mAdapter.highlightRoom("#matrix-dev:matrix.org");
                        mAdapter.highlightRoom("#matrix-fr:matrix.org");

                        mAdapter.setPublicRoomsList(mPublicRoomsListList, mHomeServerNames);
                        mAdapter.sortSummaries();
                        mAdapter.notifyDataSetChanged();

                        expandAllGroups();

                        // load the public load in background
                        // done onResume
                        //refreshPublicRoomsList();
                    }
                });
            }

            @Override
            public void onRoomInitialSyncComplete(final String roomId) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.sortSummaries();
                        mAdapter.notifyDataSetChanged();
                    }
                });
            }

            @Override
            public void onRoomInternalUpdate(String roomId) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mAdapter.sortSummaries();
                        mAdapter.notifyDataSetChanged();
                    }
                });
            }

            @Override
            public void onLiveEventsChunkProcessed() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (!mIsPaused && refreshOnChunkEnd) {
                            mAdapter.sortSummaries();
                            mAdapter.notifyDataSetChanged();
                        }

                        refreshOnChunkEnd = false;
                    }
                });
            }

            @Override
            public void onLiveEvent(final Event event, final RoomState roomState) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if ((event.roomId != null) && isDisplayableEvent(event)) {
                            List<MXSession> sessions = new ArrayList<MXSession>(
                                    Matrix.getMXSessions(HomeActivity.this));
                            int section = sessions.indexOf(session);
                            String matrixId = session.getCredentials().userId;

                            mAdapter.setLatestEvent(section, event, roomState);

                            RoomSummary summary = mAdapter.getSummaryByRoomId(section, event.roomId);

                            if (summary == null) {
                                // ROOM_CREATE events will be sent during initial sync. We want to ignore them
                                // until the initial sync is done (that is, only refresh the list when there
                                // are new rooms created AFTER we have synced).
                                if (mInitialSyncComplete) {
                                    if (Event.EVENT_TYPE_STATE_ROOM_CREATE.equals(event.type)) {
                                        addNewRoom(event.roomId);
                                    } else if (Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(event.type)) {
                                        RoomMember member = JsonUtils.toRoomMember(event.content);

                                        // add the room summary if the user has
                                        if ((RoomMember.MEMBERSHIP_INVITE.equals(member.membership)
                                                || RoomMember.MEMBERSHIP_JOIN.equals(member.membership))
                                                && event.stateKey.equals(matrixId)) {
                                            // we were invited to a new room.
                                            addNewRoom(event.roomId);
                                        }
                                    }
                                }
                            }

                            // If we've left the room, remove it from the list
                            else if (mInitialSyncComplete
                                    && Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(event.type)) {
                                if (!(session.getDataHandler().doesRoomExist(event.roomId))
                                        || isMembershipInRoom(RoomMember.MEMBERSHIP_LEAVE, matrixId, summary)) {
                                    mAdapter.removeRoomSummary(section, summary);
                                }
                            }
                            // Watch for potential room name changes
                            else if (Event.EVENT_TYPE_STATE_ROOM_NAME.equals(event.type)
                                    || Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(event.type)
                                    || Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(event.type)) {
                                summary.setName(session.getDataHandler().getRoom(event.roomId).getName(matrixId));
                            }

                            ViewedRoomTracker rTracker = ViewedRoomTracker.getInstance();
                            String viewedRoomId = rTracker.getViewedRoomId();
                            String fromMatrixId = rTracker.getMatrixId();

                            // If we're not currently viewing this room or not sent by myself, increment the unread count
                            if ((!event.roomId.equals(viewedRoomId) || !matrixId.equals(fromMatrixId))
                                    && !event.userId.equals(matrixId)) {
                                if (null != summary) {
                                    summary.setHighlighted(
                                            summary.isHighlighted() || EventUtils.shouldHighlight(session, event));
                                }
                            }

                            refreshOnChunkEnd = true;
                        }
                    }
                });
            }

            // White list of displayable events
            private boolean isDisplayableEvent(Event event) {
                return Event.EVENT_TYPE_MESSAGE.equals(event.type)
                        || Event.EVENT_TYPE_STATE_ROOM_MEMBER.equals(event.type)
                        || Event.EVENT_TYPE_STATE_ROOM_CREATE.equals(event.type)
                        || Event.EVENT_TYPE_STATE_ROOM_NAME.equals(event.type)
                        || Event.EVENT_TYPE_STATE_ROOM_ALIASES.equals(event.type)
                        || Event.EVENT_TYPE_STATE_ROOM_TOPIC.equals(event.type);
            }

            private void addNewRoom(String roomId) {
                RoomSummary summary = session.getDataHandler().getStore().getSummary(roomId);
                addSummary(summary);
                mAdapter.sortSummaries();
            }

            private boolean isMembershipInRoom(String membership, String selfUserId, RoomSummary summary) {
                Room room = session.getDataHandler().getStore().getRoom(summary.getRoomId());

                if (null != room) {
                    Collection<RoomMember> members = room.getMembers();

                    for (RoomMember member : members) {
                        if (membership.equals(member.membership) && selfUserId.equals(member.getUserId())) {
                            return true;
                        }
                    }
                }
                return false;
            }

            private void addSummary(RoomSummary summary) {
                String selfUserId = session.getCredentials().userId;

                if (summary.isInvited()) {
                    Room room = session.getDataHandler().getStore().getRoom(summary.getRoomId());

                    // display the room name instead of "Room invitation"
                    // at least, you know who invited you
                    if (null != room) {
                        summary.setName(room.getName(session.getCredentials().userId));
                    } else if (null == summary.getRoomName()) {
                        summary.setName(getString(R.string.summary_invitation));
                    }
                }

                // only add summaries to rooms we have not left.
                if (!isMembershipInRoom(RoomMember.MEMBERSHIP_LEAVE, selfUserId, summary)) {
                    List<MXSession> sessions = new ArrayList<MXSession>(Matrix.getMXSessions(HomeActivity.this));
                    int section = sessions.indexOf(session);

                    mAdapter.addRoomSummary(section, summary);
                }
            }
        };

        session.getDataHandler().addListener(listener);
        mListenersBySession.put(session, listener);
    }

    /**
     * Remove the MXEventListener to the session listeners.
     * @param session the sessions.
     */
    private void removeSessionListener(final MXSession session) {
        if (mListenersBySession.containsKey(session)) {
            session.getDataHandler().removeListener(mListenersBySession.get(session));
            mListenersBySession.remove(session);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Collection<MXSession> sessions = Matrix.getInstance(this).getSessions();

        for (MXSession session : sessions) {
            removeSessionListener(session);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mExpandedGroups = getExpandedGroupsList();
        mIsPaused = true;
    }

    private void refreshSlidingList() {
        // adjust the sliding menu entries
        ArrayList<Integer> slideMenuTitleIds = new ArrayList<Integer>(Arrays.asList(mSlideMenuTitleIds));
        ArrayList<Integer> slideMenuResourceIds = new ArrayList<Integer>(Arrays.asList(mSlideMenuResourceIds));

        Matrix matrix = Matrix.getInstance(this);

        // only one account, do not offer to remove it
        if (matrix.getSessions().size() == 1) {

            int pos = slideMenuTitleIds.indexOf(R.string.action_remove_account);

            if (pos >= 0) {
                slideMenuTitleIds.remove(pos);
                slideMenuResourceIds.remove(pos);
            }
        }

        GcmRegistrationManager gcmManager = Matrix.getInstance(this).getSharedGcmRegistrationManager();

        // hide the disconnect when GCM is enabled.
        if ((null != gcmManager) && gcmManager.useGCM()) {
            int pos = slideMenuTitleIds.indexOf(R.string.action_disconnect);

            if (pos >= 0) {
                slideMenuTitleIds.remove(pos);
                slideMenuResourceIds.remove(pos);
            }
        }

        // apply the updated sliding list
        Integer[] slideMenuTitleIds2 = new Integer[slideMenuTitleIds.size()];
        Integer[] slideMenuResourceIds2 = new Integer[slideMenuTitleIds.size()];
        addSlidingMenu(slideMenuResourceIds.toArray(slideMenuResourceIds2),
                slideMenuTitleIds.toArray(slideMenuTitleIds2), true);
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyPresenceManager.createPresenceManager(this, Matrix.getInstance(this).getSessions());
        MyPresenceManager.advertiseAllOnline();
        mIsPaused = false;

        // some unsent messages could have been added
        // it does not trigger any live event.
        // So, it is safer to sort the messages when debackgrounding
        mAdapter.sortSummaries();
        // expand/collapse to force th group refresh
        collapseAllGroups();
        // all the groups must be displayed during a search
        mAdapter.setDisplayAllGroups(mSearchRoomEditText.getVisibility() == View.VISIBLE);
        mAdapter.notifyDataSetChanged();

        // expand previously expanded groups.
        // to restore the same UX
        expandGroupIndexes(mExpandedGroups);

        if (null != mAutomaticallyOpenedRoomId) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    CommonActivityUtils.goToRoomPage(mAutomaticallyOpenedMatrixId,
                            HomeActivity.this.mAutomaticallyOpenedRoomId, HomeActivity.this, mOpenedRoomIntent);
                    HomeActivity.this.mAutomaticallyOpenedRoomId = null;
                    HomeActivity.this.mAutomaticallyOpenedMatrixId = null;
                    HomeActivity.this.mOpenedRoomIntent = null;
                }
            });
        }

        refreshSlidingList();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if (intent.hasExtra(EXTRA_JUMP_TO_ROOM_ID)) {
            mAutomaticallyOpenedRoomId = intent.getStringExtra(EXTRA_JUMP_TO_ROOM_ID);
        }

        if (intent.hasExtra(EXTRA_JUMP_MATRIX_ID)) {
            mAutomaticallyOpenedMatrixId = intent.getStringExtra(EXTRA_JUMP_MATRIX_ID);
        }

        if (intent.hasExtra(EXTRA_ROOM_INTENT)) {
            mOpenedRoomIntent = intent.getParcelableExtra(EXTRA_ROOM_INTENT);
        }
    }

    @Override
    protected void selectDrawItem(int position) {
        // Highlight the selected item, update the title, and close the drawer
        mDrawerList.setItemChecked(position, true);

        final int id = ((DrawerAdapter.Entry) (mDrawerList.getAdapter().getItem(position))).mIconResourceId;

        this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (id == R.drawable.ic_material_search) {
                    toggleSearchContacts();
                } else if (id == R.drawable.ic_material_find_in_page) {
                    toggleSearchButton();
                } else if (id == R.drawable.vector_create) {
                    createRoom();
                } else if (id == R.drawable.ic_material_group) {
                    joinRoomByName();
                } else if (id == R.drawable.ic_material_done_all) {
                    markAllMessagesAsRead();
                } else if (id == R.drawable.vector_settings) {
                    HomeActivity.this.startActivity(new Intent(HomeActivity.this, SettingsActivity.class));
                } else if (id == R.drawable.ic_material_clear) {
                    CommonActivityUtils.disconnect(HomeActivity.this);
                } else if (id == R.drawable.ic_material_bug_report) {
                    RageShake.getInstance().sendBugReport();
                } else if (id == R.drawable.ic_material_exit_to_app) {
                    CommonActivityUtils.logout(HomeActivity.this);
                } else if (id == R.drawable.ic_material_person_add) {
                    HomeActivity.this.addAccount();
                } else if (id == R.drawable.ic_material_remove_circle_outline) {
                    HomeActivity.this.removeAccount();
                }
            }
        });

        mDrawerLayout.closeDrawer(mDrawerList);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_SEARCH)) {
            toggleSearchButton();
            return true;
        }

        if ((keyCode == KeyEvent.KEYCODE_MENU)) {
            HomeActivity.this.startActivity(new Intent(HomeActivity.this, SettingsActivity.class));
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.home, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.ic_action_search_contact) {
            toggleSearchContacts();
        } else if (id == R.id.ic_action_search_room) {
            toggleSearchButton();
        } else if (id == R.id.ic_action_mark_all_as_read) {
            markAllMessagesAsRead();
        }

        return super.onOptionsItemSelected(item);
    }

    private void toggleSearchContacts() {
        FragmentManager fm = getSupportFragmentManager();

        ContactsListDialogFragment fragment = (ContactsListDialogFragment) fm
                .findFragmentByTag(TAG_FRAGMENT_CONTACTS_LIST);
        if (fragment != null) {
            fragment.dismissAllowingStateLoss();
        }
        fragment = ContactsListDialogFragment.newInstance();
        fragment.show(fm, TAG_FRAGMENT_CONTACTS_LIST);
    }

    private void joinRoomByName() {
        if (Matrix.getMXSessions(this).size() == 1) {
            joinRoomByName(Matrix.getMXSession(this, null));
        } else {
            FragmentManager fm = getSupportFragmentManager();

            AccountsSelectionDialogFragment fragment = (AccountsSelectionDialogFragment) fm
                    .findFragmentByTag(TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
            if (fragment != null) {
                fragment.dismissAllowingStateLoss();
            }

            fragment = AccountsSelectionDialogFragment.newInstance(Matrix.getMXSessions(getApplicationContext()));

            fragment.setListener(new AccountsSelectionDialogFragment.AccountsListener() {
                @Override
                public void onSelected(final MXSession session) {

                    HomeActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            HomeActivity.this.joinRoomByName(session);
                        }
                    });
                }
            });

            fragment.show(fm, TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
        }
    }

    private void joinRoomByName(final MXSession session) {
        AlertDialog alert = CommonActivityUtils.createEditTextAlert(this, getString(R.string.join_room_title),
                getString(R.string.join_room_hint), null, new CommonActivityUtils.OnSubmitListener() {
                    @Override
                    public void onSubmit(String text) {
                        session.joinRoom(text, new ApiCallback<String>() {
                            @Override
                            public void onSuccess(String roomId) {
                                if (null != roomId) {
                                    CommonActivityUtils.goToRoomPage((MXSession) null, roomId, HomeActivity.this,
                                            null);
                                }
                            }

                            @Override
                            public void onNetworkError(Exception e) {
                                Toast.makeText(HomeActivity.this, getString(R.string.network_error),
                                        Toast.LENGTH_LONG).show();
                            }

                            @Override
                            public void onMatrixError(MatrixError e) {
                                Toast.makeText(HomeActivity.this, e.error, Toast.LENGTH_LONG).show();
                            }

                            @Override
                            public void onUnexpectedError(Exception e) {
                                Toast.makeText(HomeActivity.this, e.getLocalizedMessage(), Toast.LENGTH_LONG)
                                        .show();

                            }
                        });
                    }

                    @Override
                    public void onCancelled() {
                    }
                });
        alert.show();
    }

    private void createRoom() {
        if (Matrix.getMXSessions(this).size() == 1) {
            // use the default session
            createRoom(Matrix.getMXSession(this, null));
        } else {
            FragmentManager fm = getSupportFragmentManager();

            AccountsSelectionDialogFragment fragment = (AccountsSelectionDialogFragment) fm
                    .findFragmentByTag(TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
            if (fragment != null) {
                fragment.dismissAllowingStateLoss();
            }

            fragment = AccountsSelectionDialogFragment.newInstance(Matrix.getMXSessions(getApplicationContext()));

            fragment.setListener(new AccountsSelectionDialogFragment.AccountsListener() {
                @Override
                public void onSelected(final MXSession session) {

                    HomeActivity.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            HomeActivity.this.createRoom(session);
                        }
                    });
                }
            });

            fragment.show(fm, TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
        }
    }

    private void createRoom(MXSession session) {
        FragmentManager fm = getSupportFragmentManager();

        RoomCreationDialogFragment fragment = (RoomCreationDialogFragment) fm
                .findFragmentByTag(TAG_FRAGMENT_CREATE_ROOM_DIALOG);
        if (fragment != null) {
            fragment.dismissAllowingStateLoss();
        }
        fragment = RoomCreationDialogFragment.newInstance(session);
        fragment.show(fm, TAG_FRAGMENT_CREATE_ROOM_DIALOG);
    }

    private void markAllMessagesAsRead() {
        // flush the summaries
        ArrayList<MXSession> sessions = new ArrayList<MXSession>(Matrix.getMXSessions(HomeActivity.this));
        ;
        for (int index = 0; index < sessions.size(); index++) {
            MXSession session = sessions.get(index);

            // flush only if there is an update
            if (mAdapter.resetUnreadCounts(index)) {
                session.getDataHandler().getStore().flushSummaries();
            }
        }

        mAdapter.notifyDataSetChanged();
    }

    /**
     * Add an existing account
     */
    private void addAccount() {
        LayoutInflater factory = LayoutInflater.from(this);

        final View layout = factory.inflate(R.layout.fragment_dialog_add_account, null);
        final EditText usernameEditText = (EditText) layout.findViewById(R.id.editText_username);
        final EditText passwordEditText = (EditText) layout.findViewById(R.id.editText_password);
        final EditText homeServerEditText = (EditText) layout.findViewById(R.id.editText_hs);

        final AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle(R.string.action_add_account).setView(layout)
                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        String hsUrl = homeServerEditText.getText().toString();
                        String username = usernameEditText.getText().toString();
                        String password = passwordEditText.getText().toString();

                        if (!hsUrl.startsWith("http")) {
                            Toast.makeText(HomeActivity.this, getString(R.string.login_error_must_start_http),
                                    Toast.LENGTH_SHORT).show();
                            return;
                        }

                        if (TextUtils.isEmpty(username) || TextUtils.isEmpty(password)) {
                            Toast.makeText(HomeActivity.this, getString(R.string.login_error_invalid_credentials),
                                    Toast.LENGTH_SHORT).show();
                            return;
                        }

                        LoginRestClient client = null;

                        try {
                            client = new LoginRestClient(Uri.parse(hsUrl));
                        } catch (Exception e) {
                        }

                        if (null == client) {
                            Toast.makeText(HomeActivity.this, getString(R.string.login_error_invalid_home_server),
                                    Toast.LENGTH_SHORT).show();
                            return;
                        }

                        client.loginWithPassword(username, password,
                                new SimpleApiCallback<Credentials>(HomeActivity.this) {
                                    @Override
                                    public void onSuccess(Credentials credentials) {
                                        // check if there is active sessions with the same credentials.
                                        Collection<MXSession> sessions = Matrix.getMXSessions(HomeActivity.this);

                                        Boolean isDuplicated = false;

                                        for (MXSession existingSession : sessions) {
                                            isDuplicated |= (existingSession.getCredentials().userId
                                                    .equals(credentials.userId));
                                        }

                                        if (isDuplicated) {
                                            Toast.makeText(getApplicationContext(),
                                                    getString(R.string.login_error_already_logged_in),
                                                    Toast.LENGTH_LONG).show();
                                        } else {
                                            MXSession session = Matrix.getInstance(getApplicationContext())
                                                    .createSession(credentials);
                                            Matrix.getInstance(getApplicationContext()).addSession(session);
                                            startActivity(new Intent(HomeActivity.this, SplashActivity.class));
                                            HomeActivity.this.finish();
                                        }
                                    }

                                    @Override
                                    public void onNetworkError(Exception e) {
                                        Toast.makeText(getApplicationContext(),
                                                getString(R.string.login_error_network_error), Toast.LENGTH_LONG)
                                                .show();
                                    }

                                    @Override
                                    public void onUnexpectedError(Exception e) {
                                        String msg = getString(R.string.login_error_unable_login) + " : "
                                                + e.getMessage();
                                        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                                    }

                                    @Override
                                    public void onMatrixError(MatrixError e) {
                                        String msg = getString(R.string.login_error_unable_login) + " : " + e.error
                                                + "(" + e.errcode + ")";
                                        Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
                                    }
                                });

                    }
                }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                    }
                });
        alert.show();
    }

    private void removeAccount() {
        final ArrayList<MXSession> sessions = new ArrayList<MXSession>(Matrix.getMXSessions(this));

        // only one session -> loggout
        if (sessions.size() == 1) {
            CommonActivityUtils.logout(HomeActivity.this);
        }

        FragmentManager fm = getSupportFragmentManager();

        AccountsSelectionDialogFragment fragment = (AccountsSelectionDialogFragment) fm
                .findFragmentByTag(TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
        if (fragment != null) {
            fragment.dismissAllowingStateLoss();
        }

        fragment = AccountsSelectionDialogFragment.newInstance(Matrix.getMXSessions(getApplicationContext()));

        fragment.setListener(new AccountsSelectionDialogFragment.AccountsListener() {
            @Override
            public void onSelected(final MXSession session) {
                HomeActivity.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        final int sectionPos = sessions.indexOf(session);

                        CommonActivityUtils.logout(HomeActivity.this, session, true);

                        HomeActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                // expand/collapse to force the group refresh
                                collapseAllGroups();

                                mAdapter.removeSection(sectionPos);
                                mAdapter.notifyDataSetChanged();

                                // all the groups must be displayed during a search
                                mAdapter.setDisplayAllGroups(mSearchRoomEditText.getVisibility() == View.VISIBLE);
                                expandAllGroups();
                            }
                        });
                    }
                });
            }
        });

        fragment.show(fm, TAG_FRAGMENT_ACCOUNT_SELECTION_DIALOG);
    }
}