org.mariotaku.twidere.fragment.AccountsDashboardFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.mariotaku.twidere.fragment.AccountsDashboardFragment.java

Source

/*
 *             Twidere - Twitter client for Android
 * 
 *  Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mariotaku.twidere.fragment;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.NavigationView;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.view.SupportMenuInflater;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.ActionMenuView.OnMenuItemClickListener;
import android.support.v7.widget.FixedLinearLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ViewSwitcher;

import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.ComposeActivity;
import org.mariotaku.twidere.activity.HomeActivity;
import org.mariotaku.twidere.activity.PlusServiceDashboardActivity;
import org.mariotaku.twidere.activity.QuickSearchBarActivity;
import org.mariotaku.twidere.activity.SettingsActivity;
import org.mariotaku.twidere.annotation.CustomTabType;
import org.mariotaku.twidere.menu.AccountToggleProvider;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.SupportTabSpec;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.IntentUtils;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.MenuUtils;
import org.mariotaku.twidere.util.TransitionUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
import org.mariotaku.twidere.view.ShapedImageView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class AccountsDashboardFragment extends BaseSupportFragment
        implements LoaderCallbacks<Cursor>, OnSharedPreferenceChangeListener, OnClickListener,
        KeyboardShortcutCallback, NavigationView.OnNavigationItemSelectedListener {

    private final Rect mSystemWindowsInsets = new Rect();
    private ContentResolver mResolver;

    private AccountSelectorAdapter mAccountsAdapter;

    private NavigationView mNavigationView;
    private View mAccountSelectorView;
    private RecyclerView mAccountsSelector;
    private ViewSwitcher mAccountProfileBannerView;
    private ImageView mFloatingProfileImageSnapshotView;
    private ShapedImageView mAccountProfileImageView;
    private TextView mAccountProfileNameView, mAccountProfileScreenNameView;
    private ActionMenuView mAccountsToggleMenu;
    private View mAccountProfileContainer;
    private View mNoAccountContainer;

    private AccountToggleProvider mAccountActionProvider;
    private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
            this, 0, this) {
        @Override
        public void onChange(boolean selfChange, @Nullable Uri uri) {
            final ContentResolver cr = getContentResolver();
            if (cr == null)
                return;
            final Cursor c = cr.query(Accounts.CONTENT_URI, Accounts.COLUMNS, null, null, Accounts.SORT_POSITION);
            try {
                updateAccountProviderData(c);
            } finally {
                Utils.closeSilently(c);
            }
            super.onChange(selfChange, uri);
        }
    };
    private boolean mSwitchAccountAnimationPlaying;
    private boolean mUseStarsForLikes;
    private boolean mLoaderInitialized;

    @NonNull
    public UserKey[] getActivatedAccountIds() {
        if (mAccountActionProvider != null) {
            return mAccountActionProvider.getActivatedAccountIds();
        }
        return DataStoreUtils.getActivatedAccountKeys(getActivity());
    }

    @Override
    public boolean handleKeyboardShortcutSingle(@NonNull final KeyboardShortcutsHandler handler, final int keyCode,
            @NonNull final KeyEvent event, int metaState) {
        return false;
    }

    @Override
    public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode,
            @NonNull KeyEvent event, int metaState) {
        final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
        return ACTION_NAVIGATION_PREVIOUS.equals(action) || ACTION_NAVIGATION_NEXT.equals(action);
    }

    @Override
    public boolean handleKeyboardShortcutRepeat(@NonNull final KeyboardShortcutsHandler handler, final int keyCode,
            final int repeatCount, @NonNull final KeyEvent event, int metaState) {
        final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event, metaState);
        if (action == null)
            return false;
        final int offset;
        switch (action) {
        case ACTION_NAVIGATION_PREVIOUS: {
            offset = -1;
            break;
        }
        case ACTION_NAVIGATION_NEXT: {
            offset = 1;
            break;
        }
        default: {
            return false;
        }
        }
        //        final int selectedItem = mNavigationView.getSelectedItemPosition();
        //        final int count = mNavigationView.getCount();
        //        int resultPosition;
        //        if (!mNavigationView.isFocused() || selectedItem == ListView.INVALID_POSITION) {
        //            resultPosition = firstVisiblePosition;
        //        } else {
        //            resultPosition = selectedItem + offset;
        //            while (resultPosition >= 0 && resultPosition < count && !mAdapter.isEnabled(resultPosition)) {
        //                resultPosition += offset;
        //            }
        //        }
        //        final View focusedChild = mNavigationView.getFocusedChild();
        //        if (focusedChild == null) {
        //            mNavigationView.requestChildFocus(mNavigationView.getChildAt(0), null);
        //        }
        //        if (resultPosition >= 0 && resultPosition < count) {
        //            mNavigationView.setSelection(resultPosition);
        //        }
        return true;
    }

    @Override
    public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        switch (requestCode) {
        case REQUEST_SETTINGS: {
            if (data == null)
                return;
            final FragmentActivity activity = getActivity();
            if (data.getBooleanExtra(EXTRA_CHANGED, false)) {
                activity.recreate();
            }
            return;
        }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onResume() {
        super.onResume();
        updateDefaultAccountState();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.profile_container: {
            final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
            if (account == null)
                return;
            final FragmentActivity activity = getActivity();
            if (account.account_user != null) {
                IntentUtils.openUserProfile(activity, account.account_user, null,
                        mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), UserFragment.Referral.SELF_PROFILE);
            } else {
                IntentUtils.openUserProfile(activity, account.account_key, account.account_key, account.screen_name,
                        null, mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), UserFragment.Referral.SELF_PROFILE);
            }
            break;
        }
        }
    }

    @Override
    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
        return new CursorLoader(getActivity(), Accounts.CONTENT_URI, Accounts.COLUMNS, null, null,
                Accounts.SORT_POSITION);
    }

    @Override
    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
        updateAccountProviderData(data);
    }

    private void updateAccountProviderData(@Nullable final Cursor cursor) {
        if (cursor == null)
            return;
        final Menu menu = mAccountsToggleMenu.getMenu();
        mAccountActionProvider = (AccountToggleProvider) MenuItemCompat
                .getActionProvider(menu.findItem(R.id.select_account));
        final ParcelableAccount[] accounts = ParcelableAccountUtils.getAccounts(cursor);
        if (accounts.length > 0) {
            mNoAccountContainer.setVisibility(View.GONE);
            mAccountProfileContainer.setVisibility(View.VISIBLE);
        } else {
            mNoAccountContainer.setVisibility(View.VISIBLE);
            mAccountProfileContainer.setVisibility(View.INVISIBLE);
        }
        UserKey defaultId = null;
        for (ParcelableAccount account : accounts) {
            if (account.is_activated) {
                defaultId = account.account_key;
                break;
            }
        }
        mUseStarsForLikes = mPreferences.getBoolean(KEY_I_WANT_MY_STARS_BACK);

        mAccountsAdapter.setAccounts(accounts);
        UserKey accountKey = UserKey.valueOf(mPreferences.getString(KEY_DEFAULT_ACCOUNT_KEY, null));
        if (accountKey == null) {
            accountKey = defaultId;
        }
        ParcelableAccount selectedAccount = null;
        for (ParcelableAccount account : accounts) {
            if (account.account_key.maybeEquals(accountKey)) {
                selectedAccount = account;
                break;
            }
        }
        mAccountsAdapter.setSelectedAccount(selectedAccount);

        if (mAccountActionProvider != null) {
            mAccountActionProvider.setExclusive(false);
            mAccountActionProvider.setAccounts(accounts);
        }
        updateAccountActions();
        ParcelableAccount currentAccount = mAccountsAdapter.getSelectedAccount();
        if (currentAccount != null) {
            displayAccountBanner(currentAccount);
            displayCurrentAccount(null);
        }
        updateDefaultAccountState();
    }

    @Override
    public void onLoaderReset(final Loader<Cursor> loader) {
    }

    @Override
    public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
        if (KEY_DEFAULT_ACCOUNT_KEY.equals(key)) {
            updateDefaultAccountState();
        }
    }

    @Override
    protected void fitSystemWindows(Rect insets) {
        mSystemWindowsInsets.set(insets);
        updateSystemWindowsInsets();
    }

    private void updateSystemWindowsInsets() {
        if (mAccountProfileContainer == null)
            return;
        final Rect insets = mSystemWindowsInsets;
    }

    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mResolver = getContentResolver();
        final View view = getView();
        assert view != null;
        final Context context = view.getContext();
        final LayoutInflater inflater = getLayoutInflater(savedInstanceState);
        mAccountsAdapter = new AccountSelectorAdapter(inflater, this);
        final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(context);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        layoutManager.setStackFromEnd(true);
        mAccountsSelector.setLayoutManager(layoutManager);
        mAccountsSelector.setAdapter(mAccountsAdapter);
        mAccountsSelector.setItemAnimator(null);
        final SupportMenuInflater menuInflater = new SupportMenuInflater(context);
        menuInflater.inflate(R.menu.action_dashboard_timeline_toggle, mAccountsToggleMenu.getMenu());
        mAccountsToggleMenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                if (item.getGroupId() != AccountToggleProvider.MENU_GROUP) {
                    switch (item.getItemId()) {
                    case R.id.compose: {
                        final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
                        if (account == null)
                            return true;
                        final Intent composeIntent = new Intent(INTENT_ACTION_COMPOSE);
                        composeIntent.setClass(getActivity(), ComposeActivity.class);
                        composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.account_key);
                        startActivity(composeIntent);
                        return true;
                    }
                    }
                    return false;
                }
                final ParcelableAccount[] accounts = mAccountActionProvider.getAccounts();
                final ParcelableAccount account = accounts[item.getOrder()];
                final ContentValues values = new ContentValues();
                final boolean newActivated = !account.is_activated;
                mAccountActionProvider.setAccountActivated(account.account_key, newActivated);
                values.put(Accounts.IS_ACTIVATED, newActivated);
                final String where = Expression.equalsArgs(Accounts.ACCOUNT_KEY).getSQL();
                final String[] whereArgs = { account.account_key.toString() };
                mResolver.update(Accounts.CONTENT_URI, values, where, whereArgs);
                return true;
            }
        });

        mAccountProfileContainer.setOnClickListener(this);

        mAccountProfileBannerView.setInAnimation(getContext(), android.R.anim.fade_in);
        mAccountProfileBannerView.setOutAnimation(getContext(), android.R.anim.fade_out);
        mAccountProfileBannerView.setFactory(new ViewSwitcher.ViewFactory() {
            @Override
            public View makeView() {
                return inflater.inflate(R.layout.layout_account_dashboard_profile_image, mAccountProfileBannerView,
                        false);
            }
        });

        mNavigationView.setNavigationItemSelectedListener(this);
        mPreferences.registerOnSharedPreferenceChangeListener(this);

        loadAccounts();

        updateSystemWindowsInsets();
    }

    public void loadAccounts() {
        if (!mLoaderInitialized) {
            mLoaderInitialized = true;
            getLoaderManager().initLoader(0, null, this);
        } else {
            getLoaderManager().restartLoader(0, null, this);
        }
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
            final Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_accounts_dashboard, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mNavigationView = (NavigationView) view.findViewById(R.id.navigation_view);
        mAccountSelectorView = mNavigationView.getHeaderView(0);
        mAccountsSelector = (RecyclerView) mAccountSelectorView.findViewById(R.id.other_accounts_list);
        mAccountProfileContainer = mAccountSelectorView.findViewById(R.id.profile_container);
        mNoAccountContainer = mAccountSelectorView.findViewById(R.id.no_account_container);
        mAccountProfileImageView = (ShapedImageView) mAccountSelectorView.findViewById(R.id.profile_image);
        mAccountProfileBannerView = (ViewSwitcher) mAccountSelectorView.findViewById(R.id.account_profile_banner);
        mFloatingProfileImageSnapshotView = (ImageView) mAccountSelectorView
                .findViewById(R.id.floating_profile_image_snapshot);
        mAccountProfileNameView = (TextView) mAccountSelectorView.findViewById(R.id.name);
        mAccountProfileScreenNameView = (TextView) mAccountSelectorView.findViewById(R.id.screen_name);
        mAccountsToggleMenu = (ActionMenuView) mAccountSelectorView.findViewById(R.id.account_dashboard_menu);
    }

    @Override
    public void onStart() {
        super.onStart();
        final ContentResolver resolver = getContentResolver();
        resolver.registerContentObserver(Accounts.CONTENT_URI, true, mReloadContentObserver);
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    public void onStop() {
        final ContentResolver resolver = getContentResolver();
        resolver.unregisterContentObserver(mReloadContentObserver);
        super.onStop();
    }

    void updateAccountActions() {
        final HomeActivity activity = (HomeActivity) getActivity();
        if (activity == null)
            return;
        final List<SupportTabSpec> tabs = activity.getTabs();
        final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
        if (account == null)
            return;
        boolean hasDmTab = false, hasInteractionsTab = false;
        for (SupportTabSpec tab : tabs) {
            if (tab.type == null)
                continue;
            switch (tab.type) {
            case CustomTabType.DIRECT_MESSAGES: {
                if (!hasDmTab) {
                    hasDmTab = hasAccountInTab(tab, account.account_key, account.is_activated);
                }
                break;
            }
            case CustomTabType.NOTIFICATIONS_TIMELINE: {
                if (!hasInteractionsTab) {
                    hasInteractionsTab = hasAccountInTab(tab, account.account_key, account.is_activated);
                }
                break;
            }
            }
        }
        final Menu menu = mNavigationView.getMenu();
        MenuUtils.setMenuItemAvailability(menu, R.id.interactions, !hasInteractionsTab);
        MenuUtils.setMenuItemAvailability(menu, R.id.messages, !hasDmTab);

        if (mUseStarsForLikes) {
            MenuUtils.setMenuItemTitle(menu, R.id.favorites, R.string.favorites);
            MenuUtils.setMenuItemIcon(menu, R.id.favorites, R.drawable.ic_action_star);
        } else {
            MenuUtils.setMenuItemTitle(menu, R.id.favorites, R.string.likes);
            MenuUtils.setMenuItemIcon(menu, R.id.favorites, R.drawable.ic_action_heart);
        }
        boolean hasLists = false, hasGroups = false, hasPublicTimeline = false;
        switch (ParcelableAccountUtils.getAccountType(account)) {
        case ParcelableAccount.Type.TWITTER: {
            hasLists = true;
            break;
        }
        case ParcelableAccount.Type.STATUSNET: {
            hasGroups = true;
            break;
        }
        case ParcelableAccount.Type.FANFOU: {
            hasPublicTimeline = true;
            break;
        }
        }
        MenuUtils.setMenuItemAvailability(menu, R.id.groups, hasGroups);
        MenuUtils.setMenuItemAvailability(menu, R.id.lists, hasLists);
        MenuUtils.setMenuItemAvailability(menu, R.id.public_timeline, hasPublicTimeline);
    }

    private boolean hasAccountInTab(SupportTabSpec tab, UserKey accountId, boolean isActivated) {
        if (tab.args == null)
            return false;
        final UserKey[] accountKeys = Utils.getAccountKeys(getContext(), tab.args);
        if (accountKeys == null)
            return isActivated;
        return ArrayUtils.contains(accountKeys, accountId);
    }

    private void closeAccountsDrawer() {
        final Activity activity = getActivity();
        if (activity instanceof HomeActivity) {
            ((HomeActivity) activity).closeAccountsDrawer();
        }
    }

    private void getLocationOnScreen(View view, RectF rectF) {
        final int[] location = new int[2];
        view.getLocationOnScreen(location);
        rectF.set(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight());
    }

    private void onAccountSelected(AccountProfileImageViewHolder holder, @NonNull final ParcelableAccount account) {
        if (mSwitchAccountAnimationPlaying)
            return;
        final ImageView snapshotView = mFloatingProfileImageSnapshotView;
        final ShapedImageView profileImageView = mAccountProfileImageView;
        final ShapedImageView clickedImageView = holder.getIconView();

        // Reset snapshot view position
        snapshotView.setPivotX(0);
        snapshotView.setPivotY(0);
        snapshotView.setTranslationX(0);
        snapshotView.setTranslationY(0);

        final Matrix matrix = new Matrix();
        final RectF sourceBounds = new RectF(), destBounds = new RectF(), snapshotBounds = new RectF();
        getLocationOnScreen(clickedImageView, sourceBounds);
        getLocationOnScreen(profileImageView, destBounds);
        getLocationOnScreen(snapshotView, snapshotBounds);
        final float finalScale = destBounds.width() / sourceBounds.width();
        final Bitmap snapshotBitmap = TransitionUtils.createViewBitmap(clickedImageView, matrix,
                new RectF(0, 0, sourceBounds.width(), sourceBounds.height()));
        final ViewGroup.LayoutParams lp = snapshotView.getLayoutParams();
        lp.width = clickedImageView.getWidth();
        lp.height = clickedImageView.getHeight();
        snapshotView.setLayoutParams(lp);
        // Copied from MaterialNavigationDrawer: https://github.com/madcyph3r/AdvancedMaterialDrawer/
        AnimatorSet set = new AnimatorSet();
        set.play(ObjectAnimator.ofFloat(snapshotView, View.TRANSLATION_X, sourceBounds.left - snapshotBounds.left,
                destBounds.left - snapshotBounds.left))
                .with(ObjectAnimator.ofFloat(snapshotView, View.TRANSLATION_Y,
                        sourceBounds.top - snapshotBounds.top, destBounds.top - snapshotBounds.top))
                .with(ObjectAnimator.ofFloat(snapshotView, View.SCALE_X, 1, finalScale))
                .with(ObjectAnimator.ofFloat(snapshotView, View.SCALE_Y, 1, finalScale))
                .with(ObjectAnimator.ofFloat(profileImageView, View.ALPHA, 1, 0))
                .with(ObjectAnimator.ofFloat(clickedImageView, View.SCALE_X, 0, 1))
                .with(ObjectAnimator.ofFloat(clickedImageView, View.SCALE_Y, 0, 1));
        final long animationTransition = 400;
        set.setDuration(animationTransition);
        set.setInterpolator(new DecelerateInterpolator());
        set.addListener(new AnimatorListener() {

            private Drawable clickedDrawable;
            private int[] clickedColors;

            @Override
            public void onAnimationStart(Animator animation) {
                snapshotView.setVisibility(View.VISIBLE);
                snapshotView.setImageBitmap(snapshotBitmap);
                final Drawable profileDrawable = profileImageView.getDrawable();
                clickedDrawable = clickedImageView.getDrawable();
                clickedColors = clickedImageView.getBorderColors();
                final ParcelableAccount oldSelectedAccount = mAccountsAdapter.getSelectedAccount();
                if (oldSelectedAccount == null)
                    return;
                mMediaLoader.displayDashboardProfileImage(clickedImageView, oldSelectedAccount, profileDrawable);
                clickedImageView.setBorderColors(profileImageView.getBorderColors());

                displayAccountBanner(account);

                mSwitchAccountAnimationPlaying = true;
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                finishAnimation();
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                finishAnimation();
            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }

            private void finishAnimation() {
                final Editor editor = mPreferences.edit();
                editor.putString(KEY_DEFAULT_ACCOUNT_KEY, account.account_key.toString());
                editor.apply();
                mAccountsAdapter.setSelectedAccount(account);
                updateAccountActions();
                displayCurrentAccount(clickedDrawable);
                snapshotView.setVisibility(View.INVISIBLE);
                snapshotView.setImageDrawable(null);
                profileImageView.setImageDrawable(clickedDrawable);
                profileImageView.setBorderColors(clickedColors);
                profileImageView.setAlpha(1f);
                clickedImageView.setScaleX(1);
                clickedImageView.setScaleY(1);
                clickedImageView.setAlpha(1f);
                mSwitchAccountAnimationPlaying = false;
            }
        });
        set.start();

    }

    protected void displayAccountBanner(@NonNull ParcelableAccount account) {
        final int bannerWidth = mAccountProfileBannerView.getWidth();
        final Resources res = getResources();
        final int defWidth = res.getDisplayMetrics().widthPixels;
        final int width = bannerWidth > 0 ? bannerWidth : defWidth;
        final ImageView bannerView = (ImageView) mAccountProfileBannerView.getNextView();
        if (bannerView.getDrawable() == null || !CompareUtils.objectEquals(account, bannerView.getTag())) {
            mMediaLoader.displayProfileBanner(bannerView, account, width);
            bannerView.setTag(account);
        } else {
            mMediaLoader.cancelDisplayTask(bannerView);
        }
    }

    private void displayCurrentAccount(Drawable profileImageSnapshot) {
        final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
        if (account == null) {
            return;
        }
        mAccountProfileNameView.setText(account.name);
        mAccountProfileScreenNameView.setText(String.format("@%s", account.screen_name));
        mMediaLoader.displayDashboardProfileImage(mAccountProfileImageView, account, profileImageSnapshot);
        mAccountProfileImageView.setBorderColors(account.color);
        mAccountProfileBannerView.showNext();
    }

    private void updateDefaultAccountState() {
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
        if (account == null)
            return false;
        switch (item.getItemId()) {
        case R.id.search: {
            final Intent intent = new Intent(getActivity(), QuickSearchBarActivity.class);
            intent.putExtra(EXTRA_ACCOUNT_KEY, account.account_key);
            startActivity(intent);
            closeAccountsDrawer();
            break;
        }
        case R.id.compose: {
            final Intent composeIntent = new Intent(INTENT_ACTION_COMPOSE);
            composeIntent.setClass(getActivity(), ComposeActivity.class);
            composeIntent.putExtra(EXTRA_ACCOUNT_KEY, account.account_key);
            startActivity(composeIntent);
            break;
        }
        case R.id.favorites: {
            IntentUtils.openUserFavorites(getActivity(), account.account_key, account.account_key,
                    account.screen_name);
            break;
        }
        case R.id.lists: {
            IntentUtils.openUserLists(getActivity(), account.account_key, account.account_key, account.screen_name);
            break;
        }
        case R.id.groups: {
            IntentUtils.openUserGroups(getActivity(), account.account_key, account.account_key,
                    account.screen_name);
            break;
        }
        case R.id.public_timeline: {
            IntentUtils.openPublicTimeline(getActivity(), account.account_key);
            break;
        }
        case R.id.messages: {
            IntentUtils.openDirectMessages(getActivity(), account.account_key);
            break;
        }
        case R.id.interactions: {
            IntentUtils.openInteractions(getActivity(), account.account_key);
            break;
        }
        case R.id.edit: {
            IntentUtils.openProfileEditor(getActivity(), account.account_key);
            break;
        }
        case R.id.accounts: {
            IntentUtils.openAccountsManager(getActivity());
            closeAccountsDrawer();
            break;
        }
        case R.id.drafts: {
            IntentUtils.openDrafts(getActivity());
            closeAccountsDrawer();
            break;
        }
        case R.id.filters: {
            IntentUtils.openFilters(getActivity());
            closeAccountsDrawer();
            break;
        }
        case R.id.plus_service: {
            final Intent intent = new Intent(getActivity(), PlusServiceDashboardActivity.class);
            startActivity(intent);
            closeAccountsDrawer();
            break;
        }
        case R.id.settings: {
            final Intent intent = new Intent(getActivity(), SettingsActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
            startActivityForResult(intent, REQUEST_SETTINGS);
            closeAccountsDrawer();
            break;
        }
        }
        return false;
    }

    public void setStatusBarHeight(int height) {
        final int top = Utils.getInsetsTopWithoutActionBarHeight(getActivity(), height);
        mAccountProfileContainer.setPadding(0, top, 0, 0);
    }

    public RecyclerView getAccountsSelector() {
        return mAccountsSelector;
    }

    static class AccountProfileImageViewHolder extends ViewHolder implements OnClickListener {

        private final AccountSelectorAdapter adapter;
        private final ShapedImageView icon;

        public AccountProfileImageViewHolder(AccountSelectorAdapter adapter, View itemView) {
            super(itemView);
            this.adapter = adapter;
            itemView.setOnClickListener(this);
            icon = (ShapedImageView) itemView.findViewById(android.R.id.icon);
        }

        public ShapedImageView getIconView() {
            return icon;
        }

        @Override
        public void onClick(View v) {
            adapter.dispatchItemSelected(this);
        }
    }

    private static class AccountSelectorAdapter extends Adapter<AccountProfileImageViewHolder> {

        private final LayoutInflater mInflater;
        private final MediaLoaderWrapper mImageLoader;
        private final AccountsDashboardFragment mFragment;
        private ParcelableAccount[] mInternalAccounts;

        AccountSelectorAdapter(LayoutInflater inflater, AccountsDashboardFragment fragment) {
            mInflater = inflater;
            mImageLoader = fragment.mMediaLoader;
            mFragment = fragment;
            setHasStableIds(true);
        }

        private static int indexOfAccount(List<ParcelableAccount> accounts, UserKey accountId) {
            for (int i = 0, j = accounts.size(); i < j; i++) {
                if (accounts.get(i).account_key.equals(accountId))
                    return i;
            }
            return -1;
        }

        public ParcelableAccount getAdapterAccount(int adapterPosition) {
            if (mInternalAccounts == null || mInternalAccounts.length < 1) {
                return null;
            }
            return mInternalAccounts[adapterPosition + 1];
        }

        @Nullable
        public ParcelableAccount getSelectedAccount() {
            if (mInternalAccounts == null || mInternalAccounts.length == 0) {
                return null;
            }
            return mInternalAccounts[0];
        }

        @Nullable
        public UserKey getSelectedAccountKey() {
            final ParcelableAccount selectedAccount = getSelectedAccount();
            if (selectedAccount == null)
                return null;
            return selectedAccount.account_key;
        }

        public void setSelectedAccount(@Nullable ParcelableAccount account) {
            final ParcelableAccount selectedAccount = getSelectedAccount();
            if (selectedAccount == null || account == null)
                return;
            swap(account, selectedAccount);
        }

        @Override
        public AccountProfileImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            final View view = mInflater.inflate(R.layout.adapter_item_dashboard_account, parent, false);
            return new AccountProfileImageViewHolder(this, view);
        }

        @Override
        public void onBindViewHolder(AccountProfileImageViewHolder holder, int position) {
            final ParcelableAccount account = getAdapterAccount(position);
            mImageLoader.displayDashboardProfileImage(holder.icon, account, null);
            holder.icon.setBorderColor(account.color);
        }

        @Override
        public long getItemId(int position) {
            return getAdapterAccount(position).hashCode();
        }

        @Override
        public int getItemCount() {
            if (mInternalAccounts == null || mInternalAccounts.length == 0)
                return 0;
            return mInternalAccounts.length - 1;
        }

        public void setAccounts(ParcelableAccount[] accounts) {
            if (accounts != null) {
                final ParcelableAccount[] previousAccounts = mInternalAccounts;
                mInternalAccounts = new ParcelableAccount[accounts.length];
                int tempIdx = 0;
                final List<ParcelableAccount> tempList = new ArrayList<>();
                Collections.addAll(tempList, accounts);
                if (previousAccounts != null) {
                    for (ParcelableAccount previousAccount : previousAccounts) {
                        final int idx = indexOfAccount(tempList, previousAccount.account_key);
                        if (idx >= 0) {
                            mInternalAccounts[tempIdx++] = tempList.remove(idx);
                        }
                    }
                }
                for (ParcelableAccount account : tempList) {
                    mInternalAccounts[tempIdx++] = account;
                }
            } else {
                mInternalAccounts = null;
            }
            notifyDataSetChanged();
        }

        private void dispatchItemSelected(AccountProfileImageViewHolder holder) {
            mFragment.onAccountSelected(holder, getAdapterAccount(holder.getAdapterPosition()));
        }

        public ParcelableAccount[] getAccounts() {
            return mInternalAccounts;
        }

        private void swap(@NonNull ParcelableAccount from, @NonNull ParcelableAccount to) {
            int fromIdx = -1, toIdx = -1;
            for (int i = 0, j = mInternalAccounts.length; i < j; i++) {
                final ParcelableAccount account = mInternalAccounts[i];
                if (from.id == account.id) {
                    fromIdx = i;
                }
                if (to.id == account.id) {
                    toIdx = i;
                }
            }
            if (fromIdx < 0 || toIdx < 0)
                return;
            final ParcelableAccount temp = mInternalAccounts[toIdx];
            mInternalAccounts[toIdx] = mInternalAccounts[fromIdx];
            mInternalAccounts[fromIdx] = temp;
            notifyDataSetChanged();
        }
    }

    public static class OptionItem {

        private final int name, icon, id;

        OptionItem(final int name, final int icon, final int id) {
            this.name = name;
            this.icon = icon;
            this.id = id;
        }

        @Override
        public boolean equals(final Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof OptionItem))
                return false;
            final OptionItem other = (OptionItem) obj;
            if (icon != other.icon)
                return false;
            if (id != other.id)
                return false;
            return name == other.name;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + icon;
            result = prime * result + id;
            result = prime * result + name;
            return result;
        }

        @Override
        public String toString() {
            return "AccountOption{name=" + name + ", icon=" + icon + ", id=" + id + "}";
        }

    }

}