parent
1e8c6233d3
commit
8069111e51
|
@ -64,6 +64,7 @@ public interface TwidereDataStore {
|
|||
CachedHashtags.CONTENT_URI, CachedTrends.Local.CONTENT_URI};
|
||||
Uri[] DIRECT_MESSAGES_URIS = new Uri[]{DirectMessages.Inbox.CONTENT_URI,
|
||||
DirectMessages.Outbox.CONTENT_URI};
|
||||
Uri[] ACTIVITIES_URIS = new Uri[]{Activities.AboutMe.CONTENT_URI};
|
||||
|
||||
interface InsertedDateColumns {
|
||||
String INSERTED_DATE = "inserted_date";
|
||||
|
|
|
@ -111,7 +111,7 @@ dependencies {
|
|||
compile 'org.attoparser:attoparser:1.4.0.RELEASE'
|
||||
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.10'
|
||||
compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view:0.9.10'
|
||||
compile 'com.github.mariotaku:SQLiteQB:0.9.4'
|
||||
compile 'com.github.mariotaku.SQLiteQB:library:0.9.5-SNAPSHOT'
|
||||
compile 'com.github.mariotaku.ObjectCursor:core:0.9.4'
|
||||
compile project(':twidere.component.common')
|
||||
compile project(':twidere.component.nyan')
|
||||
|
|
|
@ -82,6 +82,7 @@ import org.mariotaku.twidere.model.ParcelableAccount;
|
|||
import org.mariotaku.twidere.model.SupportTabSpec;
|
||||
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
|
||||
import org.mariotaku.twidere.model.message.UnreadCountUpdatedEvent;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
|
@ -917,7 +918,8 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
|||
}
|
||||
}
|
||||
|
||||
private static class UpdateUnreadCountTask extends AsyncTask<Object, Object, SparseIntArray> {
|
||||
private static class UpdateUnreadCountTask extends AsyncTask<Object, UpdateUnreadCountTask.TabBadge,
|
||||
SparseIntArray> {
|
||||
private final Context mContext;
|
||||
private final ReadStateManager mReadStateManager;
|
||||
private final TabPagerIndicator mIndicator;
|
||||
|
@ -934,17 +936,22 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
|||
@Override
|
||||
protected SparseIntArray doInBackground(final Object... params) {
|
||||
final SparseIntArray result = new SparseIntArray();
|
||||
for (int i = 0, count = mTabs.size(); i < count; i++) {
|
||||
for (int i = 0, j = mTabs.size(); i < j; i++) {
|
||||
SupportTabSpec spec = mTabs.get(i);
|
||||
if (spec.type == null) continue;
|
||||
if (spec.type == null) {
|
||||
publishProgress(new TabBadge(i, -1));
|
||||
continue;
|
||||
}
|
||||
switch (spec.type) {
|
||||
case CustomTabType.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(i, DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
|
||||
position, accountIds));
|
||||
final int count = DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
|
||||
position, accountIds);
|
||||
result.put(i, count);
|
||||
publishProgress(new TabBadge(i, count));
|
||||
break;
|
||||
}
|
||||
case CustomTabType.NOTIFICATIONS_TIMELINE: {
|
||||
|
@ -955,20 +962,29 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
|||
|
||||
Expression extraWhere = null;
|
||||
String[] extraWhereArgs = null;
|
||||
boolean followingOnly = false;
|
||||
if (spec.args != null) {
|
||||
Bundle extras = spec.args.getBundle(EXTRA_EXTRAS);
|
||||
if (extras != null && extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
|
||||
extraWhere = Expression.inArgs(Activities.ACTION, 3);
|
||||
extraWhereArgs = new String[]{Activity.Action.MENTION,
|
||||
Activity.Action.REPLY, Activity.Action.QUOTE};
|
||||
if (extras != null) {
|
||||
if (extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
|
||||
extraWhere = Expression.inArgs(Activities.ACTION, 3);
|
||||
extraWhereArgs = new String[]{Activity.Action.MENTION,
|
||||
Activity.Action.REPLY, Activity.Action.QUOTE};
|
||||
}
|
||||
if (extras.getBoolean(EXTRA_MY_FOLLOWING_ONLY)) {
|
||||
followingOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.put(i, DataStoreUtils.getActivitiesCount(mContext,
|
||||
final int count = DataStoreUtils.getActivitiesCount(mContext,
|
||||
Activities.AboutMe.CONTENT_URI, extraWhere, extraWhereArgs,
|
||||
position, accountIds));
|
||||
position, followingOnly, accountIds);
|
||||
publishProgress(new TabBadge(i, count));
|
||||
result.put(i, count);
|
||||
break;
|
||||
}
|
||||
case CustomTabType.DIRECT_MESSAGES: {
|
||||
default: {
|
||||
publishProgress(new TabBadge(i, -1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -984,6 +1000,22 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onProgressUpdate(TabBadge... values) {
|
||||
for (TabBadge value : values) {
|
||||
mIndicator.setBadge(value.index, value.count);
|
||||
}
|
||||
}
|
||||
|
||||
static class TabBadge {
|
||||
int index;
|
||||
int count;
|
||||
|
||||
public TabBadge(int index, int count) {
|
||||
this.index = index;
|
||||
this.count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.mariotaku.twidere.model;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
import org.mariotaku.library.objectcursor.annotation.CursorField;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/2/25.
|
||||
*
|
||||
* This is a subset of {@link ParcelableUser}, which only has two fields, id and is_following,
|
||||
* to minimize processing speed.
|
||||
*/
|
||||
@JsonObject
|
||||
public class UserFollowState {
|
||||
|
||||
@JsonField(name = "id")
|
||||
public long id;
|
||||
|
||||
@JsonField(name = "is_following")
|
||||
public boolean is_following;
|
||||
}
|
|
@ -29,6 +29,9 @@ import android.provider.BaseColumns;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.bluelinelabs.logansquare.JsonMapper;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.mariotaku.sqliteqb.library.ArgsArray;
|
||||
|
@ -48,6 +51,7 @@ import org.mariotaku.twidere.model.ParcelableAccount;
|
|||
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
|
||||
import org.mariotaku.twidere.model.UserFollowState;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
||||
|
@ -72,12 +76,14 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
|
|||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.provider.TwidereDataStore.ACTIVITIES_URIS;
|
||||
import static org.mariotaku.twidere.provider.TwidereDataStore.CACHE_URIS;
|
||||
import static org.mariotaku.twidere.provider.TwidereDataStore.DIRECT_MESSAGES_URIS;
|
||||
import static org.mariotaku.twidere.provider.TwidereDataStore.STATUSES_URIS;
|
||||
|
@ -395,7 +401,7 @@ public class DataStoreUtils implements Constants {
|
|||
|
||||
public static int getActivitiesCount(final Context context, final Uri uri,
|
||||
final Expression extraWhere, final String[] extraWhereArgs,
|
||||
final long sinceTimestamp, final long... accountIds) {
|
||||
final long sinceTimestamp, boolean followingOnly, final long... accountIds) {
|
||||
if (context == null) return 0;
|
||||
final RawItemArray idsIn;
|
||||
if (accountIds == null || accountIds.length == 0 || (accountIds.length == 1 && accountIds[0] < 0)) {
|
||||
|
@ -414,6 +420,45 @@ public class DataStoreUtils implements Constants {
|
|||
expressions[1] = Expression.greaterThan(Activities.TIMESTAMP, sinceTimestamp);
|
||||
expressions[2] = buildActivityFilterWhereClause(getTableNameByUri(uri), null);
|
||||
final Expression selection = Expression.and(expressions);
|
||||
// If followingOnly option is on, we have to iterate over items
|
||||
if (followingOnly) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
final String[] projection = new String[]{Activities.SOURCES};
|
||||
final Cursor cur = resolver.query(uri, projection, selection.getSQL(), extraWhereArgs, null);
|
||||
if (cur == null) return -1;
|
||||
try {
|
||||
final JsonMapper<UserFollowState> mapper;
|
||||
try {
|
||||
mapper = LoganSquareMapperFinder.mapperFor(UserFollowState.class);
|
||||
} catch (LoganSquareMapperFinder.ClassLoaderDeadLockException e) {
|
||||
return -1;
|
||||
}
|
||||
int total = 0;
|
||||
cur.moveToFirst();
|
||||
while (cur.isAfterLast()) {
|
||||
final String string = cur.getString(0);
|
||||
if (TextUtils.isEmpty(string)) continue;
|
||||
boolean hasFollowing = false;
|
||||
try {
|
||||
for (UserFollowState state : mapper.parseList(string)) {
|
||||
if (state.is_following) {
|
||||
hasFollowing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
continue;
|
||||
}
|
||||
if (hasFollowing) {
|
||||
total++;
|
||||
}
|
||||
cur.moveToNext();
|
||||
}
|
||||
return total;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
return queryCount(context, uri, selection.getSQL(), extraWhereArgs);
|
||||
}
|
||||
|
||||
|
@ -648,24 +693,41 @@ public class DataStoreUtils implements Constants {
|
|||
continue;
|
||||
}
|
||||
final String table = getTableNameByUri(uri);
|
||||
final Expression account_where = new Expression(Statuses.ACCOUNT_ID + " = " + accountId);
|
||||
final Expression accountWhere = new Expression(Statuses.ACCOUNT_ID + " = " + accountId);
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
qb.select(new Column(Statuses._ID)).from(new Tables(table));
|
||||
qb.where(Expression.equals(Statuses.ACCOUNT_ID, accountId));
|
||||
qb.orderBy(new OrderBy(Statuses.STATUS_ID, false));
|
||||
qb.limit(itemLimit);
|
||||
final Expression where = Expression.and(Expression.notIn(new Column(Statuses._ID), qb.build()), account_where);
|
||||
qb.select(new Column(Statuses._ID))
|
||||
.from(new Tables(table))
|
||||
.where(Expression.equals(Statuses.ACCOUNT_ID, accountId))
|
||||
.orderBy(new OrderBy(Statuses.STATUS_ID, false))
|
||||
.limit(itemLimit);
|
||||
final Expression where = Expression.and(Expression.lesserThan(new Column(Statuses._ID),
|
||||
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Statuses._ID))).from(qb.build()).build()), accountWhere);
|
||||
resolver.delete(uri, where.getSQL(), null);
|
||||
}
|
||||
for (final Uri uri : ACTIVITIES_URIS) {
|
||||
final String table = getTableNameByUri(uri);
|
||||
final Expression accountWhere = new Expression(Activities.ACCOUNT_ID + " = " + accountId);
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
qb.select(new Column(Activities._ID))
|
||||
.from(new Tables(table))
|
||||
.where(Expression.equals(Activities.ACCOUNT_ID, accountId))
|
||||
.orderBy(new OrderBy(Activities.TIMESTAMP, false))
|
||||
.limit(itemLimit);
|
||||
final Expression where = Expression.and(Expression.lesserThan(new Column(Activities._ID),
|
||||
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Activities._ID))).from(qb.build()).build()), accountWhere);
|
||||
resolver.delete(uri, where.getSQL(), null);
|
||||
}
|
||||
for (final Uri uri : DIRECT_MESSAGES_URIS) {
|
||||
final String table = getTableNameByUri(uri);
|
||||
final Expression account_where = new Expression(DirectMessages.ACCOUNT_ID + " = " + accountId);
|
||||
final Expression accountWhere = new Expression(DirectMessages.ACCOUNT_ID + " = " + accountId);
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
qb.select(new Column(DirectMessages._ID)).from(new Tables(table));
|
||||
qb.where(Expression.equals(DirectMessages.ACCOUNT_ID, accountId));
|
||||
qb.orderBy(new OrderBy(DirectMessages.MESSAGE_ID, false));
|
||||
qb.limit(itemLimit * 10);
|
||||
final Expression where = Expression.and(Expression.notIn(new Column(DirectMessages._ID), qb.build()), account_where);
|
||||
qb.select(new Column(DirectMessages._ID))
|
||||
.from(new Tables(table))
|
||||
.where(Expression.equals(DirectMessages.ACCOUNT_ID, accountId))
|
||||
.orderBy(new OrderBy(DirectMessages.MESSAGE_ID, false))
|
||||
.limit(itemLimit * 10);
|
||||
final Expression where = Expression.and(Expression.lesserThan(new Column(DirectMessages._ID),
|
||||
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(DirectMessages._ID))).from(qb.build()).build()), accountWhere);
|
||||
resolver.delete(uri, where.getSQL(), null);
|
||||
}
|
||||
}
|
||||
|
@ -674,11 +736,12 @@ public class DataStoreUtils implements Constants {
|
|||
final String table = getTableNameByUri(uri);
|
||||
if (table == null) continue;
|
||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||
qb.select(new Column(BaseColumns._ID));
|
||||
qb.from(new Tables(table));
|
||||
qb.orderBy(new OrderBy(BaseColumns._ID, false));
|
||||
qb.limit(itemLimit * 20);
|
||||
final Expression where = Expression.notIn(new Column(BaseColumns._ID), qb.build());
|
||||
qb.select(new Column(BaseColumns._ID))
|
||||
.from(new Tables(table))
|
||||
.orderBy(new OrderBy(BaseColumns._ID, false))
|
||||
.limit(itemLimit * 20);
|
||||
final Expression where = Expression.lesserThan(new Column(BaseColumns._ID),
|
||||
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(BaseColumns._ID))).from(qb.build()).build());
|
||||
resolver.delete(uri, where.getSQL(), null);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue