home tab supports hide retweets/quotes/replies

This commit is contained in:
Mariotaku Lee 2016-06-22 09:21:13 +08:00
parent 48bf2c390e
commit 346ad297f6
14 changed files with 233 additions and 39 deletions

View File

@ -193,6 +193,9 @@ public interface IntentConstants {
String EXTRA_CURRENT_MEDIA = "current_media";
String EXTRA_EXTRAS = "extras";
String EXTRA_MY_FOLLOWING_ONLY = "my_following_only";
String EXTRA_HIDE_RETWEETS = "hide_retweets";
String EXTRA_HIDE_QUOTES = "hide_quotes";
String EXTRA_HIDE_REPLIES = "hide_replies";
String EXTRA_MENTIONS_ONLY = "mentions_only";
String EXTRA_CHANGED = "changed";
String EXTRA_NOTIFY_CHANGE = "notify_change";

View File

@ -988,7 +988,7 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag
true, ReadPositionTag.HOME_TIMELINE, accountKeys);
final long position = mReadStateManager.getPosition(tagWithAccounts);
final int count = DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
position, Statuses.STATUS_TIMESTAMP, true, accountKeys);
spec.args, position, Statuses.STATUS_TIMESTAMP, true, accountKeys);
result.put(i, count);
publishProgress(new TabBadge(i, count));
break;

View File

