997 lines
41 KiB
Java
997 lines
41 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.activity.support;
|
|
|
|
import android.app.ActivityManager;
|
|
import android.app.NotificationManager;
|
|
import android.app.PendingIntent;
|
|
import android.app.SearchManager;
|
|
import android.content.ContentResolver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.SharedPreferences;
|
|
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
|
import android.database.ContentObserver;
|
|
import android.graphics.PorterDuff.Mode;
|
|
import android.graphics.Rect;
|
|
import android.net.Uri;
|
|
import android.os.AsyncTask;
|
|
import android.os.Build;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.support.annotation.NonNull;
|
|
import android.support.v4.app.Fragment;
|
|
import android.support.v4.app.FragmentManager;
|
|
import android.support.v4.app.NotificationCompat;
|
|
import android.support.v4.view.GravityCompat;
|
|
import android.support.v4.view.ViewCompat;
|
|
import android.support.v4.view.ViewPager;
|
|
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
|
import android.support.v4.widget.DrawerLayout;
|
|
import android.support.v4.widget.DrawerLayoutTrojan;
|
|
import android.support.v7.widget.Toolbar;
|
|
import android.view.Gravity;
|
|
import android.view.KeyEvent;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
import android.view.View.OnClickListener;
|
|
import android.view.View.OnLongClickListener;
|
|
import android.view.ViewGroup;
|
|
import android.view.ViewGroup.MarginLayoutParams;
|
|
import android.view.Window;
|
|
import android.view.WindowManager;
|
|
import android.widget.FrameLayout;
|
|
import android.widget.FrameLayout.LayoutParams;
|
|
import android.widget.Toast;
|
|
|
|
import com.meizu.flyme.reflect.StatusBarProxy;
|
|
import com.squareup.otto.Bus;
|
|
import com.squareup.otto.Subscribe;
|
|
|
|
import org.apache.commons.lang3.ArrayUtils;
|
|
import org.mariotaku.twidere.R;
|
|
import org.mariotaku.twidere.activity.SettingsActivity;
|
|
import org.mariotaku.twidere.activity.SettingsWizardActivity;
|
|
import org.mariotaku.twidere.activity.UsageStatisticsActivity;
|
|
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
|
|
import org.mariotaku.twidere.app.TwidereApplication;
|
|
import org.mariotaku.twidere.fragment.CustomTabsFragment;
|
|
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
|
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
|
|
import org.mariotaku.twidere.fragment.support.AccountsDashboardFragment;
|
|
import org.mariotaku.twidere.fragment.support.DirectMessagesFragment;
|
|
import org.mariotaku.twidere.fragment.support.TrendsSuggestionsFragment;
|
|
import org.mariotaku.twidere.graphic.EmptyDrawable;
|
|
import org.mariotaku.twidere.model.ParcelableAccount;
|
|
import org.mariotaku.twidere.model.SupportTabSpec;
|
|
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
|
import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
|
|
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
|
import org.mariotaku.twidere.service.StreamingService;
|
|
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
|
import org.mariotaku.twidere.util.CustomTabUtils;
|
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
|
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
|
import org.mariotaku.twidere.util.MathUtils;
|
|
import org.mariotaku.twidere.util.MultiSelectEventHandler;
|
|
import org.mariotaku.twidere.util.ParseUtils;
|
|
import org.mariotaku.twidere.util.ReadStateManager;
|
|
import org.mariotaku.twidere.util.ThemeUtils;
|
|
import org.mariotaku.twidere.util.TwidereColorUtils;
|
|
import org.mariotaku.twidere.util.Utils;
|
|
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
|
|
import org.mariotaku.twidere.util.message.UnreadCountUpdatedEvent;
|
|
import org.mariotaku.twidere.util.support.ActivitySupport;
|
|
import org.mariotaku.twidere.util.support.ActivitySupport.TaskDescriptionCompat;
|
|
import org.mariotaku.twidere.util.support.ViewSupport;
|
|
import org.mariotaku.twidere.util.support.view.ViewOutlineProviderCompat;
|
|
import org.mariotaku.twidere.view.ExtendedViewPager;
|
|
import org.mariotaku.twidere.view.TabPagerIndicator;
|
|
import org.mariotaku.twidere.view.TintedStatusFrameLayout;
|
|
import org.mariotaku.twidere.view.iface.IHomeActionButton;
|
|
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Map.Entry;
|
|
|
|
import edu.tsinghua.hotmobi.HotMobiLogger;
|
|
import edu.tsinghua.hotmobi.model.SessionEvent;
|
|
|
|
import static org.mariotaku.twidere.util.CompareUtils.classEquals;
|
|
import static org.mariotaku.twidere.util.Utils.cleanDatabasesByItemLimit;
|
|
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;
|
|
import static org.mariotaku.twidere.util.Utils.getTabDisplayOptionInt;
|
|
import static org.mariotaku.twidere.util.Utils.isDatabaseReady;
|
|
import static org.mariotaku.twidere.util.Utils.openMessageConversation;
|
|
import static org.mariotaku.twidere.util.Utils.openSearch;
|
|
import static org.mariotaku.twidere.util.Utils.showMenuItemToast;
|
|
|
|
public class HomeActivity extends BaseAppCompatActivity implements OnClickListener, OnPageChangeListener,
|
|
SupportFragmentCallback, OnLongClickListener {
|
|
|
|
private static final String EXTRA_SESSION_EVENT = "session_event";
|
|
private final Handler mHandler = new Handler();
|
|
|
|
private final ContentObserver mAccountChangeObserver = new AccountChangeObserver(this, mHandler);
|
|
|
|
private ParcelableAccount mSelectedAccountToSearch;
|
|
|
|
private SharedPreferences mPreferences;
|
|
|
|
|
|
private NotificationManager mNotificationManager;
|
|
|
|
private MultiSelectEventHandler mMultiSelectHandler;
|
|
|
|
private SupportTabsAdapter mPagerAdapter;
|
|
|
|
private ExtendedViewPager mViewPager;
|
|
private TabPagerIndicator mTabIndicator;
|
|
private DrawerLayout mDrawerLayout;
|
|
private View mEmptyTabHint;
|
|
private View mActionsButton;
|
|
private View mActionBarWithOverlay;
|
|
private TintedStatusFrameLayout mHomeContent;
|
|
|
|
private UpdateUnreadCountTask mUpdateUnreadCountTask;
|
|
|
|
private Toolbar mActionBar;
|
|
|
|
private OnSharedPreferenceChangeListener mReadStateChangeListener = new OnSharedPreferenceChangeListener() {
|
|
@Override
|
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
|
updateUnreadCount();
|
|
}
|
|
};
|
|
private ControlBarShowHideHelper mControlBarShowHideHelper = new ControlBarShowHideHelper(this);
|
|
private int mTabColumns;
|
|
private View mActionBarContainer;
|
|
private SessionEvent mSessionEvent;
|
|
|
|
public void closeAccountsDrawer() {
|
|
if (mDrawerLayout == null) return;
|
|
mDrawerLayout.closeDrawers();
|
|
}
|
|
|
|
public long[] getActivatedAccountIds() {
|
|
final Fragment fragment = getLeftDrawerFragment();
|
|
if (fragment instanceof AccountsDashboardFragment) {
|
|
return ((AccountsDashboardFragment) fragment).getActivatedAccountIds();
|
|
}
|
|
return Utils.getActivatedAccountIds(this);
|
|
}
|
|
|
|
@Override
|
|
public Fragment getCurrentVisibleFragment() {
|
|
final int currentItem = mViewPager.getCurrentItem();
|
|
if (currentItem < 0 || currentItem >= mPagerAdapter.getCount()) return null;
|
|
return (Fragment) mPagerAdapter.instantiateItem(mViewPager, currentItem);
|
|
}
|
|
|
|
@Override
|
|
public boolean triggerRefresh(final int position) {
|
|
final Fragment f = (Fragment) mPagerAdapter.instantiateItem(mViewPager, position);
|
|
if (!(f instanceof RefreshScrollTopInterface)) return false;
|
|
if (f.getActivity() == null || f.isDetached()) return false;
|
|
return ((RefreshScrollTopInterface) f).triggerRefresh();
|
|
}
|
|
|
|
public Fragment getLeftDrawerFragment() {
|
|
return getSupportFragmentManager().findFragmentById(R.id.left_drawer);
|
|
}
|
|
|
|
public boolean getDefaultSystemWindowsInsets(Rect insets) {
|
|
return super.getSystemWindowsInsets(insets);
|
|
}
|
|
|
|
@Override
|
|
public boolean getSystemWindowsInsets(Rect insets) {
|
|
final int height = mTabIndicator != null ? mTabIndicator.getHeight() : 0;
|
|
insets.top = (height != 0 ? height : ThemeUtils.getActionBarHeight(this));
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void setControlBarVisibleAnimate(boolean visible) {
|
|
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
|
|
}
|
|
|
|
@Override
|
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
|
switch (item.getItemId()) {
|
|
case android.R.id.home: {
|
|
final FragmentManager fm = getSupportFragmentManager();
|
|
final int count = fm.getBackStackEntryCount();
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.START) || mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
|
|
mDrawerLayout.closeDrawers();
|
|
return true;
|
|
} else if (count == 0) {
|
|
mDrawerLayout.openDrawer(GravityCompat.START);
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
case R.id.search: {
|
|
openSearchView(mSelectedAccountToSearch);
|
|
return true;
|
|
}
|
|
case R.id.actions: {
|
|
triggerActionsClick();
|
|
return true;
|
|
}
|
|
}
|
|
return super.onOptionsItemSelected(item);
|
|
}
|
|
|
|
@Override
|
|
public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
|
|
if (handleFragmentKeyboardShortcutSingle(handler, keyCode, event)) return true;
|
|
String action = handler.getKeyAction(CONTEXT_TAG_HOME, keyCode, event);
|
|
if (action != null) {
|
|
switch (action) {
|
|
case ACTION_HOME_ACCOUNTS_DASHBOARD: {
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
|
|
mDrawerLayout.closeDrawers();
|
|
} else {
|
|
mDrawerLayout.openDrawer(GravityCompat.START);
|
|
setControlBarVisibleAnimate(true);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event);
|
|
if (action != null) {
|
|
switch (action) {
|
|
case ACTION_NAVIGATION_PREVIOUS_TAB: {
|
|
final int previous = mViewPager.getCurrentItem() - 1;
|
|
if (previous < 0 && DrawerLayoutTrojan.findDrawerWithGravity(mDrawerLayout, Gravity.START) != null) {
|
|
mDrawerLayout.openDrawer(GravityCompat.START);
|
|
setControlBarVisibleAnimate(true);
|
|
} else if (previous < mPagerAdapter.getCount()) {
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
|
|
mDrawerLayout.closeDrawers();
|
|
} else {
|
|
mViewPager.setCurrentItem(previous, true);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
case ACTION_NAVIGATION_NEXT_TAB: {
|
|
final int next = mViewPager.getCurrentItem() + 1;
|
|
if (next >= mPagerAdapter.getCount() && DrawerLayoutTrojan.findDrawerWithGravity(mDrawerLayout, Gravity.END) != null) {
|
|
mDrawerLayout.openDrawer(GravityCompat.END);
|
|
setControlBarVisibleAnimate(true);
|
|
} else if (next >= 0) {
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
|
|
mDrawerLayout.closeDrawers();
|
|
} else {
|
|
mViewPager.setCurrentItem(next, true);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return handler.handleKey(this, null, keyCode, event);
|
|
}
|
|
|
|
@Override
|
|
public boolean isKeyboardShortcutHandled(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) {
|
|
if (isFragmentKeyboardShortcutHandled(handler, keyCode, event)) return true;
|
|
return super.isKeyboardShortcutHandled(handler, keyCode, event);
|
|
}
|
|
|
|
@Override
|
|
public boolean handleKeyboardShortcutRepeat(@NonNull KeyboardShortcutsHandler handler, int keyCode, int repeatCount, @NonNull KeyEvent event) {
|
|
if (handleFragmentKeyboardShortcutRepeat(handler, keyCode, repeatCount, event)) return true;
|
|
return super.handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
|
|
}
|
|
|
|
@Override
|
|
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
|
switch (keyCode) {
|
|
case KeyEvent.KEYCODE_MENU: {
|
|
final DrawerLayout drawer = mDrawerLayout;
|
|
if (isDrawerOpen()) {
|
|
drawer.closeDrawers();
|
|
} else {
|
|
drawer.openDrawer(Gravity.LEFT);
|
|
}
|
|
return true;
|
|
}
|
|
case KeyEvent.KEYCODE_BACK: {
|
|
final DrawerLayout drawer = mDrawerLayout;
|
|
if (isDrawerOpen()) {
|
|
drawer.closeDrawers();
|
|
} else {
|
|
onBackPressed();
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
return super.onKeyUp(keyCode, event);
|
|
}
|
|
|
|
private boolean isDrawerOpen() {
|
|
final DrawerLayout drawer = mDrawerLayout;
|
|
if (drawer == null) return false;
|
|
return drawer.isDrawerOpen(GravityCompat.START) || drawer.isDrawerOpen(GravityCompat.END);
|
|
}
|
|
|
|
/**
|
|
* Called when the context is first created.
|
|
*/
|
|
@Override
|
|
protected void onCreate(final Bundle savedInstanceState) {
|
|
final Window window = getWindow();
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
|
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
|
|
}
|
|
super.onCreate(savedInstanceState);
|
|
if (!isDatabaseReady(this)) {
|
|
Toast.makeText(this, R.string.preparing_database_toast, Toast.LENGTH_SHORT).show();
|
|
finish();
|
|
return;
|
|
}
|
|
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
final TwidereApplication app = TwidereApplication.getInstance(this);
|
|
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
mMultiSelectHandler = new MultiSelectEventHandler(this);
|
|
mMultiSelectHandler.dispatchOnCreate();
|
|
if (!Utils.hasAccount(this)) {
|
|
final Intent signInIntent = new Intent(INTENT_ACTION_TWITTER_LOGIN);
|
|
signInIntent.setClass(this, SignInActivity.class);
|
|
startActivity(signInIntent);
|
|
finish();
|
|
return;
|
|
} else {
|
|
notifyAccountsChanged();
|
|
}
|
|
final Intent intent = getIntent();
|
|
if (openSettingsWizard()) {
|
|
finish();
|
|
return;
|
|
}
|
|
setContentView(R.layout.activity_home);
|
|
setSupportActionBar(mActionBar);
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONCREATE));
|
|
final boolean refreshOnStart = mPreferences.getBoolean(KEY_REFRESH_ON_START, false);
|
|
int tabDisplayOptionInt = getTabDisplayOptionInt(this);
|
|
|
|
mTabColumns = getResources().getInteger(R.integer.default_tab_columns);
|
|
|
|
mHomeContent.setOnFitSystemWindowsListener(this);
|
|
mPagerAdapter = new SupportTabsAdapter(this, getSupportFragmentManager(), mTabIndicator, mTabColumns);
|
|
mViewPager.setAdapter(mPagerAdapter);
|
|
// mViewPager.setOffscreenPageLimit(3);
|
|
mTabIndicator.setViewPager(mViewPager);
|
|
mTabIndicator.setOnPageChangeListener(this);
|
|
mTabIndicator.setColumns(mTabColumns);
|
|
if (tabDisplayOptionInt == 0) {
|
|
tabDisplayOptionInt = TabPagerIndicator.ICON;
|
|
}
|
|
mTabIndicator.setTabDisplayOption(tabDisplayOptionInt);
|
|
mTabIndicator.setTabExpandEnabled((tabDisplayOptionInt & TabPagerIndicator.LABEL) == 0);
|
|
mTabIndicator.setDisplayBadge(mPreferences.getBoolean(KEY_UNREAD_COUNT, true));
|
|
mTabIndicator.updateAppearance();
|
|
|
|
mActionsButton.setOnClickListener(this);
|
|
mActionsButton.setOnLongClickListener(this);
|
|
mEmptyTabHint.setOnClickListener(this);
|
|
|
|
ThemeUtils.setCompatContentViewOverlay(this, new EmptyDrawable());
|
|
ViewCompat.setElevation(mActionBarContainer, ThemeUtils.getSupportActionBarElevation(this));
|
|
ViewSupport.setOutlineProvider(mActionBarContainer, ViewOutlineProviderCompat.BACKGROUND);
|
|
final View windowOverlay = findViewById(R.id.window_overlay);
|
|
ViewSupport.setBackground(windowOverlay, ThemeUtils.getNormalWindowContentOverlay(this, getCurrentThemeResourceId()));
|
|
|
|
setupSlidingMenu();
|
|
setupBars();
|
|
showDataProfilingRequest();
|
|
initUnreadCount();
|
|
updateActionsButton();
|
|
updateSlidingMenuTouchMode();
|
|
|
|
if (savedInstanceState == null) {
|
|
if (refreshOnStart) {
|
|
mTwitterWrapper.refreshAll(getActivatedAccountIds());
|
|
}
|
|
if (intent.getBooleanExtra(EXTRA_OPEN_ACCOUNTS_DRAWER, false)) {
|
|
openAccountsDrawer();
|
|
}
|
|
}
|
|
setupHomeTabs();
|
|
|
|
final int initialTabPosition = handleIntent(intent, savedInstanceState == null);
|
|
setTabPosition(initialTabPosition);
|
|
|
|
if (Utils.isStreamingEnabled()) {
|
|
startService(new Intent(this, StreamingService.class));
|
|
}
|
|
|
|
if (savedInstanceState != null) {
|
|
mSessionEvent = savedInstanceState.getParcelable(EXTRA_SESSION_EVENT);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onStart() {
|
|
super.onStart();
|
|
mMultiSelectHandler.dispatchOnStart();
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONSTART));
|
|
final ContentResolver resolver = getContentResolver();
|
|
resolver.registerContentObserver(Accounts.CONTENT_URI, true, mAccountChangeObserver);
|
|
final Bus bus = TwidereApplication.getInstance(this).getMessageBus();
|
|
assert bus != null;
|
|
bus.register(this);
|
|
// BEGIN HotMobi
|
|
if (mSessionEvent == null) {
|
|
mSessionEvent = SessionEvent.create(this);
|
|
}
|
|
// END HotMobi
|
|
mReadStateManager.registerOnSharedPreferenceChangeListener(mReadStateChangeListener);
|
|
updateUnreadCount();
|
|
}
|
|
|
|
@Override
|
|
protected void onResume() {
|
|
super.onResume();
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONRESUME));
|
|
invalidateOptionsMenu();
|
|
updateActionsButtonStyle();
|
|
updateActionsButton();
|
|
updateSlidingMenuTouchMode();
|
|
}
|
|
|
|
@Override
|
|
protected void onPause() {
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONPAUSE));
|
|
super.onPause();
|
|
}
|
|
|
|
@Override
|
|
protected void onStop() {
|
|
mMultiSelectHandler.dispatchOnStop();
|
|
mReadStateManager.unregisterOnSharedPreferenceChangeListener(mReadStateChangeListener);
|
|
final Bus bus = TwidereApplication.getInstance(this).getMessageBus();
|
|
assert bus != null;
|
|
bus.unregister(this);
|
|
final ContentResolver resolver = getContentResolver();
|
|
resolver.unregisterContentObserver(mAccountChangeObserver);
|
|
mPreferences.edit().putInt(KEY_SAVED_TAB_POSITION, mViewPager.getCurrentItem()).apply();
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONSTOP));
|
|
|
|
// BEGIN HotMobi
|
|
final SessionEvent event = mSessionEvent;
|
|
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
|
|
if (event != null && isFinishing()) {
|
|
event.markEnd();
|
|
HotMobiLogger.getInstance(this).log(event);
|
|
}
|
|
// END HotMobi
|
|
super.onStop();
|
|
}
|
|
|
|
public ViewPager getViewPager() {
|
|
return mViewPager;
|
|
}
|
|
|
|
public void notifyAccountsChanged() {
|
|
}
|
|
|
|
@Override
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
super.onSaveInstanceState(outState);
|
|
outState.putParcelable(EXTRA_SESSION_EVENT, mSessionEvent);
|
|
}
|
|
|
|
@Subscribe
|
|
public void notifyTaskStateChanged(TaskStateChangedEvent event) {
|
|
updateActionsButton();
|
|
}
|
|
|
|
@Subscribe
|
|
public void notifyUnreadCountUpdated(UnreadCountUpdatedEvent event) {
|
|
updateUnreadCount();
|
|
}
|
|
|
|
@Override
|
|
public void onClick(final View v) {
|
|
switch (v.getId()) {
|
|
case R.id.actions_button: {
|
|
triggerActionsClick();
|
|
break;
|
|
}
|
|
case R.id.empty_tab_hint: {
|
|
final Intent intent = new Intent(this, SettingsActivity.class);
|
|
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, CustomTabsFragment.class.getName());
|
|
intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE, R.string.tabs);
|
|
startActivityForResult(intent, REQUEST_SETTINGS);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onLongClick(final View v) {
|
|
switch (v.getId()) {
|
|
case R.id.actions_button: {
|
|
showMenuItemToast(v, v.getContentDescription(), true);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
|
|
}
|
|
|
|
@Override
|
|
public void onPageSelected(final int position) {
|
|
//TODO handle secondary drawer
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
|
|
mDrawerLayout.closeDrawers();
|
|
}
|
|
updateSlidingMenuTouchMode();
|
|
updateActionsButton();
|
|
}
|
|
|
|
@Override
|
|
public void onPageScrollStateChanged(final int state) {
|
|
setControlBarVisibleAnimate(true);
|
|
}
|
|
|
|
@Override
|
|
public boolean onSearchRequested() {
|
|
startActivity(new Intent(this, QuickSearchBarActivity.class));
|
|
return true;
|
|
}
|
|
|
|
public void openSearchView(final ParcelableAccount account) {
|
|
mSelectedAccountToSearch = account;
|
|
onSearchRequested();
|
|
}
|
|
|
|
@Override
|
|
public void onFitSystemWindows(Rect insets) {
|
|
super.onFitSystemWindows(insets);
|
|
final Fragment fragment = getLeftDrawerFragment();
|
|
if (fragment instanceof AccountsDashboardFragment) {
|
|
((AccountsDashboardFragment) fragment).requestFitSystemWindows();
|
|
}
|
|
mHomeContent.setStatusBarHeight(insets.top);
|
|
}
|
|
|
|
public void updateUnreadCount() {
|
|
if (mTabIndicator == null || mUpdateUnreadCountTask != null
|
|
&& mUpdateUnreadCountTask.getStatus() == AsyncTask.Status.RUNNING) return;
|
|
mUpdateUnreadCountTask = new UpdateUnreadCountTask(this, mReadStateManager, mTabIndicator,
|
|
mPagerAdapter.getTabs());
|
|
AsyncTaskUtils.executeTask(mUpdateUnreadCountTask);
|
|
mTabIndicator.setDisplayBadge(mPreferences.getBoolean(KEY_UNREAD_COUNT, true));
|
|
}
|
|
|
|
@Override
|
|
protected void onNewIntent(final Intent intent) {
|
|
final int tabPosition = handleIntent(intent, false);
|
|
if (tabPosition >= 0) {
|
|
mViewPager.setCurrentItem(MathUtils.clamp(tabPosition, mPagerAdapter.getCount(), 0));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onDestroy() {
|
|
|
|
stopService(new Intent(this, StreamingService.class));
|
|
|
|
// Delete unused items in databases.
|
|
cleanDatabasesByItemLimit(this);
|
|
sendBroadcast(new Intent(BROADCAST_HOME_ACTIVITY_ONDESTROY));
|
|
super.onDestroy();
|
|
}
|
|
|
|
@Override
|
|
public float getControlBarOffset() {
|
|
if (mTabColumns > 1) {
|
|
final ViewGroup.LayoutParams lp = mActionsButton.getLayoutParams();
|
|
float total;
|
|
if (lp instanceof MarginLayoutParams) {
|
|
total = ((MarginLayoutParams) lp).bottomMargin + mActionsButton.getHeight();
|
|
} else {
|
|
total = mActionsButton.getHeight();
|
|
}
|
|
return 1 - mActionsButton.getTranslationY() / total;
|
|
}
|
|
final float totalHeight = getControlBarHeight();
|
|
return 1 + mActionBarWithOverlay.getTranslationY() / totalHeight;
|
|
}
|
|
|
|
@Override
|
|
public void setControlBarOffset(float offset) {
|
|
mActionBarWithOverlay.setTranslationY(mTabColumns > 1 ? 0 : getControlBarHeight() * (offset - 1));
|
|
final ViewGroup.LayoutParams lp = mActionsButton.getLayoutParams();
|
|
if (lp instanceof MarginLayoutParams) {
|
|
mActionsButton.setTranslationY((((MarginLayoutParams) lp).bottomMargin + mActionsButton.getHeight()) * (1 - offset));
|
|
} else {
|
|
mActionsButton.setTranslationY(mActionsButton.getHeight() * (1 - offset));
|
|
}
|
|
notifyControlBarOffsetChanged();
|
|
}
|
|
|
|
@Override
|
|
public void onContentChanged() {
|
|
super.onContentChanged();
|
|
mActionBar = (Toolbar) findViewById(R.id.action_bar);
|
|
mActionBarContainer = findViewById(R.id.twidere_action_bar_container);
|
|
mTabIndicator = (TabPagerIndicator) findViewById(R.id.main_tabs);
|
|
mDrawerLayout = (DrawerLayout) findViewById(R.id.home_menu);
|
|
mViewPager = (ExtendedViewPager) findViewById(R.id.main_pager);
|
|
mEmptyTabHint = findViewById(R.id.empty_tab_hint);
|
|
mActionsButton = findViewById(R.id.actions_button);
|
|
mActionBarWithOverlay = findViewById(R.id.twidere_action_bar_with_overlay);
|
|
mTabIndicator = (TabPagerIndicator) findViewById(R.id.main_tabs);
|
|
mHomeContent = (TintedStatusFrameLayout) findViewById(R.id.home_content);
|
|
}
|
|
|
|
private Fragment getKeyboardShortcutRecipient() {
|
|
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
|
|
return getLeftDrawerFragment();
|
|
} else if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
|
|
return null;
|
|
} else {
|
|
return getCurrentVisibleFragment();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getControlBarHeight() {
|
|
return mTabIndicator.getHeight() - mTabIndicator.getStripHeight();
|
|
}
|
|
|
|
private boolean handleFragmentKeyboardShortcutRepeat(final KeyboardShortcutsHandler handler,
|
|
final int keyCode, final int repeatCount,
|
|
@NonNull final KeyEvent event) {
|
|
final Fragment fragment = getKeyboardShortcutRecipient();
|
|
if (fragment instanceof KeyboardShortcutCallback) {
|
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutRepeat(handler, keyCode, repeatCount, event);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean handleFragmentKeyboardShortcutSingle(final KeyboardShortcutsHandler handler,
|
|
final int keyCode, @NonNull final KeyEvent event) {
|
|
final Fragment fragment = getKeyboardShortcutRecipient();
|
|
if (fragment instanceof KeyboardShortcutCallback) {
|
|
return ((KeyboardShortcutCallback) fragment).handleKeyboardShortcutSingle(handler, keyCode, event);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private boolean isFragmentKeyboardShortcutHandled(final KeyboardShortcutsHandler handler,
|
|
final int keyCode, @NonNull final KeyEvent event) {
|
|
final Fragment fragment = getKeyboardShortcutRecipient();
|
|
if (fragment instanceof KeyboardShortcutCallback) {
|
|
return ((KeyboardShortcutCallback) fragment).isKeyboardShortcutHandled(handler, keyCode, event);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private int handleIntent(final Intent intent, final boolean firstCreate) {
|
|
// use packge's class loader to prevent BadParcelException
|
|
intent.setExtrasClassLoader(getClassLoader());
|
|
// reset intent
|
|
setIntent(new Intent(this, HomeActivity.class));
|
|
final String action = intent.getAction();
|
|
if (Intent.ACTION_SEARCH.equals(action)) {
|
|
final String query = intent.getStringExtra(SearchManager.QUERY);
|
|
final Bundle appSearchData = intent.getBundleExtra(SearchManager.APP_DATA);
|
|
final long accountId;
|
|
if (appSearchData != null && appSearchData.containsKey(EXTRA_ACCOUNT_ID)) {
|
|
accountId = appSearchData.getLong(EXTRA_ACCOUNT_ID, -1);
|
|
} else {
|
|
accountId = getDefaultAccountId(this);
|
|
}
|
|
openSearch(this, accountId, query);
|
|
return -1;
|
|
}
|
|
final boolean refreshOnStart = mPreferences.getBoolean(KEY_REFRESH_ON_START, false);
|
|
final long[] refreshedIds = intent.getLongArrayExtra(EXTRA_REFRESH_IDS);
|
|
if (refreshedIds != null) {
|
|
mTwitterWrapper.refreshAll(refreshedIds);
|
|
} else if (firstCreate && refreshOnStart) {
|
|
mTwitterWrapper.refreshAll();
|
|
}
|
|
|
|
final Uri uri = intent.getData();
|
|
final String tabType = uri != null ? Utils.matchTabType(uri) : null;
|
|
int initialTab = -1;
|
|
if (tabType != null) {
|
|
final long accountId = ParseUtils.parseLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID));
|
|
for (int i = mPagerAdapter.getCount() - 1; i > -1; i--) {
|
|
final SupportTabSpec tab = mPagerAdapter.getTab(i);
|
|
if (tabType.equals(tab.type)) {
|
|
initialTab = i;
|
|
if (hasAccountId(tab.args, accountId)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (initialTab != -1 && mViewPager != null) {
|
|
// clearNotification(initial_tab);
|
|
}
|
|
final Intent extraIntent = intent.getParcelableExtra(EXTRA_EXTRA_INTENT);
|
|
if (extraIntent != null && firstCreate) {
|
|
extraIntent.setExtrasClassLoader(getClassLoader());
|
|
startActivity(extraIntent);
|
|
}
|
|
return initialTab;
|
|
}
|
|
|
|
private boolean hasAccountId(Bundle args, long accountId) {
|
|
if (args == null) return false;
|
|
if (args.containsKey(EXTRA_ACCOUNT_ID)) {
|
|
return args.getLong(EXTRA_ACCOUNT_ID) == accountId;
|
|
} else if (args.containsKey(EXTRA_ACCOUNT_IDS)) {
|
|
return ArrayUtils.contains(args.getLongArray(EXTRA_ACCOUNT_IDS), accountId);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void initUnreadCount() {
|
|
for (int i = 0, j = mTabIndicator.getCount(); i < j; i++) {
|
|
mTabIndicator.setBadge(i, 0);
|
|
}
|
|
}
|
|
|
|
private void openAccountsDrawer() {
|
|
if (mDrawerLayout == null) return;
|
|
mDrawerLayout.openDrawer(GravityCompat.START);
|
|
}
|
|
|
|
private boolean openSettingsWizard() {
|
|
if (mPreferences == null || mPreferences.getBoolean(KEY_SETTINGS_WIZARD_COMPLETED, false))
|
|
return false;
|
|
startActivity(new Intent(this, SettingsWizardActivity.class));
|
|
return true;
|
|
}
|
|
|
|
private void setTabPosition(final int initialTab) {
|
|
final boolean rememberPosition = mPreferences.getBoolean(KEY_REMEMBER_POSITION, true);
|
|
if (initialTab >= 0) {
|
|
mViewPager.setCurrentItem(MathUtils.clamp(initialTab, mPagerAdapter.getCount(), 0));
|
|
} else if (rememberPosition) {
|
|
final int position = mPreferences.getInt(KEY_SAVED_TAB_POSITION, 0);
|
|
mViewPager.setCurrentItem(MathUtils.clamp(position, mPagerAdapter.getCount(), 0));
|
|
}
|
|
}
|
|
|
|
private void setupBars() {
|
|
final int themeColor = getThemeColor();
|
|
final int themeResId = getCurrentThemeResourceId();
|
|
final String backgroundOption = getCurrentThemeBackgroundOption();
|
|
final boolean isTransparent = ThemeUtils.isTransparentBackground(backgroundOption);
|
|
final int actionBarAlpha = isTransparent ? ThemeUtils.getActionBarAlpha(ThemeUtils.getUserThemeBackgroundAlpha(this)) : 0xFF;
|
|
final IHomeActionButton homeActionButton = (IHomeActionButton) mActionsButton;
|
|
mTabIndicator.setItemContext(ThemeUtils.getActionBarThemedContext(this, themeResId, themeColor));
|
|
ViewSupport.setBackground(mActionBarContainer, ThemeUtils.getActionBarBackground(this, themeResId, themeColor,
|
|
backgroundOption, true));
|
|
final int actionBarColor = ThemeUtils.getActionBarColor(this, themeColor, themeResId, backgroundOption);
|
|
final int actionItemColor = ThemeUtils.getContrastForegroundColor(this, getCurrentThemeResourceId(), themeColor);
|
|
final int[] foregroundColors = new int[2];
|
|
ThemeUtils.getColorForegroundAndInverse(this, foregroundColors);
|
|
if (ThemeUtils.isDarkTheme(themeResId)) {
|
|
homeActionButton.setButtonColor(actionBarColor);
|
|
homeActionButton.setIconColor(actionItemColor, Mode.SRC_ATOP);
|
|
mTabIndicator.setStripColor(themeColor);
|
|
mTabIndicator.setIconColor(foregroundColors[0]);
|
|
mTabIndicator.setLabelColor(foregroundColors[0]);
|
|
} else {
|
|
final int contrastColor = TwidereColorUtils.getContrastYIQ(themeColor,
|
|
ThemeUtils.ACCENT_COLOR_THRESHOLD, foregroundColors[0], foregroundColors[1]);
|
|
homeActionButton.setButtonColor(themeColor);
|
|
homeActionButton.setIconColor(actionItemColor, Mode.SRC_ATOP);
|
|
mTabIndicator.setStripColor(contrastColor);
|
|
mTabIndicator.setIconColor(contrastColor);
|
|
mTabIndicator.setLabelColor(contrastColor);
|
|
ActivitySupport.setTaskDescription(this, new TaskDescriptionCompat(null, null, themeColor));
|
|
}
|
|
mHomeContent.setDrawColor(true);
|
|
mHomeContent.setDrawShadow(false);
|
|
mHomeContent.setColor(actionBarColor, actionBarAlpha);
|
|
StatusBarProxy.setStatusBarDarkIcon(getWindow(), TwidereColorUtils.getYIQLuminance(actionBarColor) > ThemeUtils.ACCENT_COLOR_THRESHOLD);
|
|
mHomeContent.setFactor(1);
|
|
mActionBarWithOverlay.setAlpha(actionBarAlpha / 255f);
|
|
mActionsButton.setAlpha(actionBarAlpha / 255f);
|
|
}
|
|
|
|
private void setupHomeTabs() {
|
|
mPagerAdapter.clear();
|
|
mPagerAdapter.addTabs(CustomTabUtils.getHomeTabs(this));
|
|
final boolean hasNoTab = mPagerAdapter.getCount() == 0;
|
|
mEmptyTabHint.setVisibility(hasNoTab ? View.VISIBLE : View.GONE);
|
|
mViewPager.setVisibility(hasNoTab ? View.GONE : View.VISIBLE);
|
|
// mViewPager.setOffscreenPageLimit(mPagerAdapter.getCount() / 2);
|
|
}
|
|
|
|
private void setupSlidingMenu() {
|
|
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow_start, GravityCompat.START);
|
|
final Window window = getWindow();
|
|
ThemeUtils.applyWindowBackground(this, mHomeContent, getCurrentThemeResourceId(),
|
|
getThemeBackgroundOption(), getCurrentThemeBackgroundAlpha());
|
|
window.setBackgroundDrawable(new EmptyDrawable());
|
|
}
|
|
|
|
private void showDataProfilingRequest() {
|
|
//spice
|
|
if (mPreferences.contains(KEY_USAGE_STATISTICS)) {
|
|
return;
|
|
}
|
|
final Intent intent = new Intent(this, UsageStatisticsActivity.class);
|
|
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
|
|
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
|
builder.setAutoCancel(true);
|
|
builder.setSmallIcon(R.drawable.ic_stat_info);
|
|
builder.setTicker(getString(R.string.usage_statistics));
|
|
builder.setContentTitle(getString(R.string.usage_statistics));
|
|
builder.setContentText(getString(R.string.usage_statistics_notification_summary));
|
|
builder.setContentIntent(contentIntent);
|
|
mNotificationManager.notify(NOTIFICATION_ID_DATA_PROFILING, builder.build());
|
|
}
|
|
|
|
private void triggerActionsClick() {
|
|
if (mViewPager == null || mPagerAdapter == null) return;
|
|
final int position = mViewPager.getCurrentItem();
|
|
final SupportTabSpec tab = mPagerAdapter.getTab(position);
|
|
if (tab == null) {
|
|
startActivity(new Intent(INTENT_ACTION_COMPOSE));
|
|
} else {
|
|
if (classEquals(DirectMessagesFragment.class, tab.cls)) {
|
|
openMessageConversation(this, -1, -1);
|
|
} else if (classEquals(TrendsSuggestionsFragment.class, tab.cls)) {
|
|
openSearchView(null);
|
|
} else {
|
|
startActivity(new Intent(INTENT_ACTION_COMPOSE));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateActionsButton() {
|
|
if (mViewPager == null || mPagerAdapter == null) return;
|
|
final int icon, title;
|
|
final int position = mViewPager.getCurrentItem();
|
|
final SupportTabSpec tab = mPagerAdapter.getTab(position);
|
|
if (tab == null) {
|
|
title = R.string.compose;
|
|
icon = R.drawable.ic_action_status_compose;
|
|
} else {
|
|
if (classEquals(DirectMessagesFragment.class, tab.cls)) {
|
|
icon = R.drawable.ic_action_add;
|
|
title = R.string.new_direct_message;
|
|
} else if (classEquals(TrendsSuggestionsFragment.class, tab.cls)) {
|
|
icon = R.drawable.ic_action_search;
|
|
title = android.R.string.search_go;
|
|
} else {
|
|
icon = R.drawable.ic_action_status_compose;
|
|
title = R.string.compose;
|
|
}
|
|
}
|
|
if (mActionsButton instanceof IHomeActionButton) {
|
|
final IHomeActionButton hab = (IHomeActionButton) mActionsButton;
|
|
hab.setIcon(icon);
|
|
hab.setTitle(title);
|
|
}
|
|
}
|
|
|
|
private void updateActionsButtonStyle() {
|
|
final boolean leftsideComposeButton = mPreferences.getBoolean(KEY_LEFTSIDE_COMPOSE_BUTTON, false);
|
|
final FrameLayout.LayoutParams lp = (LayoutParams) mActionsButton.getLayoutParams();
|
|
lp.gravity = Gravity.BOTTOM | (leftsideComposeButton ? Gravity.LEFT : Gravity.RIGHT);
|
|
mActionsButton.setLayoutParams(lp);
|
|
}
|
|
|
|
private void updateSlidingMenuTouchMode() {
|
|
// if (mViewPager == null || mSlidingMenu == null) return;
|
|
// final int position = mViewPager.getCurrentItem();
|
|
// final boolean pagingEnabled = mViewPager.isEnabled();
|
|
// final boolean atFirstOrLast = position == 0 || position == mPagerAdapter.getCount() - 1;
|
|
// final int mode = !pagingEnabled || atFirstOrLast ? SlidingMenu.TOUCHMODE_FULLSCREEN
|
|
// : SlidingMenu.TOUCHMODE_MARGIN;
|
|
// mSlidingMenu.setTouchModeAbove(mode);
|
|
}
|
|
|
|
private static final class AccountChangeObserver extends ContentObserver {
|
|
private final HomeActivity mActivity;
|
|
|
|
public AccountChangeObserver(final HomeActivity activity, final Handler handler) {
|
|
super(handler);
|
|
mActivity = activity;
|
|
}
|
|
|
|
@Override
|
|
public void onChange(final boolean selfChange) {
|
|
onChange(selfChange, null);
|
|
}
|
|
|
|
@Override
|
|
public void onChange(final boolean selfChange, final Uri uri) {
|
|
mActivity.notifyAccountsChanged();
|
|
mActivity.updateUnreadCount();
|
|
}
|
|
}
|
|
|
|
private static class UpdateUnreadCountTask extends AsyncTask<Object, Object, Map<SupportTabSpec, Integer>> {
|
|
private final Context mContext;
|
|
private final ReadStateManager mReadStateManager;
|
|
private final TabPagerIndicator mIndicator;
|
|
private final List<SupportTabSpec> mTabs;
|
|
|
|
UpdateUnreadCountTask(final Context context, final ReadStateManager manager, final TabPagerIndicator indicator, final List<SupportTabSpec> tabs) {
|
|
mContext = context;
|
|
mReadStateManager = manager;
|
|
mIndicator = indicator;
|
|
mTabs = Collections.unmodifiableList(tabs);
|
|
}
|
|
|
|
@Override
|
|
protected Map<SupportTabSpec, Integer> doInBackground(final Object... params) {
|
|
final Map<SupportTabSpec, Integer> result = new HashMap<>();
|
|
for (SupportTabSpec spec : mTabs) {
|
|
switch (spec.type) {
|
|
case TAB_TYPE_HOME_TIMELINE: {
|
|
final long[] accountIds = Utils.getAccountIds(spec.args);
|
|
final String tagWithAccounts = Utils.getReadPositionTagWithAccounts(mContext, true, spec.tag, accountIds);
|
|
final long position = mReadStateManager.getPosition(tagWithAccounts);
|
|
result.put(spec, Utils.getStatusesCount(mContext, Statuses.CONTENT_URI, position, accountIds));
|
|
break;
|
|
}
|
|
case TAB_TYPE_MENTIONS_TIMELINE: {
|
|
final long[] accountIds = Utils.getAccountIds(spec.args);
|
|
final String tagWithAccounts = Utils.getReadPositionTagWithAccounts(mContext, true, spec.tag, accountIds);
|
|
final long position = mReadStateManager.getPosition(tagWithAccounts);
|
|
result.put(spec, Utils.getStatusesCount(mContext, Mentions.CONTENT_URI, position, accountIds));
|
|
break;
|
|
}
|
|
case TAB_TYPE_DIRECT_MESSAGES: {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(final Map<SupportTabSpec, Integer> result) {
|
|
mIndicator.clearBadge();
|
|
for (Entry<SupportTabSpec, Integer> entry : result.entrySet()) {
|
|
final SupportTabSpec key = entry.getKey();
|
|
mIndicator.setBadge(key.position, entry.getValue());
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|