parent
1e8c6233d3
commit
8069111e51
|
@ -64,6 +64,7 @@ public interface TwidereDataStore {
|
||||||
CachedHashtags.CONTENT_URI, CachedTrends.Local.CONTENT_URI};
|
CachedHashtags.CONTENT_URI, CachedTrends.Local.CONTENT_URI};
|
||||||
Uri[] DIRECT_MESSAGES_URIS = new Uri[]{DirectMessages.Inbox.CONTENT_URI,
|
Uri[] DIRECT_MESSAGES_URIS = new Uri[]{DirectMessages.Inbox.CONTENT_URI,
|
||||||
DirectMessages.Outbox.CONTENT_URI};
|
DirectMessages.Outbox.CONTENT_URI};
|
||||||
|
Uri[] ACTIVITIES_URIS = new Uri[]{Activities.AboutMe.CONTENT_URI};
|
||||||
|
|
||||||
interface InsertedDateColumns {
|
interface InsertedDateColumns {
|
||||||
String INSERTED_DATE = "inserted_date";
|
String INSERTED_DATE = "inserted_date";
|
||||||
|
|
|
@ -111,7 +111,7 @@ dependencies {
|
||||||
compile 'org.attoparser:attoparser:1.4.0.RELEASE'
|
compile 'org.attoparser:attoparser:1.4.0.RELEASE'
|
||||||
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.10'
|
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.10'
|
||||||
compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view: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 'com.github.mariotaku.ObjectCursor:core:0.9.4'
|
||||||
compile project(':twidere.component.common')
|
compile project(':twidere.component.common')
|
||||||
compile project(':twidere.component.nyan')
|
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.SupportTabSpec;
|
||||||
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
|
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
|
||||||
import org.mariotaku.twidere.model.message.UnreadCountUpdatedEvent;
|
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.Accounts;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
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 Context mContext;
|
||||||
private final ReadStateManager mReadStateManager;
|
private final ReadStateManager mReadStateManager;
|
||||||
private final TabPagerIndicator mIndicator;
|
private final TabPagerIndicator mIndicator;
|
||||||
|
@ -934,17 +936,22 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
||||||
@Override
|
@Override
|
||||||
protected SparseIntArray doInBackground(final Object... params) {
|
protected SparseIntArray doInBackground(final Object... params) {
|
||||||
final SparseIntArray result = new SparseIntArray();
|
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);
|
SupportTabSpec spec = mTabs.get(i);
|
||||||
if (spec.type == null) continue;
|
if (spec.type == null) {
|
||||||
|
publishProgress(new TabBadge(i, -1));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
switch (spec.type) {
|
switch (spec.type) {
|
||||||
case CustomTabType.HOME_TIMELINE: {
|
case CustomTabType.HOME_TIMELINE: {
|
||||||
final long[] accountIds = Utils.getAccountIds(spec.args);
|
final long[] accountIds = Utils.getAccountIds(spec.args);
|
||||||
final String tagWithAccounts = Utils.getReadPositionTagWithAccounts(mContext,
|
final String tagWithAccounts = Utils.getReadPositionTagWithAccounts(mContext,
|
||||||
true, spec.tag, accountIds);
|
true, spec.tag, accountIds);
|
||||||
final long position = mReadStateManager.getPosition(tagWithAccounts);
|
final long position = mReadStateManager.getPosition(tagWithAccounts);
|
||||||
result.put(i, DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
|
final int count = DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
|
||||||
position, accountIds));
|
position, accountIds);
|
||||||
|
result.put(i, count);
|
||||||
|
publishProgress(new TabBadge(i, count));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CustomTabType.NOTIFICATIONS_TIMELINE: {
|
case CustomTabType.NOTIFICATIONS_TIMELINE: {
|
||||||
|
@ -955,20 +962,29 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
||||||
|
|
||||||
Expression extraWhere = null;
|
Expression extraWhere = null;
|
||||||
String[] extraWhereArgs = null;
|
String[] extraWhereArgs = null;
|
||||||
|
boolean followingOnly = false;
|
||||||
if (spec.args != null) {
|
if (spec.args != null) {
|
||||||
Bundle extras = spec.args.getBundle(EXTRA_EXTRAS);
|
Bundle extras = spec.args.getBundle(EXTRA_EXTRAS);
|
||||||
if (extras != null && extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
|
if (extras != null) {
|
||||||
extraWhere = Expression.inArgs(Activities.ACTION, 3);
|
if (extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
|
||||||
extraWhereArgs = new String[]{Activity.Action.MENTION,
|
extraWhere = Expression.inArgs(Activities.ACTION, 3);
|
||||||
Activity.Action.REPLY, Activity.Action.QUOTE};
|
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,
|
Activities.AboutMe.CONTENT_URI, extraWhere, extraWhereArgs,
|
||||||
position, accountIds));
|
position, followingOnly, accountIds);
|
||||||
|
publishProgress(new TabBadge(i, count));
|
||||||
|
result.put(i, count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CustomTabType.DIRECT_MESSAGES: {
|
default: {
|
||||||
|
publishProgress(new TabBadge(i, -1));
|
||||||
break;
|
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.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.LongSparseArray;
|
import android.support.v4.util.LongSparseArray;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.bluelinelabs.logansquare.JsonMapper;
|
||||||
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.mariotaku.sqliteqb.library.ArgsArray;
|
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.ParcelableAccountCursorIndices;
|
||||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||||
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
|
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
|
||||||
|
import org.mariotaku.twidere.model.UserFollowState;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
|
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.Tabs;
|
||||||
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static android.text.TextUtils.isEmpty;
|
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.CACHE_URIS;
|
||||||
import static org.mariotaku.twidere.provider.TwidereDataStore.DIRECT_MESSAGES_URIS;
|
import static org.mariotaku.twidere.provider.TwidereDataStore.DIRECT_MESSAGES_URIS;
|
||||||
import static org.mariotaku.twidere.provider.TwidereDataStore.STATUSES_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,
|
public static int getActivitiesCount(final Context context, final Uri uri,
|
||||||
final Expression extraWhere, final String[] extraWhereArgs,
|
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;
|
if (context == null) return 0;
|
||||||
final RawItemArray idsIn;
|
final RawItemArray idsIn;
|
||||||
if (accountIds == null || accountIds.length == 0 || (accountIds.length == 1 && accountIds[0] < 0)) {
|
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[1] = Expression.greaterThan(Activities.TIMESTAMP, sinceTimestamp);
|
||||||
expressions[2] = buildActivityFilterWhereClause(getTableNameByUri(uri), null);
|
expressions[2] = buildActivityFilterWhereClause(getTableNameByUri(uri), null);
|
||||||
final Expression selection = Expression.and(expressions);
|
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);
|
return queryCount(context, uri, selection.getSQL(), extraWhereArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,24 +693,41 @@ public class DataStoreUtils implements Constants {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final String table = getTableNameByUri(uri);
|
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();
|
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||||
qb.select(new Column(Statuses._ID)).from(new Tables(table));
|
qb.select(new Column(Statuses._ID))
|
||||||
qb.where(Expression.equals(Statuses.ACCOUNT_ID, accountId));
|
.from(new Tables(table))
|
||||||
qb.orderBy(new OrderBy(Statuses.STATUS_ID, false));
|
.where(Expression.equals(Statuses.ACCOUNT_ID, accountId))
|
||||||
qb.limit(itemLimit);
|
.orderBy(new OrderBy(Statuses.STATUS_ID, false))
|
||||||
final Expression where = Expression.and(Expression.notIn(new Column(Statuses._ID), qb.build()), account_where);
|
.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);
|
resolver.delete(uri, where.getSQL(), null);
|
||||||
}
|
}
|
||||||
for (final Uri uri : DIRECT_MESSAGES_URIS) {
|
for (final Uri uri : DIRECT_MESSAGES_URIS) {
|
||||||
final String table = getTableNameByUri(uri);
|
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();
|
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||||
qb.select(new Column(DirectMessages._ID)).from(new Tables(table));
|
qb.select(new Column(DirectMessages._ID))
|
||||||
qb.where(Expression.equals(DirectMessages.ACCOUNT_ID, accountId));
|
.from(new Tables(table))
|
||||||
qb.orderBy(new OrderBy(DirectMessages.MESSAGE_ID, false));
|
.where(Expression.equals(DirectMessages.ACCOUNT_ID, accountId))
|
||||||
qb.limit(itemLimit * 10);
|
.orderBy(new OrderBy(DirectMessages.MESSAGE_ID, false))
|
||||||
final Expression where = Expression.and(Expression.notIn(new Column(DirectMessages._ID), qb.build()), account_where);
|
.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);
|
resolver.delete(uri, where.getSQL(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -674,11 +736,12 @@ public class DataStoreUtils implements Constants {
|
||||||
final String table = getTableNameByUri(uri);
|
final String table = getTableNameByUri(uri);
|
||||||
if (table == null) continue;
|
if (table == null) continue;
|
||||||
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
|
||||||
qb.select(new Column(BaseColumns._ID));
|
qb.select(new Column(BaseColumns._ID))
|
||||||
qb.from(new Tables(table));
|
.from(new Tables(table))
|
||||||
qb.orderBy(new OrderBy(BaseColumns._ID, false));
|
.orderBy(new OrderBy(BaseColumns._ID, false))
|
||||||
qb.limit(itemLimit * 20);
|
.limit(itemLimit * 20);
|
||||||
final Expression where = Expression.notIn(new Column(BaseColumns._ID), qb.build());
|
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);
|
resolver.delete(uri, where.getSQL(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue