Twidere-App-Android-Twitter.../twidere/src/main/java/org/mariotaku/twidere/fragment/support/AccountsDashboardFragment.java

925 lines
39 KiB
Java

/*
* 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.support;
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.PorterDuff.Mode;
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.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.content.res.ResourcesCompat;
import android.support.v4.util.LongSparseArray;
import android.support.v4.util.Pair;
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.ContextThemeWrapper;
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.AdapterView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.commonsware.cwac.merge.MergeAdapter;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.SettingsActivity;
import org.mariotaku.twidere.activity.iface.IThemedActivity;
import org.mariotaku.twidere.activity.support.ComposeActivity;
import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.activity.support.QuickSearchBarActivity;
import org.mariotaku.twidere.adapter.ArrayAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.menu.support.AccountToggleProvider;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
import org.mariotaku.twidere.util.ListViewUtils;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TransitionUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.SupportFragmentReloadCursorObserver;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.view.ShapedImageView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
public class AccountsDashboardFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
OnSharedPreferenceChangeListener, ImageLoadingListener, OnClickListener, KeyboardShortcutCallback, AdapterView.OnItemClickListener {
private final Rect mSystemWindowsInsets = new Rect();
private ContentResolver mResolver;
private MergeAdapter mAdapter;
private AccountSelectorAdapter mAccountsAdapter;
private AccountOptionsAdapter mAccountOptionsAdapter;
private AppMenuAdapter mAppMenuAdapter;
private ListView mListView;
private View mAccountSelectorView;
private RecyclerView mAccountsSelector;
private ImageView mAccountProfileBannerView;
private ImageView mFloatingProfileImageSnapshotView;
private ShapedImageView mAccountProfileImageView;
private TextView mAccountProfileNameView, mAccountProfileScreenNameView;
private ActionMenuView mAccountsToggleMenu;
private View mAccountProfileContainer;
private View mNoAccountContainer;
private Context mThemedContext;
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;
public long[] getActivatedAccountIds() {
if (mAccountActionProvider != null) {
return mAccountActionProvider.getActivatedAccountIds();
}
return DataStoreUtils.getActivatedAccountIds(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 firstVisiblePosition = ListViewUtils.getFirstFullyVisiblePosition(mListView);
final int selectedItem = mListView.getSelectedItemPosition();
final int count = mListView.getCount();
int resultPosition;
if (!mListView.isFocused() || selectedItem == ListView.INVALID_POSITION) {
resultPosition = firstVisiblePosition;
} else {
resultPosition = selectedItem + offset;
while (resultPosition >= 0 && resultPosition < count && !mAdapter.isEnabled(resultPosition)) {
resultPosition += offset;
}
}
final View focusedChild = mListView.getFocusedChild();
if (focusedChild == null) {
mListView.requestChildFocus(mListView.getChildAt(0), null);
}
if (resultPosition >= 0 && resultPosition < count) {
mListView.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 instanceof IThemedActivity) {
((IThemedActivity) activity).restart();
}
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();
final Bundle activityOption = Utils.makeSceneTransitionOption(activity,
new Pair<View, String>(mAccountProfileImageView, UserFragment.TRANSITION_NAME_PROFILE_IMAGE));
Utils.openUserProfile(activity, account.account_id, account.account_id,
account.screen_name, activityOption);
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 = ParcelableAccount.getAccounts(cursor);
if (accounts.length > 0) {
mNoAccountContainer.setVisibility(View.GONE);
mAccountProfileContainer.setVisibility(View.VISIBLE);
} else {
mNoAccountContainer.setVisibility(View.VISIBLE);
mAccountProfileContainer.setVisibility(View.INVISIBLE);
}
long defaultId = -1;
for (ParcelableAccount account : accounts) {
if (account.is_activated) {
defaultId = account.account_id;
break;
}
}
mAccountsAdapter.setAccounts(accounts);
mAccountsAdapter.setSelectedAccountId(mPreferences.getLong(KEY_DEFAULT_ACCOUNT_ID, defaultId));
mAccountOptionsAdapter.setSelectedAccount(mAccountsAdapter.getSelectedAccount());
if (mAccountActionProvider != null) {
mAccountActionProvider.setExclusive(false);
mAccountActionProvider.setAccounts(accounts);
}
initAccountActionsAdapter(accounts);
updateAccountOptionsSeparatorLabel(null);
updateDefaultAccountState();
}
@Override
public void onLoaderReset(final Loader<Cursor> loader) {
}
@Override
public void onItemClick(final AdapterView<?> parent, final View v, final int position, final long id) {
final ListAdapter adapter = mAdapter.getAdapter(position);
final Object item = mAdapter.getItem(position);
if (adapter instanceof AccountOptionsAdapter) {
final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
if (account == null || !(item instanceof OptionItem)) return;
final OptionItem option = (OptionItem) item;
switch (option.id) {
case R.id.search: {
final Intent intent = new Intent(getActivity(), QuickSearchBarActivity.class);
intent.putExtra(EXTRA_ACCOUNT_ID, account.account_id);
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_IDS, new long[]{account.account_id});
startActivity(composeIntent);
break;
}
case R.id.favorites: {
Utils.openUserFavorites(getActivity(), account.account_id, account.account_id, account.screen_name);
break;
}
case R.id.lists: {
Utils.openUserLists(getActivity(), account.account_id, account.account_id, account.screen_name);
break;
}
case R.id.edit: {
Utils.openProfileEditor(getActivity(), account.account_id);
break;
}
}
} else if (adapter instanceof AppMenuAdapter) {
if (!(item instanceof OptionItem)) return;
final OptionItem option = (OptionItem) item;
switch (option.id) {
case R.id.accounts: {
Utils.openAccountsManager(getActivity());
break;
}
case R.id.drafts: {
Utils.openDrafts(getActivity());
break;
}
case R.id.filters: {
Utils.openFilters(getActivity());
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);
break;
}
}
closeAccountsDrawer();
}
}
@Override
public void onLoadingStarted(String imageUri, View view) {
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
view.setTag(imageUri);
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
if (KEY_DEFAULT_ACCOUNT_ID.equals(key)) {
updateDefaultAccountState();
}
}
public void setStatusBarHeight(int height) {
mAccountProfileContainer.setPadding(0, height, 0, 0);
}
@Override
protected void fitSystemWindows(Rect insets) {
mSystemWindowsInsets.set(insets);
updateSystemWindowsInsets();
}
private void updateSystemWindowsInsets() {
if (mAccountProfileContainer == null) return;
final HomeActivity activity = (HomeActivity) getActivity();
final Rect insets = mSystemWindowsInsets;
if (!activity.getDefaultSystemWindowsInsets(insets)) return;
final int top = Utils.getInsetsTopWithoutActionBarHeight(getActivity(), insets.top);
mAccountProfileContainer.setPadding(0, top, 0, 0);
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mResolver = getContentResolver();
final View view = getView();
assert view != null;
final Context context = view.getContext();
mListView.setItemsCanFocus(true);
mAdapter = new MergeAdapter();
final LayoutInflater inflater = getLayoutInflater(savedInstanceState);
mAccountsAdapter = new AccountSelectorAdapter(context, inflater, this);
mAccountOptionsAdapter = new AccountOptionsAdapter(context);
mAppMenuAdapter = new AppMenuAdapter(context);
mAccountSelectorView = inflater.inflate(R.layout.header_drawer_account_selector, mListView, false);
mAccountsSelector = (RecyclerView) mAccountSelectorView.findViewById(R.id.other_accounts_list);
final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
layoutManager.setStackFromEnd(true);
mAccountsSelector.setLayoutManager(layoutManager);
mAccountsSelector.setAdapter(mAccountsAdapter);
mAccountsSelector.setItemAnimator(null);
mAccountProfileContainer = mAccountSelectorView.findViewById(R.id.profile_container);
mNoAccountContainer = mAccountSelectorView.findViewById(R.id.no_account_container);
mAccountProfileImageView = (ShapedImageView) mAccountSelectorView.findViewById(R.id.profile_image);
mAccountProfileBannerView = (ImageView) 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);
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_IDS, new long[]{account.account_id});
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_id, newActivated);
values.put(Accounts.IS_ACTIVATED, newActivated);
final String where = Expression.equals(Accounts.ACCOUNT_ID, account.account_id).getSQL();
mResolver.update(Accounts.CONTENT_URI, values, where, null);
return true;
}
});
mAccountProfileContainer.setOnClickListener(this);
mAdapter.addView(mAccountSelectorView, true);
mAdapter.addAdapter(mAccountOptionsAdapter);
mAdapter.addView(inflater.inflate(R.layout.layout_divider_drawer, mListView, false), false);
mAdapter.addAdapter(mAppMenuAdapter);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
mPreferences.registerOnSharedPreferenceChangeListener(this);
getLoaderManager().initLoader(0, null, this);
updateSystemWindowsInsets();
}
@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 onBaseViewCreated(View view, Bundle savedInstanceState) {
super.onBaseViewCreated(view, savedInstanceState);
mListView = (ListView) view.findViewById(android.R.id.list);
}
@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 initAccountActionsAdapter(ParcelableAccount[] accounts) {
mAccountOptionsAdapter.clear();
mAccountOptionsAdapter.add(new OptionItem(android.R.string.search_go, R.drawable.ic_action_search,
R.id.search));
if (mPreferences.getBoolean(KEY_I_WANT_MY_STARS_BACK)) {
mAccountOptionsAdapter.add(new OptionItem(R.string.favorites, R.drawable.ic_action_star,
R.id.favorites));
} else {
mAccountOptionsAdapter.add(new OptionItem(R.string.likes, R.drawable.ic_action_heart,
R.id.favorites));
}
mAccountOptionsAdapter.add(new OptionItem(R.string.lists, R.drawable.ic_action_list, R.id.lists));
}
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());
}
@Override
public Context getThemedContext() {
if (mThemedContext != null) return mThemedContext;
final Context context = getActivity();
final int themeResource = ThemeUtils.getDrawerThemeResource(context);
return mThemedContext = new ContextThemeWrapper(context, themeResource);
}
private void onAccountSelected(AccountProfileImageViewHolder holder, 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();
mMediaLoader.displayDashboardProfileImage(clickedImageView,
oldSelectedAccount.profile_image_url, profileDrawable);
// mMediaLoader.displayDashboardProfileImage(profileImageView,
// account.profile_image_url, clickedDrawable);
clickedImageView.setBorderColors(profileImageView.getBorderColors());
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.putLong(KEY_DEFAULT_ACCOUNT_ID, account.account_id);
editor.apply();
mAccountsAdapter.setSelectedAccountId(account.account_id);
mAccountOptionsAdapter.setSelectedAccount(account);
updateAccountOptionsSeparatorLabel(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();
}
private void updateAccountOptionsSeparatorLabel(Drawable profileImageSnapshot) {
final ParcelableAccount account = mAccountsAdapter.getSelectedAccount();
if (account == null) {
return;
}
mAccountProfileNameView.setText(account.name);
mAccountProfileScreenNameView.setText("@" + account.screen_name);
mMediaLoader.displayDashboardProfileImage(mAccountProfileImageView,
account.profile_image_url, profileImageSnapshot);
mAccountProfileImageView.setBorderColors(account.color);
final int bannerWidth = mAccountProfileBannerView.getWidth();
final Resources res = getResources();
final int defWidth = res.getDisplayMetrics().widthPixels;
final int width = bannerWidth > 0 ? bannerWidth : defWidth;
final String bannerUrl = TwitterContentUtils.getBestBannerUrl(account.profile_banner_url, width);
final ImageView bannerView = mAccountProfileBannerView;
if (bannerView.getDrawable() == null || !CompareUtils.objectEquals(bannerUrl, bannerView.getTag())) {
mMediaLoader.displayProfileBanner(mAccountProfileBannerView, bannerUrl, this);
} else {
mMediaLoader.cancelDisplayTask(mAccountProfileBannerView);
}
}
private void updateDefaultAccountState() {
}
public static final class AccountOptionsAdapter extends OptionItemsAdapter {
private final boolean mNameFirst;
private ParcelableAccount mSelectedAccount;
AccountOptionsAdapter(final Context context) {
super(context);
mNameFirst = mPreferences.getBoolean(KEY_NAME_FIRST);
}
public void setSelectedAccount(ParcelableAccount account) {
mSelectedAccount = account;
notifyDataSetChanged();
}
@Override
public boolean isEnabled(final int position) {
return mSelectedAccount != null;
}
@Override
protected String getTitle(int position, OptionItem option) {
final ParcelableAccount account = mSelectedAccount;
if (account != null && option.id == R.id.compose) {
final Context context = getContext();
final String displayName = mUserColorNameManager.getDisplayName(-1, account.name,
account.screen_name, mNameFirst, false);
return context.getString(R.string.tweet_from_name, displayName);
}
return super.getTitle(position, option);
}
}
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 final LongSparseArray<Long> positionMap = new LongSparseArray<>();
private ParcelableAccount[] mInternalAccounts;
AccountSelectorAdapter(Context context, LayoutInflater inflater, AccountsDashboardFragment fragment) {
mInflater = inflater;
mImageLoader = fragment.mMediaLoader;
mFragment = fragment;
setHasStableIds(true);
}
private static int indexOfAccount(List<ParcelableAccount> accounts, long accountId) {
for (int i = 0, j = accounts.size(); i < j; i++) {
if (accounts.get(i).account_id == 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];
}
public long getSelectedAccountId() {
final ParcelableAccount selectedAccount = getSelectedAccount();
if (selectedAccount == null) return -1;
return selectedAccount.account_id;
}
public void setSelectedAccountId(long accountId) {
final ParcelableAccount selectedAccount = getSelectedAccount();
if (selectedAccount == null) return;
swap(accountId, selectedAccount.account_id);
}
@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) {
// holder.itemView.setAlpha(c.getInt(mIndices.is_activated) == 1 ? 1 : 0.5f);
final ParcelableAccount account = getAdapterAccount(position);
// holder.icon.setImageDrawable(null);
mImageLoader.displayDashboardProfileImage(holder.icon, account.profile_image_url, null);
holder.icon.setBorderColor(account.color);
}
@Override
public long getItemId(int position) {
return getAdapterAccount(position).account_id;
}
@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_id);
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()));
}
private void swap(long fromId, long toId) {
int fromIdx = -1, toIdx = -1;
for (int i = 0, j = mInternalAccounts.length; i < j; i++) {
final ParcelableAccount account = mInternalAccounts[i];
if (account.account_id == fromId) {
fromIdx = i;
}
if (account.account_id == toId) {
toIdx = i;
}
}
if (fromIdx < 0 || toIdx < 0) return;
final ParcelableAccount temp = mInternalAccounts[toIdx];
mInternalAccounts[toIdx] = mInternalAccounts[fromIdx];
mInternalAccounts[fromIdx] = temp;
notifyDataSetChanged();
}
}
private static final class AppMenuAdapter extends OptionItemsAdapter {
public AppMenuAdapter(final Context context) {
super(context);
add(new OptionItem(R.string.accounts, R.drawable.ic_action_accounts, R.id.accounts));
add(new OptionItem(R.string.drafts, R.drawable.ic_action_draft, R.id.drafts));
add(new OptionItem(R.string.filters, R.drawable.ic_action_speaker_muted, R.id.filters));
add(new OptionItem(R.string.settings, R.drawable.ic_action_settings, R.id.settings));
}
}
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 + "}";
}
}
public static abstract class OptionItemsAdapter extends ArrayAdapter<OptionItem> {
@Inject
UserColorNameManager mUserColorNameManager;
@Inject
SharedPreferencesWrapper mPreferences;
private final int mActionIconColor;
OptionItemsAdapter(final Context context) {
super(context, R.layout.list_item_dashboard_menu);
GeneralComponentHelper.build(context).inject(this);
mActionIconColor = ThemeUtils.getThemeForegroundColor(context);
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final OptionItem option = getItem(position);
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
text1.setText(getTitle(position, option));
icon.setImageDrawable(ResourcesCompat.getDrawable(icon.getResources(), option.icon, null));
icon.setColorFilter(mActionIconColor, Mode.SRC_ATOP);
return view;
}
protected String getTitle(int position, OptionItem option) {
return getContext().getString(option.name);
}
}
}