1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-02 01:36:50 +01:00

improved search ui

fixed notification light/vibrate/ringtone option
improved refresh indicator in statuses timeline
fixed crashes when open drafts
This commit is contained in:
Mariotaku Lee 2015-04-01 18:28:26 +08:00
parent ac58c878a9
commit 9f2abf6cd9
22 changed files with 381 additions and 146 deletions

View File

@ -113,7 +113,9 @@ public class ParcelableMedia implements Parcelable, JSONParcelable, SimpleValueS
type = update.type;
}
public static ParcelableMedia[] fromMediaUpdates(ParcelableMediaUpdate[] mediaUpdates) {
@Nullable
public static ParcelableMedia[] fromMediaUpdates(@Nullable final ParcelableMediaUpdate[] mediaUpdates) {
if (mediaUpdates == null) return null;
final ParcelableMedia[] media = new ParcelableMedia[mediaUpdates.length];
for (int i = 0, j = mediaUpdates.length; i < j; i++) {
final ParcelableMediaUpdate mediaUpdate = mediaUpdates[i];

View File

@ -1,5 +1,11 @@
package org.mariotaku.twidere.activity.iface;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.util.Property;
import android.view.animation.DecelerateInterpolator;
/**
* Created by mariotaku on 14/10/21.
*/
@ -22,4 +28,71 @@ public interface IControlBarActivity {
public interface ControlBarOffsetListener {
public void onControlBarOffsetChanged(IControlBarActivity activity, float offset);
}
public final class ControlBarShowHideHelper {
private static final long DURATION = 200l;
private final IControlBarActivity mActivity;
private int mControlAnimationDirection;
public ControlBarShowHideHelper(IControlBarActivity activity) {
mActivity = activity;
}
private static class ControlBarOffsetProperty extends Property<IControlBarActivity, Float> {
public static final ControlBarOffsetProperty SINGLETON = new ControlBarOffsetProperty();
@Override
public void set(IControlBarActivity object, Float value) {
object.setControlBarOffset(value);
}
public ControlBarOffsetProperty() {
super(Float.TYPE, null);
}
@Override
public Float get(IControlBarActivity object) {
return object.getControlBarOffset();
}
}
public void setControlBarVisibleAnimate(boolean visible) {
if (mControlAnimationDirection != 0) return;
final ObjectAnimator animator;
final float offset = mActivity.getControlBarOffset();
if (visible) {
if (offset >= 1) return;
animator = ObjectAnimator.ofFloat(mActivity, ControlBarOffsetProperty.SINGLETON, offset, 1);
} else {
if (offset <= 0) return;
animator = ObjectAnimator.ofFloat(mActivity, ControlBarOffsetProperty.SINGLETON, offset, 0);
}
animator.setInterpolator(new DecelerateInterpolator());
animator.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mControlAnimationDirection = 0;
}
@Override
public void onAnimationCancel(Animator animation) {
mControlAnimationDirection = 0;
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.setDuration(DURATION);
animator.start();
mControlAnimationDirection = visible ? 1 : -1;
}
}
}

View File

@ -160,6 +160,7 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
@Override
public void onFitSystemWindows(Rect insets) {
mSystemWindowsInsets = new Rect(insets);
notifyControlBarOffsetChanged();
}
@Override

View File

@ -19,9 +19,6 @@
package org.mariotaku.twidere.activity.support;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.SearchManager;
@ -48,7 +45,6 @@ import android.support.v4.app.NotificationCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.widget.Toolbar;
import android.util.Property;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.KeyEvent;
@ -60,7 +56,6 @@ import android.view.ViewGroup;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.FrameLayout.LayoutParams;
import android.widget.Toast;
@ -76,7 +71,6 @@ 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.iface.IControlBarActivity;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.CustomTabsFragment;
@ -131,8 +125,7 @@ import static org.mariotaku.twidere.util.Utils.openSearch;
import static org.mariotaku.twidere.util.Utils.showMenuItemToast;
public class HomeActivity extends BaseActionBarActivity implements OnClickListener, OnPageChangeListener,
SupportFragmentCallback, OnOpenedListener, OnClosedListener,
OnLongClickListener, AnimatorListener {
SupportFragmentCallback, OnOpenedListener, OnClosedListener, OnLongClickListener {
private final Handler mHandler = new Handler();
@ -169,7 +162,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
private int mTabDisplayOption;
private float mPagerPosition;
private Toolbar mActionBar;
private int mControlAnimationDirection;
public void closeAccountsDrawer() {
if (mSlidingMenu == null) return;
@ -181,24 +173,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
return mCurrentVisibleFragment;
}
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mControlAnimationDirection = 0;
}
@Override
public void onAnimationCancel(Animator animation) {
mControlAnimationDirection = 0;
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onDetachFragment(final Fragment fragment) {
@ -221,25 +195,11 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
&& ((RefreshScrollTopInterface) f).triggerRefresh();
}
private static final long DURATION = 200l;
private ControlBarShowHideHelper mControlBarShowHideHelper = new ControlBarShowHideHelper(this);
@Override
public void setControlBarVisibleAnimate(boolean visible) {
if (mControlAnimationDirection != 0) return;
final ObjectAnimator animator;
final float offset = getControlBarOffset();
if (visible) {
if (offset >= 1) return;
animator = ObjectAnimator.ofFloat(this, ControlBarOffsetProperty.SINGLETON, offset, 1);
} else {
if (offset <= 0) return;
animator = ObjectAnimator.ofFloat(this, ControlBarOffsetProperty.SINGLETON, offset, 0);
}
animator.setInterpolator(new DecelerateInterpolator());
animator.addListener(this);
animator.setDuration(DURATION);
animator.start();
mControlAnimationDirection = visible ? 1 : -1;
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
}
@Override
@ -992,21 +952,4 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
}
private static class ControlBarOffsetProperty extends Property<IControlBarActivity, Float> {
public static final ControlBarOffsetProperty SINGLETON = new ControlBarOffsetProperty();
@Override
public void set(IControlBarActivity object, Float value) {
object.setControlBarOffset(value);
}
public ControlBarOffsetProperty() {
super(Float.TYPE, null);
}
@Override
public Float get(IControlBarActivity object) {
return object.getControlBarOffset();
}
}
}

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.activity.support;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
@ -44,7 +43,6 @@ import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCal
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.util.FlymeUtils;
import org.mariotaku.twidere.util.MultiSelectEventHandler;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -56,14 +54,34 @@ import static org.mariotaku.twidere.util.Utils.createFragmentForIntent;
import static org.mariotaku.twidere.util.Utils.matchLinkId;
public class LinkHandlerActivity extends BaseActionBarActivity implements OnClickListener,
OnLongClickListener, SystemWindowsInsetsCallback, IControlBarActivity {
OnLongClickListener, SystemWindowsInsetsCallback, IControlBarActivity, SupportFragmentCallback {
private ControlBarShowHideHelper mControlBarShowHideHelper = new ControlBarShowHideHelper(this);
private MultiSelectEventHandler mMultiSelectHandler;
private TintedStatusFrameLayout mMainContent;
private boolean mFinishOnly;
@Override
public Fragment getCurrentVisibleFragment() {
return getSupportFragmentManager().findFragmentById(R.id.main_content);
}
@Override
public void onDetachFragment(Fragment fragment) {
}
@Override
public void onSetUserVisibleHint(Fragment fragment, boolean isVisibleToUser) {
}
@Override
public boolean triggerRefresh(int position) {
return false;
}
@Override
public void onClick(final View v) {
switch (v.getId()) {
@ -110,7 +128,7 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
@Override
protected IBasePullToRefreshFragment getCurrentPullToRefreshFragment() {
final Fragment fragment = getSupportFragmentManager().findFragmentById(android.R.id.content);
final Fragment fragment = getCurrentVisibleFragment();
if (fragment instanceof IBasePullToRefreshFragment)
return (IBasePullToRefreshFragment) fragment;
else if (fragment instanceof SupportFragmentCallback) {
@ -129,7 +147,6 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
final Uri data = intent.getData();
final int linkId = matchLinkId(data);
requestWindowFeatures(getWindow(), linkId, data);
setUiOptions(getWindow(), linkId, data);
super.onCreate(savedInstanceState);
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
@ -211,9 +228,14 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
case LINK_ID_USER: {
break;
}
case LINK_ID_SEARCH: {
ThemeUtils.applyActionBarBackground(actionBar, this, getCurrentThemeResourceId(),
getCurrentThemeColor(), false);
break;
}
default: {
ThemeUtils.applyActionBarBackground(actionBar, this, getCurrentThemeResourceId(),
getCurrentThemeColor());
getCurrentThemeColor(), true);
break;
}
}
@ -255,16 +277,6 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
}
}
private void setUiOptions(final Window window, int linkId, final Uri uri) {
if (!FlymeUtils.hasSmartBar()) return;
switch (linkId) {
case LINK_ID_USER: {
window.setUiOptions(ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW);
break;
}
}
}
private boolean showFragment(final int linkId, final Uri uri) {
final Intent intent = getIntent();
intent.setExtrasClassLoader(getClassLoader());
@ -381,13 +393,24 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements OnClic
}
@Override
public void setControlBarOffset(float offset) {
public void setControlBarVisibleAnimate(boolean visible) {
mControlBarShowHideHelper.setControlBarVisibleAnimate(visible);
}
@Override
public void setControlBarOffset(float offset) {
final ActionBar actionBar = getSupportActionBar();
if (actionBar == null) return;
actionBar.setHideOffset(Math.round((1 - offset) * getControlBarHeight()));
notifyControlBarOffsetChanged();
}
@Override
public float getControlBarOffset() {
return 0;
final ActionBar actionBar = getSupportActionBar();
if (actionBar == null) return 0;
return 1f - actionBar.getHideOffset() / (float) getControlBarHeight();
}
@Override

View File

@ -672,7 +672,7 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
}
public ParcelableAccount getSelectedAccount() {
if (mInternalAccounts == null || mInternalAccounts.length < 0) {
if (mInternalAccounts == null || mInternalAccounts.length == 0) {
return null;
}
return mInternalAccounts[0];

View File

@ -43,10 +43,10 @@ import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
import org.mariotaku.twidere.util.message.StatusRetweetedEvent;
import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import static org.mariotaku.twidere.util.Utils.buildStatusFilterWhereClause;
import static org.mariotaku.twidere.util.Utils.getNewestStatusIdsFromDatabase;
@ -85,15 +85,16 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor>
@Override
protected Object createMessageBusCallback() {
return new ParcelableStatusesBusCallback();
return new CursorStatusesBusCallback();
}
protected class ParcelableStatusesBusCallback {
protected class CursorStatusesBusCallback {
@Subscribe
public void notifyTaskStateChanged(TaskStateChangedEvent event) {
updateRefreshState();
public void notifyGetStatusesTaskChanged(GetStatusesTaskEvent event) {
if (!event.uri.equals(getContentUri())) return;
setRefreshing(event.running);
}
@Subscribe
@ -138,6 +139,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor>
}
};
cr.registerContentObserver(Accounts.CONTENT_URI, true, mContentObserver);
updateRefreshState();
}
protected void reloadStatuses() {

View File

@ -20,14 +20,18 @@
package org.mariotaku.twidere.fragment.support;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.provider.SearchRecentSuggestions;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -36,7 +40,10 @@ import android.view.View;
import android.view.ViewGroup;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
import org.mariotaku.twidere.activity.iface.IControlBarActivity.ControlBarOffsetListener;
import org.mariotaku.twidere.activity.iface.IThemedActivity;
import org.mariotaku.twidere.activity.support.ComposeActivity;
import org.mariotaku.twidere.activity.support.LinkHandlerActivity;
import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
@ -45,10 +52,14 @@ import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.provider.RecentSearchProvider;
import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ColorUtils;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.TabPagerIndicator;
public class SearchFragment extends BaseSupportFragment implements RefreshScrollTopInterface,
SupportFragmentCallback, SystemWindowsInsetsCallback {
SupportFragmentCallback, SystemWindowsInsetsCallback, ControlBarOffsetListener,
OnPageChangeListener {
private ViewPager mViewPager;
@ -56,14 +67,80 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
private TabPagerIndicator mPagerIndicator;
private Fragment mCurrentVisibleFragment;
private int mControlBarOffsetPixels;
private int mControlBarHeight;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof IControlBarActivity) {
((IControlBarActivity) activity).registerControlBarOffsetListener(this);
}
}
@Override
public void onDetach() {
final FragmentActivity activity = getActivity();
if (activity instanceof IControlBarActivity) {
((IControlBarActivity) activity).unregisterControlBarOffsetListener(this);
}
super.onDetach();
}
@Override
public void onControlBarOffsetChanged(IControlBarActivity activity, float offset) {
mControlBarHeight = activity.getControlBarHeight();
mControlBarOffsetPixels = Math.round(mControlBarHeight * (1 - offset));
updateTabOffset();
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
final FragmentActivity activity = getActivity();
if (activity instanceof LinkHandlerActivity) {
((LinkHandlerActivity) activity).setControlBarVisibleAnimate(true);
}
}
private void updateTabOffset() {
int controlBarHeight = getControlBarHeight();
mPagerIndicator.setTranslationY(controlBarHeight - mControlBarOffsetPixels);
}
private int getControlBarHeight() {
final FragmentActivity activity = getActivity();
final int controlBarHeight;
if (activity instanceof LinkHandlerActivity) {
controlBarHeight = ((LinkHandlerActivity) activity).getControlBarHeight();
} else {
controlBarHeight = mControlBarHeight;
}
if (controlBarHeight == 0) {
return Utils.getActionBarHeight(activity);
}
return controlBarHeight;
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
final View view = getView();
if (view != null) {
view.setPadding(insets.left, insets.top, insets.right, insets.bottom);
final int top = Utils.getInsetsTopWithoutActionBarHeight(getActivity(), insets.top);
view.setPadding(insets.left, top, insets.right, insets.bottom);
}
updateTabOffset();
}
@Override
@ -88,11 +165,19 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
mViewPager.setOffscreenPageLimit(2);
mPagerIndicator.setViewPager(mViewPager);
mPagerIndicator.setTabDisplayOption(TabPagerIndicator.LABEL);
mPagerIndicator.setOnPageChangeListener(this);
if (activity instanceof IThemedActivity) {
mPagerIndicator.setStripColor(((IThemedActivity) activity).getCurrentThemeColor());
final int themeColor = ((IThemedActivity) activity).getCurrentThemeColor();
final int contrastColor = ColorUtils.getContrastYIQ(themeColor, 192);
mPagerIndicator.setBackgroundColor(themeColor);
mPagerIndicator.setIconColor(contrastColor);
mPagerIndicator.setLabelColor(contrastColor);
mPagerIndicator.setStripColor(contrastColor);
} else {
mPagerIndicator.setBackgroundColor(ThemeUtils.getThemeColor(activity));
}
final float supportActionBarElevation = ThemeUtils.getSupportActionBarElevation(activity);
ViewCompat.setElevation(mPagerIndicator, supportActionBarElevation);
if (savedInstanceState == null && args != null && args.containsKey(EXTRA_QUERY)) {
final String query = args.getString(EXTRA_QUERY);
final SearchRecentSuggestions suggestions = new SearchRecentSuggestions(getActivity(),
@ -109,6 +194,11 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
}
}
}
updateTabOffset();
}
public String getQuery() {
return getArguments().getString(EXTRA_QUERY);
}
@Override
@ -139,10 +229,23 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
}
return true;
}
case MENU_COMPOSE: {
final Intent intent = new Intent(getActivity(), ComposeActivity.class);
intent.setAction(INTENT_ACTION_COMPOSE);
intent.putExtra(Intent.EXTRA_TEXT, String.format("#%s ", getQuery()));
startActivity(intent);
break;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
final MenuItem item = menu.findItem(MENU_COMPOSE);
item.setTitle(getString(R.string.tweet_hashtag, getQuery()));
}
@Override
public void onSetUserVisibleHint(final Fragment fragment, final boolean isVisibleToUser) {
if (isVisibleToUser) {
@ -181,6 +284,13 @@ public class SearchFragment extends BaseSupportFragment implements RefreshScroll
@Override
public boolean getSystemWindowsInsets(Rect insets) {
if (mPagerIndicator == null) return false;
final FragmentActivity activity = getActivity();
if (activity instanceof LinkHandlerActivity) {
((LinkHandlerActivity) activity).getSystemWindowsInsets(insets);
insets.top = mPagerIndicator.getHeight() + getControlBarHeight();
return true;
}
return false;
}
}

View File

@ -20,6 +20,7 @@
package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.content.Loader;
@ -47,6 +48,11 @@ public class StatusesSearchFragment extends ParcelableStatusesFragment {
getSavedStatusesFileArgs(), tabPosition, fromUser);
}
@Override
protected void fitSystemWindows(Rect insets) {
super.fitSystemWindows(insets);
}
@Override
protected String[] getSavedStatusesFileArgs() {
final Bundle args = getArguments();

View File

@ -1380,7 +1380,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
public ActionBarDrawable(Resources resources, Drawable shadow, Drawable background,
boolean colorLineOnly) {
super(new Drawable[]{shadow, background, new LineBackgroundDrawable(resources, 2.0f),
new ActionBarColorDrawable()});
new ActionBarColorDrawable(true)});
mShadowDrawable = getDrawable(0);
mBackgroundDrawable = getDrawable(1);
mLineDrawable = (LineBackgroundDrawable) getDrawable(2);

View File

@ -30,17 +30,22 @@ import android.os.Build;
*/
public class ActionBarColorDrawable extends ColorDrawable {
public ActionBarColorDrawable() {
private final boolean outlineEnabled;
public ActionBarColorDrawable(boolean outlineEnabled) {
super();
this.outlineEnabled = outlineEnabled;
}
public ActionBarColorDrawable(int color) {
public ActionBarColorDrawable(int color, boolean outlineEnabled) {
super(color);
this.outlineEnabled = outlineEnabled;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public void getOutline(Outline outline) {
if (!outlineEnabled) return;
final Rect bounds = getBounds();
// Very very dirty hack to make outline shadow in action bar not visible beneath status bar
outline.setRect(bounds.left - bounds.width() / 2, -bounds.height(),

View File

@ -111,7 +111,7 @@ public class ThemePreviewPreference extends Preference implements Constants, OnS
ViewAccessor.setBackground(windowBackgroundView, ThemeUtils.getWindowBackground(context));
// ViewAccessor.setBackground(windowContentOverlayView, ThemeUtils.getWindowContentOverlay(context));
ViewAccessor.setBackground(actionBarView, ThemeUtils.getActionBarBackground(context, themeRes, accentColor));
ViewAccessor.setBackground(actionBarView, ThemeUtils.getActionBarBackground(context, themeRes, accentColor, true));
ViewAccessor.setBackground(actionBarOverlay, ThemeUtils.getWindowContentOverlay(context));
cardView.setCardBackgroundColor(cardBackgroundColor);

View File

@ -40,6 +40,7 @@ import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@ -925,6 +926,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
builder.setContentIntent(clickIntent);
builder.setNumber(statusesCount);
builder.setColor(pref.getNotificationLightColor());
setNotificationPreferences(builder, pref, pref.getHomeTimelineNotificationType());
nm.notify("home_" + accountId, NOTIFICATION_ID_HOME_TIMELINE, builder.build());
} finally {
statusCursor.close();
@ -937,8 +939,15 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
final Context context = getContext();
final Resources resources = context.getResources();
final NotificationManager nm = getNotificationManager();
final Expression selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.greaterThan(Statuses.STATUS_ID, position));
final Expression selection;
if (pref.isNotificationFollowingOnly()) {
selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.greaterThan(Statuses.STATUS_ID, position),
Expression.equals(Statuses.IS_FOLLOWING, 1));
} else {
selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.greaterThan(Statuses.STATUS_ID, position));
}
final String filteredSelection = Utils.buildStatusFilterWhereClause(Mentions.TABLE_NAME,
selection, true).getSQL();
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
@ -1018,6 +1027,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
builder.setWhen(when);
builder.setStyle(style);
builder.setColor(pref.getNotificationLightColor());
setNotificationPreferences(builder, pref, pref.getMentionsNotificationType());
nm.notify("mentions_" + accountId, NOTIFICATION_ID_MENTIONS_TIMELINE,
builder.build());
} finally {
@ -1026,6 +1036,21 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
}
private void setNotificationPreferences(NotificationCompat.Builder builder, AccountPreferences pref, int defaultFlags) {
int notificationDefaults = 0;
if (AccountPreferences.isNotificationHasLight(defaultFlags)) {
notificationDefaults |= NotificationCompat.DEFAULT_LIGHTS;
}
if (AccountPreferences.isNotificationHasVibration(defaultFlags)) {
notificationDefaults |= NotificationCompat.DEFAULT_VIBRATE;
}
if (AccountPreferences.isNotificationHasRingtone(defaultFlags)) {
notificationDefaults |= NotificationCompat.DEFAULT_SOUND;
builder.setSound(pref.getNotificationRingtone(), AudioManager.STREAM_NOTIFICATION);
}
builder.setDefaults(notificationDefaults);
}
private void showMessagesNotification(AccountPreferences pref, StringLongPair[] pairs, ContentValues[] valuesArray) {
final long accountId = pref.getAccountId();
final long prevOldestId = mReadStateManager.getPosition(TAG_OLDEST_MESSAGES, String.valueOf(accountId));
@ -1146,6 +1171,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
builder.setWhen(when);
builder.setStyle(style);
builder.setColor(pref.getNotificationLightColor());
setNotificationPreferences(builder, pref, pref.getDirectMessagesNotificationType());
nm.notify("messages_" + accountId, NOTIFICATION_ID_DIRECT_MESSAGES, builder.build());
} finally {
messageCursor.close();

View File

@ -70,6 +70,7 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.message.FavoriteCreatedEvent;
import org.mariotaku.twidere.util.message.FavoriteDestroyedEvent;
import org.mariotaku.twidere.util.message.FriendshipUpdatedEvent;
import org.mariotaku.twidere.util.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.util.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.util.message.StatusDestroyedEvent;
import org.mariotaku.twidere.util.message.StatusListChangedEvent;
@ -2101,8 +2102,23 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
@NonNull
protected abstract Uri getDatabaseUri();
@Override
protected void onPostExecute(List<StatusListResponse> statusListResponses) {
super.onPostExecute(statusListResponses);
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new GetStatusesTaskEvent(getDatabaseUri(), false));
}
@Override
protected void onPreExecute() {
super.onPreExecute();
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
bus.post(new GetStatusesTaskEvent(getDatabaseUri(), true));
}
@Override
protected List<StatusListResponse> doInBackground(final Void... params) {
final List<StatusListResponse> result = new ArrayList<>();

View File

@ -19,6 +19,7 @@
package org.mariotaku.twidere.util;
import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
@ -32,6 +33,7 @@ import android.graphics.Typeface;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.v7.internal.view.menu.ActionMenuItemView;
import android.support.v7.widget.ActionMenuView;
@ -100,18 +102,18 @@ public class ThemeUtils implements Constants {
public static void applyActionBarBackground(final ActionBar actionBar, final Context context,
final int themeRes, final int accentColor) {
final int themeRes, final int accentColor, boolean outlineEnabled) {
if (actionBar == null || context == null) return;
actionBar.setBackgroundDrawable(getActionBarBackground(context, themeRes, accentColor));
actionBar.setBackgroundDrawable(getActionBarBackground(context, themeRes, accentColor, outlineEnabled));
actionBar.setSplitBackgroundDrawable(getActionBarSplitBackground(context, themeRes));
actionBar.setStackedBackgroundDrawable(getActionBarStackedBackground(context, themeRes));
}
public static void applyActionBarBackground(final android.support.v7.app.ActionBar actionBar, final Context context,
final int themeRes, final int accentColor) {
final int themeRes, final int accentColor, boolean outlineEnabled) {
if (actionBar == null || context == null) return;
actionBar.setBackgroundDrawable(getActionBarBackground(context, themeRes, accentColor));
actionBar.setBackgroundDrawable(getActionBarBackground(context, themeRes, accentColor, outlineEnabled));
actionBar.setSplitBackgroundDrawable(getActionBarSplitBackground(context, themeRes));
actionBar.setStackedBackgroundDrawable(getActionBarStackedBackground(context, themeRes));
}
@ -354,6 +356,24 @@ public class ThemeUtils implements Constants {
// TODO support TintableBackgroundView
}
public static float getSupportActionBarElevation(final Context context) {
final TypedArray a = context.obtainStyledAttributes(null, new int[]{R.attr.elevation}, R.attr.actionBarStyle, 0);
try {
return a.getDimension(0, 0);
} finally {
a.recycle();
}
}
@TargetApi(VERSION_CODES.LOLLIPOP)
public static float getActionBarElevation(final Context context) {
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.elevation}, android.R.attr.actionBarStyle, 0);
try {
return a.getDimension(0, 0);
} finally {
a.recycle();
}
}
@Deprecated
public static Drawable getActionBarBackground(final Context context, final boolean applyAlpha) {
@ -387,9 +407,9 @@ public class ThemeUtils implements Constants {
}
public static Drawable getActionBarBackground(final Context context, final int themeRes,
final int accentColor) {
final int accentColor, boolean outlineEnabled) {
if (!isDarkTheme(themeRes)) {
final ColorDrawable d = new ActionBarColorDrawable(accentColor);
final ColorDrawable d = new ActionBarColorDrawable(accentColor, outlineEnabled);
return applyActionBarDrawable(context, d, isTransparentBackground(themeRes));
}
final TypedArray a = context.obtainStyledAttributes(null, new int[]{android.R.attr.background},

View File

@ -1,40 +0,0 @@
/*
* 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.util.accessor;
import android.app.FragmentManager;
import java.lang.reflect.Field;
public class FragmentManagerAccessor {
public static boolean isStateSaved(final FragmentManager fm) {
try {
final Field mStateSavedField = FragmentManager.class.getField("mStateSaved");
final Object mStateSaved = mStateSavedField.get(fm);
if (mStateSaved instanceof Boolean) return (Boolean) mStateSaved;
} catch (final NoSuchFieldException e) {
} catch (final IllegalArgumentException e) {
} catch (final IllegalAccessException e) {
}
return false;
}
}

View File

@ -0,0 +1,38 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 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.util.message;
import android.net.Uri;
import android.support.annotation.NonNull;
/**
* Created by mariotaku on 14/12/10.
*/
public class GetStatusesTaskEvent {
@NonNull
public final Uri uri;
public final boolean running;
public GetStatusesTaskEvent(@NonNull Uri uri, boolean running) {
this.uri = uri;
this.running = running;
}
}

View File

@ -24,6 +24,7 @@ import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.view.iface.PagerIndicator;
import java.lang.annotation.Retention;
@ -69,6 +70,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
setVerticalPadding(a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabHorizontalPadding, 0));
setStripColor(a.getColor(R.styleable.TabPagerIndicator_tabStripColor, 0));
setIconColor(a.getColor(R.styleable.TabPagerIndicator_tabIconColor, 0));
setLabelColor(a.getColor(R.styleable.TabPagerIndicator_tabLabelColor, ThemeUtils.getTextColorPrimary(context)));
setTabDisplayOption(a.getInt(R.styleable.TabPagerIndicator_tabDisplayOption, ICON));
setTabShowDivider(a.getBoolean(R.styleable.TabPagerIndicator_tabShowDivider, false));
final int dividerVerticalPadding = a.getDimensionPixelSize(R.styleable.TabPagerIndicator_tabDividerVerticalPadding, 0);
@ -317,12 +319,12 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
@Override
public void onClick(View v) {
indicator.dispatchTabClick(getPosition());
indicator.dispatchTabClick(getAdapterPosition());
}
@Override
public boolean onLongClick(View v) {
return indicator.dispatchTabLongClick(getPosition());
return indicator.dispatchTabLongClick(getAdapterPosition());
}
public void setBadge(int count, boolean display) {

View File

@ -40,6 +40,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/element_size_normal"
android:textColor="?android:textColorSecondary"
android:outlineProvider="background"
app:tabDividerVerticalPadding="@dimen/element_spacing_mlarge"
app:tabExpandEnabled="true"
app:tabHorizontalPadding="@dimen/element_spacing_large"

View File

@ -2,10 +2,15 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@id/compose"
android:icon="@drawable/ic_action_status_compose"
app:showAsAction="always"
android:title="@string/compose"/>
<item
android:id="@id/save"
android:icon="@drawable/ic_action_save"
app:showAsAction="always"
app:showAsAction="ifRoom"
android:title="@string/save"/>
</menu>

View File

@ -19,6 +19,7 @@
<declare-styleable name="TabPagerIndicator">
<attr name="tabStripColor" format="color"/>
<attr name="tabIconColor" format="color"/>
<attr name="tabLabelColor" format="color"/>
<attr name="tabHorizontalPadding" format="dimension"/>
<attr name="tabVerticalPadding" format="dimension"/>
<attr name="tabDividerVerticalPadding" format="dimension"/>

View File

@ -733,6 +733,7 @@
<string name="scale">Scale</string>
<string name="user_type_verified">Verified</string>
<string name="user_type_protected">Protected</string>
<string name="tweet_hashtag">Tweet #<xliff:g id="text">%1$s</xliff:g></string>
</resources>