com.chatwingsdk.activities.CommunicationActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.chatwingsdk.activities.CommunicationActivity.java

Source

/*
 * Copyright (C) 2014 ChatWing
 *
 * 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 com.chatwingsdk.activities;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.ConsoleMessage;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.chatwingsdk.ChatWing;
import com.chatwingsdk.Constants;
import com.chatwingsdk.R;
import com.chatwingsdk.contentproviders.ChatWingContentProvider;
import com.chatwingsdk.events.faye.ChannelSubscriptionChangedEvent;
import com.chatwingsdk.events.faye.FayePublishEvent;
import com.chatwingsdk.events.faye.MessageReceivedEvent;
import com.chatwingsdk.events.faye.ServerConnectionChangedEvent;
import com.chatwingsdk.events.internal.AllSyncsCompletedEvent;
import com.chatwingsdk.events.internal.SyncCommunicationBoxEvent;
import com.chatwingsdk.events.internal.TouchUserInfoEvent;
import com.chatwingsdk.events.internal.UserUnauthenticatedEvent;
import com.chatwingsdk.events.internal.ViewProfileEvent;
import com.chatwingsdk.fragments.CategoriesFragment;
import com.chatwingsdk.fragments.ChatMessagesFragment;
import com.chatwingsdk.fragments.ChatboxesFragment;
import com.chatwingsdk.fragments.ColorPickerDialogFragment;
import com.chatwingsdk.fragments.CommunicationDrawerFragment;
import com.chatwingsdk.fragments.CommunicationMessagesFragment;
import com.chatwingsdk.fragments.ConversationMessagesFragment;
import com.chatwingsdk.fragments.ConversationsFragment;
import com.chatwingsdk.fragments.EmoticonsFragment;
import com.chatwingsdk.fragments.InjectableFragmentDelegate;
import com.chatwingsdk.fragments.NavigatableFragmentListener;
import com.chatwingsdk.fragments.NewContentFragment;
import com.chatwingsdk.fragments.ProfileFragment;
import com.chatwingsdk.interfaces.ChatWingJSInterface;
import com.chatwingsdk.managers.ApiManager;
import com.chatwingsdk.managers.ChatboxModeManager;
import com.chatwingsdk.managers.CommunicationModeManager;
import com.chatwingsdk.managers.ConversationModeManager;
import com.chatwingsdk.managers.SyncManager;
import com.chatwingsdk.managers.UserManager;
import com.chatwingsdk.modules.CommunicationActivityModule;
import com.chatwingsdk.parsers.BBCodePair;
import com.chatwingsdk.parsers.BBCodeParser;
import com.chatwingsdk.parsers.EventParser;
import com.chatwingsdk.pojos.Event;
import com.chatwingsdk.pojos.Message;
import com.chatwingsdk.pojos.jspojos.UserResponse;
import com.chatwingsdk.pojos.params.CreateConversationParams;
import com.chatwingsdk.services.CreateConversationIntentService;
import com.chatwingsdk.services.SyncCommunicationBoxesIntentService;
import com.chatwingsdk.utils.LogUtils;
import com.chatwingsdk.views.BBCodeEditText;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

import org.json.JSONException;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.inject.Inject;

/**
 * This activity is the base where {@link com.chatwingsdk.fragments.CommunicationMessagesFragment}
 * and drawers are attached. Depend on which mode the activity is in,
 * appropriate {@link com.chatwingsdk.managers.CommunicationModeManager} is activated
 * <p/>
 * <p>
 * Due to otto limitation, subclasses must override
 * </p>
 *
 * @author cuongthai
 */
public class CommunicationActivity extends BaseABFragmentActivity
        implements NewContentFragment.Listener, ColorPickerDialogFragment.Listener,
        CommunicationMessagesFragment.Delegate, CommunicationModeManager.Delegate, InjectableFragmentDelegate,
        CommunicationDrawerFragment.Listener, NavigatableFragmentListener, ProfileFragment.Listener {

    private static final String EMOTICONS_FRAGMENT_TAG = "EmoticonsFragment";
    private static final String ATTACHMENT_CONTENT_FRAGMENT_TAG = "NewContentFragment";
    private static final int MODE_CHAT_BOX = 0;
    private static final int MODE_CONVERSATION = 1;
    public static final int REQUEST_CODE_AUTHENTICATION = 10000;

    private WebView mWebView;
    private boolean mNotSubscribeToChannels;
    @Inject
    ChatWingJSInterface mFayeJsInterface;
    @Inject
    protected ChatboxModeManager mChatboxModeManager;
    @Inject
    ConversationModeManager mConversationModeManager;
    @Inject
    Bus mBus;
    @Inject
    UserManager mUserManager;
    @Inject
    ApiManager mApiManager;
    @Inject
    EventParser mEventParser;
    @Inject
    SyncManager mSyncManager;

    protected CommunicationModeManager mCurrentCommunicationMode;

    private View mContentView;
    private View mProgressView;
    private ProgressBar mProgressBar;
    private TextView mProgressText;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    // Flag to determined onCreate is called. It is used onResume to decide
    // whether a sync operation should be triggered or not and reset right
    // after that.
    private boolean mIsCreated;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ChatWing.instance(getApplicationContext()).getChatwingGraph().plus();

        setContentView(R.layout.activity_communication);

        mBus.register(this);

        getSupportActionBar().setHomeButtonEnabled(true);

        mContentView = findViewById(R.id.fragment_container);
        mProgressView = findViewById(R.id.progress_container);
        mProgressBar = (ProgressBar) mProgressView.findViewById(R.id.loading_view);
        mProgressText = (TextView) mProgressView.findViewById(R.id.progress_text);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        mChatboxModeManager.onCreate(savedInstanceState);
        mConversationModeManager.onCreate(savedInstanceState);
        int currentMode = getDefaultMode();

        if (currentMode == MODE_CHAT_BOX) {
            setupChatboxMode();
        } else {
            setupConversationMode();
        }
        mIsCreated = true;
    }

    @Override
    protected void onStart() {
        super.onStart();

        // Determine whether a sync categories operation should be
        // performed right now or not.
        // It should start if the activity is newly created (onCreate is called).
        // Thus, we don't refresh when the activity has been in background for a
        // short period of time.
        if (mIsCreated) {
            startSyncingCommunications();
            mIsCreated = false;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        LogUtils.v("onActivityResult " + requestCode + ":" + resultCode);
        mCurrentCommunicationMode.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == REQUEST_CODE_AUTHENTICATION && resultCode == RESULT_OK) {
            startSyncingCommunications();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LogUtils.v("On Destroy Activity");
        mBus.unregister(this);

        if (mWebView != null) {
            mWebView.destroy();
            mWebView = null;
        }
        mCurrentCommunicationMode.onDestroy();
        mCurrentCommunicationMode = null;
        mNotSubscribeToChannels = true;
    }

    @Override
    protected void onResume() {
        super.onResume();

        if (Build.VERSION.SDK_INT >= 11) {
            if (mWebView != null) {
                mWebView.onResume();
            }
        }
        ensureWebViewAndSubscribeToChannels();

        mChatboxModeManager.onResume();
        mConversationModeManager.onResume();
        invalidateOptionsMenu();

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mWebView != null) {
            if (Build.VERSION.SDK_INT >= 11) {
                mWebView.onPause();
            }
        }

        mChatboxModeManager.onPause();
        mConversationModeManager.onPause();
    }

    @Override
    protected void onPostResume() {
        super.onPostResume();
        mCurrentCommunicationMode.onPostResume();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return mCurrentCommunicationMode.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return mCurrentCommunicationMode.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int i = item.getItemId();
        if (i == android.R.id.home) {
            if (getDrawerLayout().isDrawerOpen(Gravity.LEFT)) {
                getDrawerLayout().closeDrawer(Gravity.LEFT);
            } else {
                getDrawerLayout().openDrawer(Gravity.LEFT);
            }
            return true;
        } else {
            return mCurrentCommunicationMode.onOptionsItemSelected(item);
        }
    }

    @Override
    protected List<Object> getModules() {
        return Arrays.<Object>asList(new CommunicationActivityModule(this));
    }

    @Override
    public final void onItemClicked(NewContentFragment.Item item) {
        switch (item) {
        case BBCODES:
            getCommunicationMessagesFragment().showBBCodeControls();
            break;
        case EMOTICONS:
            showEmoticonsFragment();
            break;
        }
    }

    @Override
    public final void showColorPickerDialogFragment(BBCodeParser.BBCode code) {
        if (code == null) {
            throw new IllegalArgumentException("Code is required.");
        }
        ColorPickerDialogFragment fragment = ColorPickerDialogFragment.newInstance(code);
        fragment.show(getSupportFragmentManager(), code.toString());
    }

    @Override
    public final void showNewContentFragment() {
        boolean hasBBCodes = !getCommunicationMessagesFragment().isShowingBBControls();
        NewContentFragment fragment = NewContentFragment.newInstance(hasBBCodes);
        fragment.show(getSupportFragmentManager(), ATTACHMENT_CONTENT_FRAGMENT_TAG);
    }

    @Override
    public final void inject(BBCodeEditText mCommunicationBoxEditText) {
        super.inject(mCommunicationBoxEditText);
    }

    @Override
    public final void onConfirmColor(Serializable code, int color) {
        BBCodePair pair = new BBCodePair((BBCodeParser.BBCode) code, color);
        getCommunicationMessagesFragment().appendBBCode(pair);
    }

    @Override
    public final void inject(Fragment fragment) {
        super.inject(fragment);
    }

    @Override
    public final void handle(Exception exception, int errorMessageResId) {
        if (exception instanceof ApiManager.UserUnauthenticatedException) {
            onUserUnAuthenticatedEvent(null);
        } else {
            mErrorMessageView.show(exception, getString(R.string.error_unknown));
        }
    }

    @Override
    public final ActionBarActivity getActivity() {
        return this;
    }

    @Override
    public final CommunicationMessagesFragment getCommunicationMessagesFragment() {
        String tag = getString(R.string.tag_communication_messages);
        return (CommunicationMessagesFragment) getSupportFragmentManager().findFragmentByTag(tag);
    }

    @Override
    public final void setProgressText(int resId, boolean showProgressBar) {
        setContentShown(false);
        mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
        mProgressText.setText(resId);
    }

    @Override
    public final void setContentShown(boolean shown) {
        if (shown) {
            mContentView.setVisibility(View.VISIBLE);
            mProgressView.setVisibility(View.GONE);
        } else {
            mContentView.setVisibility(View.GONE);
            mProgressView.setVisibility(View.VISIBLE);
        }
    }

    @Override
    public final DrawerLayout getDrawerLayout() {
        return mDrawerLayout;
    }

    /**
     * Calls this in subclass to use it as Conversation Mode
     */
    protected void setupConversationMode() {
        setupMode(mConversationModeManager, ConversationMessagesFragment.newInstance());
    }

    /**
     * Calls this in subclass to use it as Public ChatBox Mode
     */
    protected void setupChatboxMode() {
        setupMode(mChatboxModeManager, ChatMessagesFragment.newInstance());
    }

    /**
     * Requires to be overriden by subclass to be called by otto
     *
     * @param event
     */
    protected void onUserUnAuthenticatedEvent(UserUnauthenticatedEvent event) {
        mQuickMessageView.show(R.string.message_need_login);
    }

    @Override
    public void showCategories() {
        setTitle(getActivity().getString(R.string.title_chat_boxes));
        invalidateOptionsMenu();
        if (isInConversationMode()) {
            setupChatboxMode();
        }
        addToLeftDrawer(getChatBoxesFragment());
    }

    @Override
    public void showConversations() {
        setTitle(getActivity().getString(R.string.title_activity_conversation));
        invalidateOptionsMenu();
        if (isInChatBoxMode()) {
            setupConversationMode();
        }
        addToLeftDrawer(new ConversationsFragment());
    }

    @Override
    public void back(Fragment from) {
        getSupportFragmentManager().beginTransaction().setCustomAnimations(0, R.anim.slide_out_left).remove(from)
                .commit();
        invalidateOptionsMenu();
    }

    @Override
    public boolean onSwipe() {
        return startSyncingCommunications();
    }

    @Override
    public WebView getWebView() {
        return mWebView;
    }

    @Override
    public void showConversation(CreateConversationParams.SimpleUser simpleUser) {
        initConversationMenu();

        Intent createConversation = new Intent(getActivity(), CreateConversationIntentService.class);
        createConversation.putExtra(CreateConversationIntentService.EXTRA_USER, simpleUser);
        startService(createConversation);
    }

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    public void ensureWebViewAndSubscribeToChannels() {
        if (mCurrentCommunicationMode == null)
            return;
        // Check whether the web view is available or not.
        // If not, init it and load faye client. When loading finished,
        // this method will be recursively called. At that point,
        // the actual subscribe code will be executed.
        if (mWebView == null) {
            mNotSubscribeToChannels = true;
            mWebView = new WebView(this);

            WebSettings webSettings = mWebView.getSettings();
            webSettings.setJavaScriptEnabled(true);

            mWebView.addJavascriptInterface(mFayeJsInterface, ChatWingJSInterface.CHATWING_JS_NAME);

            mWebView.setWebChromeClient(new WebChromeClient() {
                @Override
                public boolean onConsoleMessage(ConsoleMessage consoleMessage) {

                    LogUtils.v(consoleMessage.message() + " -- level " + consoleMessage.messageLevel()
                            + " -- From line " + consoleMessage.lineNumber() + " of " + consoleMessage.sourceId());

                    //This workaround tries to fix issue webview is not subscribe successfully
                    //when the screen is off, we cant listen for otto event since it's dead before that
                    //this likely happens on development or very rare case in production
                    if (consoleMessage.messageLevel().equals(ConsoleMessage.MessageLevel.ERROR)) {
                        mWebView = null;
                        mNotSubscribeToChannels = true;
                    }
                    return true;
                }
            });

            mWebView.setWebViewClient(new WebViewClient() {
                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);

                    if (url.equals(Constants.FAYE_CLIENT_URL)) {
                        // Recursively call this method,
                        // to execute subscribe code.
                        ensureWebViewAndSubscribeToChannels();
                    }
                }
            });

            mWebView.loadUrl(Constants.FAYE_CLIENT_URL);
            return;
        }
        if (mNotSubscribeToChannels) {
            mNotSubscribeToChannels = false;
            mCurrentCommunicationMode.subscribeToChannels(mWebView);
        }
    }

    //////////////////////////////////////////
    ///     Otto
    //////////////////////////////////////////

    @Subscribe
    public void onAllSyncsCompleted(AllSyncsCompletedEvent event) {
        mWebView = null;
        mNotSubscribeToChannels = true;
        ensureWebViewAndSubscribeToChannels();
        LogUtils.v("Syncing All completed");
        if (mCurrentCommunicationMode != null) {
            mCurrentCommunicationMode.reloadCurrentBox();
        }
    }

    @Subscribe
    public void onTouchUserInfoEvent(TouchUserInfoEvent event) {
        UserResponse user = event.getUser();
        String loginType = user.getLoginType();
        String loginId = user.getLoginId();
        String userAvatar = user.getUserAvatar();

        String userProfileUrl = mApiManager.getUserProfileUrl(loginType, loginId);
        ProfileFragment newFragment = ProfileFragment.newInstance(new ViewProfileEvent(userProfileUrl,
                mApiManager.getAvatarUrl(loginType, loginId, userAvatar), user.getUserName(), loginType, loginId,
                mUserManager.getCurrentUser() == null ? true : user.equals(mUserManager.getCurrentUser())));
        newFragment.show(getSupportFragmentManager(), "dialog");
    }

    @Subscribe
    public void onChannelSubscriptionChanged(ChannelSubscriptionChangedEvent event) {
        //Faye
        if (event.getStatus() == ChannelSubscriptionChangedEvent.Status.SUCCEED) {
            if (Constants.DEBUG) {
                mQuickMessageView.show(getString(R.string.message_subscribed_to_channel) + event.getChannel());
            }
            LogUtils.v("Subscribed to channel: " + event.getChannel());
            mNotSubscribeToChannels = false;
        } else {
            // Failed
            mErrorMessageView.show(getString(R.string.message_error) + event.getError());
            LogUtils.e(event.getError());
            //We resubscribe next time
            mNotSubscribeToChannels = true;
            mWebView = null;
        }
    }

    @Subscribe
    public void onFayePublished(FayePublishEvent event) {
        //Faye
        if (event.getStatus() == FayePublishEvent.Status.SUCCEED) {
            if (Constants.DEBUG) {
                mQuickMessageView.show(R.string.message_published);
            }
            LogUtils.v("Published: " + event.toString());
        } else {
            // Failed
            mErrorMessageView.show(getString(R.string.message_error) + event.getError());
            LogUtils.e(event.getError());
        }
    }

    @Subscribe
    public void onMessageReceived(MessageReceivedEvent event) {
        //Faye
        LogUtils.v("Java -----------");
        LogUtils.v(System.currentTimeMillis() + "");
        LogUtils.v("------------------");

        LogUtils.v("Java main thread -----------");
        LogUtils.v(System.currentTimeMillis() + "");
        LogUtils.v("------------------");

        try {
            Event e = mEventParser.parse(event.getMessage());
            if (Constants.DEBUG) {
                mQuickMessageView.show(getString(R.string.message_event) + e.getName());
                LogUtils.v("Event: " + e.getName());
            }
            processEvent(e);
        } catch (JSONException ex) {
            handle(ex, R.string.message_error);
        }
    }

    @Subscribe
    public void onServerConnectionChangedEvent(ServerConnectionChangedEvent event) {
        //Faye
        if (event.getStatus() == ServerConnectionChangedEvent.Status.CONNECTED) {
            if (Constants.DEBUG) {
                mQuickMessageView.show(R.string.message_connected_to_server);
            }
            LogUtils.v("Connected to server.");
        } else {
            // Disconnected
            if (Constants.DEBUG) {
                mQuickMessageView.show(R.string.message_disconnected_from_server);
            }
            LogUtils.v("Disconnected from server.");
        }
    }

    @Subscribe
    public void onSyncCommunicationBoxEvent(SyncCommunicationBoxEvent event) {
        SyncCommunicationBoxEvent.Status status = event.getStatus();
        switch (status) {
        case STARTED:
            break;
        case SUCCEED:
            /*
             * TODO when succeed, may need to check if the current chat
             * box is still valid.
             * And un-subscribe to all invalid chat boxes.
             */

            ensureWebViewAndSubscribeToChannels();
            break;
        case FAILED:
            handle(event.getException(), R.string.error_failed_to_sync_data);
            break;
        }
    }

    private void processEvent(Event event) {
        String name = event.getName();
        if (name.equals(EventParser.EVENT_NEW_MESSAGE) || name.equals(EventParser.EVENT_NETWORK_NEW_MESSAGE)) {
            Message message = (Message) event.getParams();
            message.setStatus(Message.Status.PUBLISHED);

            boolean isInCurrentCommunicationBox = mCurrentCommunicationMode.isInCurrentCommunicationBox(message);

            if (!isInCurrentCommunicationBox) {
                mCurrentCommunicationMode.processMessageNotInCurrentCommunicationBox(message);
            }
        }
    }

    //////////////////////////
    // Instance methods
    //////////////////////////
    private void initConversationMenu() {
        setTitle(getActivity().getString(R.string.title_activity_conversation));

        if (isInChatBoxMode()) {
            setupConversationMode();
        }
        invalidateOptionsMenu();
    }

    private boolean isInChatBoxMode() {
        return mCurrentCommunicationMode == null || mCurrentCommunicationMode instanceof ChatboxModeManager;
    }

    private boolean isInConversationMode() {
        return mCurrentCommunicationMode == null || mCurrentCommunicationMode instanceof ConversationModeManager;
    }

    private void addToLeftDrawer(Fragment fragment) {
        addToLeftDrawer(fragment, true);
    }

    private void addToLeftDrawer(Fragment fragment, boolean animate) {
        if (animate) {
            getSupportFragmentManager().beginTransaction()
                    .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left, R.anim.slide_in_right,
                            R.anim.slide_out_left)
                    .replace(R.id.left_drawer_container, fragment).addToBackStack(null).commit();
        } else {
            getSupportFragmentManager().beginTransaction().replace(R.id.left_drawer_container, fragment)
                    .addToBackStack(null).commit();
        }
    }

    private Fragment getChatBoxesFragment() {
        return new CategoriesFragment();
    }

    protected void setupMode(CommunicationModeManager newMode, CommunicationMessagesFragment newFragment) {
        /*
         * Update fragments
         */
        String fragmentTag = getString(R.string.tag_communication_messages);
        FragmentManager fragmentManager = getSupportFragmentManager();
        Fragment oldFragment = fragmentManager.findFragmentByTag(fragmentTag);
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        if (oldFragment != null) {
            fragmentTransaction.remove(oldFragment);
        }
        fragmentTransaction.add(R.id.fragment_container, newFragment, fragmentTag);
        fragmentTransaction.commit();

        /*
         * Deactivate old mode and activate the new one
         */
        if (mCurrentCommunicationMode != null) {
            mCurrentCommunicationMode.deactivate();
        }
        mCurrentCommunicationMode = newMode;
        mCurrentCommunicationMode.activate();

        /*
         * Setup drawer layout
         */
        // Set custom shadows that overlay the main content when a drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow_left, Gravity.LEFT);
        mDrawerToggle = mCurrentCommunicationMode.getDrawerToggleListener();
        mDrawerToggle.setDrawerIndicatorEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
        mDrawerLayout.setDrawerListener(mDrawerToggle);
        // Don't allow the drawer layout to catch back button and close itself
        // on back key is pressed. This activity will handle it.
        mDrawerLayout.setFocusableInTouchMode(false);

        invalidateOptionsMenu();
    }

    private void showEmoticonsFragment() {
        Map<String, String> emoticons = mCurrentCommunicationMode.getEmoticons();
        TreeMap<String, String> treeMap;
        if (emoticons instanceof TreeMap) {
            //noinspection unchecked
            treeMap = (TreeMap) emoticons;
        } else {
            treeMap = new TreeMap<String, String>(emoticons);
        }

        EmoticonsFragment fragment = EmoticonsFragment.newInstance(treeMap);
        fragment.show(getSupportFragmentManager(), EMOTICONS_FRAGMENT_TAG);
    }

    @Override
    public void logout() {
        if (mUserManager.getCurrentUser() == null) {
            return;
        }

        mCurrentCommunicationMode.logout();
        mUserManager.removeUsers();

        try {
            getContentResolver().applyBatch(ChatWingContentProvider.AUTHORITY,
                    ChatWingContentProvider.getClearAllDataBatch());
        } catch (RemoteException e) {
            LogUtils.e(e);
        } catch (OperationApplicationException e) {
            LogUtils.e(e);
        }

        Intent i = new Intent(this, getEntranceActivityClass());
        startActivity(i);
        finish();
    }

    protected Class<? extends BaseABFragmentActivity> getEntranceActivityClass() {
        return CommunicationActivity.class;
    }

    private boolean startSyncingCommunications() {
        if (SyncCommunicationBoxesIntentService.isInProgress()) {
            // A sync operation is running. Just wait for it.
            return false;
        }
        mSyncManager.resetQueue();
        mSyncManager.addToQueue(SyncCommunicationBoxesIntentService.class);

        Intent intent = new Intent(this, SyncCommunicationBoxesIntentService.class);
        startService(intent);
        return true;
    }

    private int getDefaultMode() {
        return MODE_CHAT_BOX;
    }

}