@ -42,6 +42,7 @@ import org.mariotaku.twidere.activity.HomeActivity;
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.loader.ExtendedObjectCursorLoader;
import org.mariotaku.twidere.model.ParameterizedExpression;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityCursorIndices;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -115,13 +116,13 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
}
final String[] accountSelectionArgs = TwidereArrayUtils.toStringArray(accountKeys, 0,
accountKeys.length);
final Where expression = processWhere(where, accountSelectionArgs);
final ParameterizedExpression expression = processWhere(where, accountSelectionArgs);
final String selection = expression.getSQL();
final ParcelableActivitiesAdapter adapter = getAdapter();
adapter.setShowAccountsColor(accountKeys.length > 1);
final String[] projection = Activities.COLUMNS;
return new CursorActivitiesLoader(context, uri, projection, selection, expression.whereArgs,
sortOrder, fromUser);
return new CursorActivitiesLoader(context, uri, projection, selection,
expression.getParameters(), sortOrder, fromUser);
}
@Override
@ -300,8 +301,8 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
protected abstract boolean isFilterEnabled();
@NonNull
protected Where processWhere(@NonNull final Expression where, @NonNull final String[] whereArgs) {
return new Where(where, whereArgs);
protected ParameterizedExpression processWhere(@NonNull final Expression where, @NonNull final String[] whereArgs) {
return new ParameterizedExpression(where, whereArgs);
}
protected abstract void updateRefreshState();
@ -388,20 +389,6 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
}
public static class Where {
Expression where;
String[] whereArgs;
public Where(@NonNull Expression where, @Nullable String[] whereArgs) {
this.where = where;
this.whereArgs = whereArgs;
}
public String getSQL() {
return where.getSQL();
}
}
public static class CursorActivitiesLoader extends ExtendedObjectCursorLoader<ParcelableActivity> {
public CursorActivitiesLoader(Context context, Uri uri, String[] projection,

View File

@ -40,6 +40,7 @@ import org.mariotaku.twidere.adapter.ListParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.loader.ExtendedObjectCursorLoader;
import org.mariotaku.twidere.model.ParameterizedExpression;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices;
import org.mariotaku.twidere.model.SimpleRefreshTaskParam;
@ -96,14 +97,15 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
} else {
where = accountWhere;
}
final String selection = processWhere(where).getSQL();
final ParcelableStatusesAdapter adapter = getAdapter();
adapter.setShowAccountsColor(accountKeys.length > 1);
final String[] projection = Statuses.COLUMNS;
final String[] selectionArgs = TwidereArrayUtils.toStringArray(accountKeys, 0,
accountKeys.length);
final ParameterizedExpression expression = processWhere(where, selectionArgs);
return new ExtendedObjectCursorLoader<>(context, ParcelableStatusCursorIndices.class, uri,
projection, selection, selectionArgs, sortOrder, fromUser);
projection, expression.getSQL(), expression.getParameters(),
sortOrder, fromUser);
}
@Override
@ -358,8 +360,8 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
protected abstract boolean isFilterEnabled();
protected Expression processWhere(final Expression where) {
return where;
protected ParameterizedExpression processWhere(@NonNull final Expression where, @NonNull final String[] whereArgs) {
return new ParameterizedExpression(where, whereArgs);
}
protected abstract void updateRefreshState();

View File

@ -21,15 +21,24 @@ package org.mariotaku.twidere.fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.annotation.ReadPositionTag;
import org.mariotaku.twidere.model.ParameterizedExpression;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import edu.tsinghua.hotmobi.model.TimelineType;
/**
@ -91,6 +100,24 @@ public class HomeTimelineFragment extends CursorStatusesFragment {
}
}
@Override
protected ParameterizedExpression processWhere(@NonNull final Expression where, @NonNull final String[] whereArgs) {
final Bundle arguments = getArguments();
if (arguments != null) {
final HomeTabExtras extras = arguments.getParcelable(EXTRA_EXTRAS);
if (extras != null) {
List<Expression> expressions = new ArrayList<>();
List<String> expressionArgs = new ArrayList<>();
Collections.addAll(expressionArgs, whereArgs);
expressions.add(where);
DataStoreUtils.processTabExtras(expressions, expressionArgs, extras);
final Expression expression = Expression.and(expressions.toArray(new Expression[expressions.size()]));
return new ParameterizedExpression(expression, expressionArgs.toArray(new String[expressionArgs.size()]));
}
}
return super.processWhere(where, whereArgs);
}
@NonNull
@Override
@TimelineType

View File

@ -30,6 +30,7 @@ import org.mariotaku.microblog.library.twitter.model.Activity;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
import org.mariotaku.twidere.annotation.ReadPositionTag;
import org.mariotaku.twidere.model.ParameterizedExpression;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
@ -79,13 +80,13 @@ public class InteractionsTimelineFragment extends CursorActivitiesFragment {
@Override
@NonNull
protected Where processWhere(@NonNull Expression where, @NonNull String[] whereArgs) {
protected ParameterizedExpression processWhere(@NonNull Expression where, @NonNull String[] whereArgs) {
final Bundle arguments = getArguments();
if (arguments != null) {
final InteractionsTabExtras extras = arguments.getParcelable(EXTRA_EXTRAS);
if (extras != null && extras.isMentionsOnly()) {
final Expression expression = Expression.and(where, Expression.inArgs(Activities.ACTION, 3));
return new Where(expression, ArrayUtils.addAll(whereArgs, Activity.Action.MENTION,
return new ParameterizedExpression(expression, ArrayUtils.addAll(whereArgs, Activity.Action.MENTION,
Activity.Action.REPLY, Activity.Action.QUOTE));
}
}

View File

@ -0,0 +1,27 @@
package org.mariotaku.twidere.model;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.mariotaku.sqliteqb.library.Expression;
/**
* Created by mariotaku on 16/6/22.
*/
public class ParameterizedExpression {
Expression expression;
String[] parameters;
public ParameterizedExpression(@NonNull Expression expression, @Nullable String[] parameters) {
this.expression = expression;
this.parameters = parameters;
}
public String[] getParameters() {
return parameters;
}
public String getSQL() {
return expression.getSQL();
}
}

View File

@ -14,6 +14,7 @@ import org.mariotaku.twidere.model.tab.argument.TabArguments;
import org.mariotaku.twidere.model.tab.argument.TextQueryArguments;
import org.mariotaku.twidere.model.tab.argument.UserArguments;
import org.mariotaku.twidere.model.tab.argument.UserListArguments;
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.model.util.TabArgumentsFieldConverter;
@ -194,12 +195,17 @@ public class Tab {
TabExtras base;
@JsonField(name = "interactions")
InteractionsTabExtras interactions;
@JsonField(name = "home")
HomeTabExtras home;
public static InternalExtras from(TabExtras extras) {
if (extras == null) return null;
InternalExtras result = new InternalExtras();
if (extras instanceof InteractionsTabExtras) {
result.interactions = (InteractionsTabExtras) extras;
}
if (extras instanceof HomeTabExtras) {
result.home = (HomeTabExtras) extras;
} else {
result.base = extras;
}
@ -209,6 +215,8 @@ public class Tab {
public TabExtras getExtras() {
if (interactions != null) {
return interactions;
} else if (home != null) {
return home;
} else {
return base;
}

View File

@ -0,0 +1,88 @@
package org.mariotaku.twidere.model.tab.extra;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import org.mariotaku.twidere.constant.IntentConstants;
/**
* Created by mariotaku on 16/6/22.
*/
@ParcelablePlease
@JsonObject
public class HomeTabExtras extends TabExtras implements Parcelable {
@JsonField(name = "hide_retweets")
boolean hideRetweets;
@JsonField(name = "hide_quotes")
boolean hideQuotes;
@JsonField(name = "hide_replies")
boolean hideReplies;
public boolean isHideRetweets() {
return hideRetweets;
}
public void setHideRetweets(boolean hideRetweets) {
this.hideRetweets = hideRetweets;
}
public boolean isHideQuotes() {
return hideQuotes;
}
public void setHideQuotes(boolean hideQuotes) {
this.hideQuotes = hideQuotes;
}
public boolean isHideReplies() {
return hideReplies;
}
public void setHideReplies(boolean hideReplies) {
this.hideReplies = hideReplies;
}
@Override
public void copyToBundle(Bundle bundle) {
super.copyToBundle(bundle);
bundle.putBoolean(IntentConstants.EXTRA_HIDE_RETWEETS, hideRetweets);
bundle.putBoolean(IntentConstants.EXTRA_HIDE_QUOTES, hideQuotes);
bundle.putBoolean(IntentConstants.EXTRA_HIDE_REPLIES, hideReplies);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
HomeTabExtrasParcelablePlease.writeToParcel(this, dest, flags);
}
@Override
public String toString() {
return "HomeTabExtras{" +
"hideRetweets=" + hideRetweets +
", hideQuotes=" + hideQuotes +
", hideReplies=" + hideReplies +
"} " + super.toString();
}
public static final Creator<HomeTabExtras> CREATOR = new Creator<HomeTabExtras>() {
public HomeTabExtras createFromParcel(Parcel source) {
HomeTabExtras target = new HomeTabExtras();
HomeTabExtrasParcelablePlease.readFromParcel(target, source);
return target;
}
public HomeTabExtras[] newArray(int size) {
return new HomeTabExtras[size];
}
};
}

View File

@ -59,6 +59,14 @@ public class InteractionsTabExtras extends TabExtras implements Parcelable {
InteractionsTabExtrasParcelablePlease.writeToParcel(this, dest, flags);
}
@Override
public String toString() {
return "InteractionsTabExtras{" +
"myFollowingOnly=" + myFollowingOnly +
", mentionsOnly=" + mentionsOnly +
"} " + super.toString();
}
public static final Creator<InteractionsTabExtras> CREATOR = new Creator<InteractionsTabExtras>() {
@Override
public InteractionsTabExtras createFromParcel(Parcel source) {

View File

@ -224,7 +224,7 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
deleteWhereArgs[0] = accountKey.toString();
int olderCount = -1;
if (minPositionKey > 0) {
olderCount = DataStoreUtils.getStatusesCount(context, uri, minPositionKey,
olderCount = DataStoreUtils.getStatusesCount(context, uri, null, minPositionKey,
Statuses.POSITION_KEY, false, accountKey);
}
final int rowsDeleted = resolver.delete(writeUri, deleteWhere, deleteWhereArgs);

View File

@ -60,6 +60,7 @@ import org.mariotaku.twidere.model.tab.argument.TabArguments;
import org.mariotaku.twidere.model.tab.argument.TextQueryArguments;
import org.mariotaku.twidere.model.tab.argument.UserArguments;
import org.mariotaku.twidere.model.tab.argument.UserListArguments;
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
@ -78,7 +79,10 @@ public class CustomTabUtils implements Constants {
static {
CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.HOME_TIMELINE, new CustomTabConfiguration(
HomeTimelineFragment.class, R.string.home, R.drawable.ic_action_home,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false));
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 0, false,
ExtraConfiguration.newBoolean(EXTRA_HIDE_RETWEETS, R.string.hide_retweets, false),
ExtraConfiguration.newBoolean(EXTRA_HIDE_QUOTES, R.string.hide_quotes, false),
ExtraConfiguration.newBoolean(EXTRA_HIDE_REPLIES, R.string.hide_replies, false)));
CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.NOTIFICATIONS_TIMELINE, new CustomTabConfiguration(
InteractionsTimelineFragment.class, R.string.interactions, R.drawable.ic_action_notification,
@ -233,6 +237,9 @@ public class CustomTabUtils implements Constants {
case CustomTabType.NOTIFICATIONS_TIMELINE: {
return JsonSerializer.parse(json, InteractionsTabExtras.class);
}
case CustomTabType.HOME_TIMELINE: {
return JsonSerializer.parse(json, HomeTabExtras.class);
}
}
return null;
}

View File

@ -26,6 +26,7 @@ import android.content.UriMatcher;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@ -60,6 +61,7 @@ import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserFollowState;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.tab.extra.HomeTabExtras;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore;
@ -466,22 +468,39 @@ public class DataStoreUtils implements Constants {
}
}
public static int getStatusesCount(@NonNull final Context context, final Uri uri, final long compare,
public static int getStatusesCount(@NonNull final Context context, final Uri uri,
@Nullable final Bundle extraArgs, final long compare,
String compareColumn, boolean greaterThan, UserKey... accountKeys) {
if (accountKeys == null) {
accountKeys = getActivatedAccountKeys(context);
}
final Expression selection = Expression.and(
Expression.inArgs(new Column(Statuses.ACCOUNT_KEY), accountKeys.length),
greaterThan ? Expression.greaterThanArgs(compareColumn) : Expression.lesserThanArgs(compareColumn),
buildStatusFilterWhereClause(getTableNameByUri(uri), null)
);
final String[] whereArgs = new String[accountKeys.length + 1];
for (int i = 0; i < accountKeys.length; i++) {
whereArgs[i] = accountKeys[i].toString();
List<Expression> expressions = new ArrayList<>();
List<String> expressionArgs = new ArrayList<>();
expressions.add(Expression.inArgs(new Column(Statuses.ACCOUNT_KEY), accountKeys.length));
for (UserKey accountKey : accountKeys) {
expressionArgs.add(accountKey.toString());
}
whereArgs[accountKeys.length] = String.valueOf(compare);
return queryCount(context, uri, selection.getSQL(), whereArgs);
if (greaterThan) {
expressions.add(Expression.greaterThanArgs(compareColumn));
} else {
expressions.add(Expression.lesserThanArgs(compareColumn));
}
expressionArgs.add(String.valueOf(compare));
expressions.add(buildStatusFilterWhereClause(getTableNameByUri(uri), null));
if (extraArgs != null) {
Parcelable extras = extraArgs.getParcelable(EXTRA_EXTRAS);
if (extras instanceof HomeTabExtras) {
processTabExtras(expressions, expressionArgs, (HomeTabExtras) extras);
}
}
Expression selection = Expression.and(expressions.toArray(new Expression[expressions.size()]));
return queryCount(context, uri, selection.getSQL(), expressionArgs.toArray(new String[expressionArgs.size()]));
}
public static int getActivitiesCount(final Context context, final Uri uri, final long compare,
@ -1064,6 +1083,20 @@ public class DataStoreUtils implements Constants {
}
}
public static void processTabExtras(List<Expression> expressions, List<String> expressionArgs, HomeTabExtras extras) {
if (extras.isHideRetweets()) {
expressions.add(Expression.equalsArgs(Statuses.IS_RETWEET));
expressionArgs.add("0");
}
if (extras.isHideQuotes()) {
expressions.add(Expression.equalsArgs(Statuses.IS_QUOTE));
expressionArgs.add("0");
}
if (extras.isHideReplies()) {
expressions.add(Expression.isNull(new Column(Statuses.IN_REPLY_TO_STATUS_ID)));
}
}
interface FieldArrayCreator<T> {
T newArray(int size);

View File

@ -807,4 +807,7 @@
<string name="no_status_content_text">No content</string>
<string name="status_not_available_text">Tweet not available</string>
<string name="share_link">Share link</string>
<string name="hide_retweets">Hide retweets</string>
<string name="hide_quotes">Hide quotes</string>
<string name="hide_replies">Hide replies</string>
</resources>