1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-01 01:06:53 +01:00
fixed some NPEs
This commit is contained in:
Mariotaku Lee 2016-03-20 12:48:47 +08:00
parent 0fcf75b21e
commit d12e331583
26 changed files with 204 additions and 107 deletions

View File

@ -300,14 +300,12 @@ public interface TwidereDataStore {
String EXTRAS = "extras";
String USER_HOST = "user_host";
String[] COLUMNS = {_ID, USER_KEY, CREATED_AT, NAME, SCREEN_NAME, DESCRIPTION_PLAIN, LOCATION,
URL, PROFILE_IMAGE_URL, PROFILE_BANNER_URL, PROFILE_BACKGROUND_URL, IS_PROTECTED,
IS_VERIFIED, IS_FOLLOWING, FOLLOWERS_COUNT, FRIENDS_COUNT, STATUSES_COUNT,
FAVORITES_COUNT, LISTED_COUNT, MEDIA_COUNT, DESCRIPTION_HTML, DESCRIPTION_EXPANDED,
URL_EXPANDED, BACKGROUND_COLOR, LINK_COLOR, TEXT_COLOR, LAST_SEEN,
DESCRIPTION_UNESCAPED, EXTRAS, USER_HOST};
DESCRIPTION_UNESCAPED, EXTRAS};
String[] BASIC_COLUMNS = {_ID, USER_KEY, NAME, SCREEN_NAME, PROFILE_IMAGE_URL};
@ -315,7 +313,7 @@ public interface TwidereDataStore {
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
TYPE_TEXT, TYPE_TEXT};
}
@ -1006,8 +1004,7 @@ public interface TwidereDataStore {
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
String USER_ID = "user_id";
String USER_KEY = "user_id";
String FOLLOWING = "following";
@ -1021,7 +1018,7 @@ public interface TwidereDataStore {
String RETWEET_ENABLED = "retweet_enabled";
String[] COLUMNS = {_ID, ACCOUNT_KEY, USER_ID, FOLLOWING, FOLLOWED_BY, BLOCKING,
String[] COLUMNS = {_ID, ACCOUNT_KEY, USER_KEY, FOLLOWING, FOLLOWED_BY, BLOCKING,
BLOCKED_BY, MUTING, RETWEET_ENABLED};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_TEXT_NOT_NULL, TYPE_TEXT_NOT_NULL,

View File

@ -3,6 +3,9 @@ package org.mariotaku.twidere.util;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
/**
* Created by mariotaku on 16/1/31.
*/
@ -10,5 +13,22 @@ public class TwidereArrayUtilsTest {
@Test
public void testMergeArray() throws Exception {
String[] array1 = {"1", "2"};
String[] array2 = {"1", "2"};
String[] array3 = null;
String[] merged = new String[TwidereArrayUtils.arraysLength(array1, array2, array3)];
TwidereArrayUtils.mergeArray(merged, array1, array2, array3);
String[] expected = {"1", "2", "1", "2"};
assertArrayEquals(expected, merged);
}
@Test
public void testArraysLength() throws Exception {
String[] array1 = {"1", "2"};
String[] array2 = {"1", "2"};
String[] array3 = null;
assertEquals(4, TwidereArrayUtils.arraysLength(array1, array2, array3));
assertEquals(6, TwidereArrayUtils.arraysLength(array1, array2, array2));
}
}

View File

@ -34,7 +34,7 @@ import static org.mariotaku.twidere.annotation.PreferenceType.STRING;
public interface Constants extends TwidereConstants {
String DATABASES_NAME = "twidere.sqlite";
int DATABASES_VERSION = 134;
int DATABASES_VERSION = 135;
int MENU_GROUP_STATUS_EXTENSION = 10;
int MENU_GROUP_COMPOSE_EXTENSION = 11;

View File

@ -42,7 +42,6 @@ import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import org.mariotaku.twidere.view.ProfileImageView;
import javax.inject.Inject;
@ -112,12 +111,15 @@ public class UserAutoCompleteAdapter extends SimpleCursorAdapter implements Cons
if (filter != null) return filter.runQuery(constraint);
final String query = constraint.toString();
final String queryEscaped = query.replace("_", "^_");
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager);
final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression usersSelection = Expression.or(
Expression.likeRaw(new Columns.Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Columns.Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Columns.Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds)));
final String[] selectionArgs = new String[]{queryEscaped, queryEscaped};
Expression.inArgs(new Columns.Column(CachedUsers.USER_KEY), nicknameKeys.length));
//TODO
final String[] selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME,
CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true};

View File

@ -208,7 +208,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
@Nullable
@Override
public long[] getMaxSortIds() {
return DataStoreUtils.getOldestActivityMaxSortPositions(getActivity(),
return DataStoreUtils.getOldestActivityMaxSortPositions(getContext(),
getContentUri(), getAccountKeys());
}
@ -216,6 +216,11 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
public boolean hasMaxIds() {
return true;
}
@Override
public boolean shouldAbort() {
return getContext() == null;
}
});
}
@ -238,7 +243,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
@Nullable
@Override
public long[] getSinceSortIds() {
return DataStoreUtils.getNewestActivityMaxSortPositions(getActivity(),
return DataStoreUtils.getNewestActivityMaxSortPositions(getContext(),
getContentUri(), getAccountKeys());
}
@ -246,6 +251,11 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
public boolean hasSinceIds() {
return true;
}
@Override
public boolean shouldAbort() {
return getContext() == null;
}
});
return true;
}

View File

@ -253,7 +253,6 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
// Only supports load from end, skip START flag
if ((position & IndicatorPosition.START) != 0) return;
super.onLoadMoreContents(position);
final Context context = getContext();
if (position == 0) return;
getStatuses(new SimpleRefreshTaskParam() {
@NonNull
@ -271,7 +270,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
@Nullable
@Override
public long[] getMaxSortIds() {
return DataStoreUtils.getOldestStatusSortIds(context, getContentUri(),
return DataStoreUtils.getOldestStatusSortIds(getContext(), getContentUri(),
getAccountKeys());
}
@ -279,13 +278,17 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
public boolean hasMaxIds() {
return true;
}
@Override
public boolean shouldAbort() {
return getContext() == null;
}
});
}
@Override
public boolean triggerRefresh() {
super.triggerRefresh();
final Context context = getContext();
getStatuses(new SimpleRefreshTaskParam() {
@NonNull
@Override
@ -307,9 +310,14 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment {
@Nullable
@Override
public long[] getSinceSortIds() {
return DataStoreUtils.getNewestStatusSortIds(context, getContentUri(),
return DataStoreUtils.getNewestStatusSortIds(getContext(), getContentUri(),
getAccountKeys());
}
@Override
public boolean shouldAbort() {
return getContext() == null;
}
});
return true;
}

View File

@ -864,11 +864,13 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
final Expression selection;
final String[] selectionArgs;
if (queryEscaped != null) {
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager);
final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
selection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds)));
selectionArgs = new String[]{queryEscaped, queryEscaped};
Expression.inArgs(new Column(CachedUsers.USER_KEY), nicknameKeys.length));
selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
} else {
selection = null;
selectionArgs = null;

View File

@ -158,7 +158,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment {
final String[] maxIds = {status.id};
mPage += mPageDelta;
final BaseRefreshTaskParam param = new BaseRefreshTaskParam(accountKeys, maxIds, null);
param.setIsLoadingMore(true);
param.setLoadingMore(true);
getStatuses(param);
}

View File

@ -244,6 +244,7 @@ public abstract class ParcelableUsersFragment extends AbsContentListRecyclerView
final ParcelableUsersAdapter adapter = getAdapter();
final int position = findPosition(adapter, event.getAccountKey(), event.getUserKey());
final List<ParcelableUser> data = adapter.getData();
if (position < 0 || position >= data.size()) return;
if (shouldRemoveUser(position, event)) {
data.remove(position);
adapter.notifyItemRemoved(position);

View File

@ -1825,7 +1825,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
return SingleResponse.getInstance(new TwitterException("No Account"));
}
final boolean isFiltering = DataStoreUtils.isFilteringUser(context, mUserId);
if (mAccountKey.getId() == mUserId)
if (mAccountKey.getId().equals(mUserId))
return SingleResponse.getInstance();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountKey, false);
if (twitter == null) {
@ -1839,7 +1839,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
} else {
Utils.setLastSeen(context, userKey, System.currentTimeMillis());
}
Utils.updateRelationship(context, relationship, mAccountKey);
Utils.updateRelationship(context, mAccountKey, userKey, relationship);
return SingleResponse.getInstance(new UserRelationship(relationship, isFiltering));
} catch (final TwitterException e) {
return SingleResponse.getInstance(e);

View File

@ -14,6 +14,7 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
private final long[] maxSortIds;
private final long[] sinceSortIds;
private boolean isLoadingMore;
private boolean shouldAbort;
public BaseRefreshTaskParam(UserKey[] accountKeys, String[] maxIds, String[] sinceIds) {
this(accountKeys, maxIds, sinceIds, null, null);
@ -71,7 +72,16 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
return isLoadingMore;
}
public void setIsLoadingMore(boolean isLoadingMore) {
public void setLoadingMore(boolean isLoadingMore) {
this.isLoadingMore = isLoadingMore;
}
@Override
public boolean shouldAbort() {
return shouldAbort;
}
public void setShouldAbort(boolean shouldAbort) {
this.shouldAbort = shouldAbort;
}
}

View File

@ -16,7 +16,7 @@ public class CachedRelationship {
@CursorField(CachedRelationships.ACCOUNT_KEY)
public UserKey account_key;
@CursorField(CachedRelationships.USER_ID)
@CursorField(CachedRelationships.USER_KEY)
public String user_id;
@CursorField(CachedRelationships.FOLLOWING)

View File

@ -28,4 +28,6 @@ public interface RefreshTaskParam {
boolean isLoadingMore();
boolean shouldAbort();
}

View File

@ -58,4 +58,9 @@ public abstract class SimpleRefreshTaskParam implements RefreshTaskParam {
public boolean isLoadingMore() {
return false;
}
@Override
public boolean shouldAbort() {
return false;
}
}

View File

@ -469,52 +469,63 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return null;
}
final long rowId;
if (tableId == TABLE_ID_CACHED_USERS) {
final Expression where = Expression.and(Expression.equalsArgs(CachedUsers.USER_KEY),
Expression.equalsArgs(CachedUsers.USER_HOST));
final String[] whereArgs = {values.getAsString(CachedUsers.USER_KEY),
values.getAsString(CachedUsers.USER_HOST)};
mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
} else if (tableId == TABLE_ID_SEARCH_HISTORY) {
values.put(SearchHistory.RECENT_QUERY, System.currentTimeMillis());
final Expression where = Expression.equalsArgs(SearchHistory.QUERY);
final String[] args = {values.getAsString(SearchHistory.QUERY)};
mDatabaseWrapper.update(table, values, where.getSQL(), args);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
} else if (tableId == TABLE_ID_CACHED_RELATIONSHIPS) {
final String accountKey = values.getAsString(CachedRelationships.ACCOUNT_KEY);
final String userId = values.getAsString(CachedRelationships.USER_ID);
final Expression where = Expression.and(
Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY),
Expression.equalsArgs(CachedRelationships.USER_ID)
);
final String[] whereArgs = {accountKey, userId};
if (mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs) > 0) {
final String[] projection = {CachedRelationships._ID};
final Cursor c = mDatabaseWrapper.query(table, projection, where.getSQL(), null,
null, null, null);
if (c.moveToFirst()) {
rowId = c.getLong(0);
} else {
rowId = 0;
}
c.close();
} else {
switch (tableId) {
case TABLE_ID_CACHED_USERS: {
final Expression where = Expression.equalsArgs(CachedUsers.USER_KEY);
final String[] whereArgs = {values.getAsString(CachedUsers.USER_KEY)};
mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
break;
}
case TABLE_ID_SEARCH_HISTORY: {
values.put(SearchHistory.RECENT_QUERY, System.currentTimeMillis());
final Expression where = Expression.equalsArgs(SearchHistory.QUERY);
final String[] args = {values.getAsString(SearchHistory.QUERY)};
mDatabaseWrapper.update(table, values, where.getSQL(), args);
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
break;
}
case TABLE_ID_CACHED_RELATIONSHIPS: {
final String accountKey = values.getAsString(CachedRelationships.ACCOUNT_KEY);
final String userId = values.getAsString(CachedRelationships.USER_KEY);
final Expression where = Expression.and(
Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY),
Expression.equalsArgs(CachedRelationships.USER_KEY)
);
final String[] whereArgs = {accountKey, userId};
if (mDatabaseWrapper.update(table, values, where.getSQL(), whereArgs) > 0) {
final String[] projection = {CachedRelationships._ID};
final Cursor c = mDatabaseWrapper.query(table, projection, where.getSQL(), null,
null, null, null);
if (c.moveToFirst()) {
rowId = c.getLong(0);
} else {
rowId = 0;
}
c.close();
} else {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_IGNORE);
}
break;
}
case VIRTUAL_TABLE_ID_DRAFTS_NOTIFICATIONS: {
rowId = showDraftNotification(values);
break;
}
default: {
if (shouldReplaceOnConflict(tableId)) {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
} else if (table != null) {
rowId = mDatabaseWrapper.insert(table, null, values);
} else {
return null;
}
break;
}
} else if (tableId == VIRTUAL_TABLE_ID_DRAFTS_NOTIFICATIONS) {
rowId = showDraftNotification(values);
} else if (shouldReplaceOnConflict(tableId)) {
rowId = mDatabaseWrapper.insertWithOnConflict(table, null, values,
SQLiteDatabase.CONFLICT_REPLACE);
} else if (table != null) {
rowId = mDatabaseWrapper.insert(table, null, values);
} else {
return null;
}
onDatabaseUpdated(tableId, uri);
onNewItemsInserted(uri, tableId, values);
@ -729,7 +740,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_RELATIONSHIP: {
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withRelationship(projection,
selection, sortOrder, accountKey);
selection, selectionArgs, sortOrder, accountKey);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI);
return c;
@ -737,7 +748,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_SCORE: {
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withScore(projection,
selection, sortOrder, accountKey, 0);
selection, selectionArgs, sortOrder, accountKey, 0);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI);
return c;
@ -834,19 +845,21 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
new Column(CachedUsers.SCREEN_NAME, Suggestions.Search.VALUE).getSQL(),
};
String queryTrimmed = queryEscaped.startsWith("@") ? queryEscaped.substring(1) : queryEscaped;
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager);
final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression usersSelection = Expression.or(
Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds)));
final String[] selectionArgs = new String[]{queryTrimmed, queryTrimmed};
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameKeys)));
final String[] selectionArgs = new String[nicknameKeys.length + 2];
selectionArgs[0] = selectionArgs[1] = queryTrimmed;
System.arraycopy(nicknameKeys, 0, selectionArgs, 2, nicknameKeys.length);
final String[] order = {CachedUsers.LAST_SEEN, CachedUsers.SCORE, CachedUsers.SCREEN_NAME,
CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true};
final OrderBy orderBy = new OrderBy(order, ascending);
final Pair<SQLSelectQuery, String[]> usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
usersSelection.getSQL(), orderBy.getSQL(), accountKey, 0);
usersSelection.getSQL(), selectionArgs, orderBy.getSQL(), accountKey, 0);
@SuppressLint("Recycle") final Cursor usersCursor = mDatabaseWrapper.rawQuery(usersQuery.first.getSQL(), usersQuery.second);
final Expression exactUserSelection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?", "^"));
final Cursor exactUserCursor = mDatabaseWrapper.query(CachedUsers.TABLE_NAME,
@ -878,11 +891,13 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
if (query == null || type == null) return null;
final String queryEscaped = query.replace("_", "^_");
if (Suggestions.AutoComplete.TYPE_USERS.equals(type)) {
final long[] nicknameIds = Utils.getMatchedNicknameIds(query, mUserColorNameManager);
final String[] nicknameKeys = Utils.getMatchedNicknameKeys(query, mUserColorNameManager);
final Expression where = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?||'%'", "^"),
Expression.likeRaw(new Column(CachedUsers.NAME), "?||'%'", "^"),
Expression.in(new Column(CachedUsers.USER_KEY), new RawItemArray(nicknameIds)));
final String[] whereArgs = {queryEscaped, queryEscaped};
Expression.inArgs(new Column(CachedUsers.USER_KEY), nicknameKeys.length));
final String[] whereArgs = new String[nicknameKeys.length + 2];
whereArgs[0] = whereArgs[1] = queryEscaped;
System.arraycopy(nicknameKeys, 0, whereArgs, 2, nicknameKeys.length);
final String[] mappedProjection = {
new Column(CachedUsers._ID, Suggestions._ID).getSQL(),
new Column("'" + Suggestions.AutoComplete.TYPE_USERS + "'", Suggestions.TYPE).getSQL(),

View File

@ -59,7 +59,7 @@ public class CreateUserBlockTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString());
values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.BLOCKING, true);
values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false);

View File

@ -53,7 +53,7 @@ public class CreateUserMuteTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString());
values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.MUTING, true);
resolver.insert(CachedRelationships.CONTENT_URI, values);
}

View File

@ -46,7 +46,7 @@ public class DestroyUserBlockTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString());
values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.BLOCKING, false);
values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false);

View File

@ -39,7 +39,7 @@ public class DestroyUserMuteTask extends AbsFriendshipOperationTask {
// I bet you don't want to see this user in your auto complete list.
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, args.accountKey.toString());
values.put(CachedRelationships.USER_ID, args.userKey.toString());
values.put(CachedRelationships.USER_KEY, args.userKey.toString());
values.put(CachedRelationships.MUTING, false);
resolver.insert(CachedRelationships.CONTENT_URI, values);
}

View File

@ -64,6 +64,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
@Override
public Object doLongOperation(RefreshTaskParam param) {
if (param.shouldAbort()) return null;
final UserKey[] accountIds = param.getAccountKeys();
final String[] maxIds = param.getMaxIds();
final String[] sinceIds = param.getSinceIds();

View File

@ -807,7 +807,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
values.put(CachedRelationships.BLOCKING, true);
values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false);
final String where = Expression.inArgs(CachedRelationships.USER_ID, list.size()).getSQL();
final String where = Expression.inArgs(CachedRelationships.USER_KEY, list.size()).getSQL();
final String[] selectionArgs = list.toArray(new String[list.size()]);
mResolver.update(CachedRelationships.CONTENT_URI, values, where, selectionArgs);
}

View File

@ -65,10 +65,11 @@ import static org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText;
public final class ContentValuesCreator implements TwidereConstants {
public static ContentValues createCachedRelationship(final Relationship relationship,
final UserKey accountKey) {
final UserKey accountKey,
final UserKey userKey) {
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, accountKey.toString());
values.put(CachedRelationships.USER_ID, relationship.getTargetUserId());
values.put(CachedRelationships.USER_KEY, userKey.toString());
values.put(CachedRelationships.FOLLOWING, relationship.isSourceFollowingTarget());
values.put(CachedRelationships.FOLLOWED_BY, relationship.isSourceFollowedByTarget());
values.put(CachedRelationships.BLOCKING, relationship.isSourceBlockingTarget());

View File

@ -96,11 +96,21 @@ public final class TwidereArrayUtils {
return list1.toArray((T[]) Array.newInstance(array1.getClass().getComponentType(), list1.size()));
}
@SuppressWarnings("SuspiciousSystemArraycopy")
public static int arraysLength(@NonNull final Object... arrays) {
int length = 0;
for (Object array : arrays) {
if (array == null) continue;
length += Array.getLength(array);
}
return length;
}
public static void mergeArray(final Object dest, @NonNull final Object... arrays) {
for (int i = 0, j = arrays.length, k = 0; i < j; i++) {
final Object array = arrays[i];
if (array == null) continue;
final int length = Array.getLength(array);
//noinspection SuspiciousSystemArraycopy
System.arraycopy(array, 0, dest, k, length);
k += length;
}

View File

@ -49,22 +49,24 @@ public class TwidereQueryBuilder {
public static Pair<SQLSelectQuery, String[]> withRelationship(final String[] projection,
final String selection,
final String[] selectionArgs,
final String sortOrder,
final UserKey accountKey) {
return withRelationship(Utils.getColumnsFromProjection(projection), selection,
sortOrder, accountKey);
selectionArgs, sortOrder, accountKey);
}
public static Pair<SQLSelectQuery, String[]> withRelationship(final Selectable select,
final String selection,
final String[] selectionArgs,
final String sortOrder,
final UserKey accountKey) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(select).from(new Tables(CachedUsers.TABLE_NAME));
final Column relationshipsUserId = new Column(new Table(CachedRelationships.TABLE_NAME),
CachedRelationships.USER_ID);
CachedRelationships.USER_KEY);
final Column usersUserId = new Column(new Table(CachedUsers.TABLE_NAME),
CachedRelationships.USER_ID);
CachedRelationships.USER_KEY);
final Column relationshipsAccountId = new Column(new Table(CachedRelationships.TABLE_NAME),
CachedRelationships.ACCOUNT_KEY);
final Expression on = Expression.and(
@ -78,11 +80,17 @@ public class TwidereQueryBuilder {
if (sortOrder != null) {
qb.orderBy(new OrderBy(sortOrder));
}
return Pair.create(qb.build(), new String[]{accountKey.toString()});
final String[] accountKeyArgs = {accountKey.toString()};
final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(accountKeyArgs, selectionArgs)];
TwidereArrayUtils.mergeArray(mergedArgs, accountKeyArgs, selectionArgs);
return Pair.create(qb.build(), mergedArgs);
}
public static Pair<SQLSelectQuery, String[]> withScore(final String[] projection, final String selection,
final String sortOrder, final UserKey accountKey,
public static Pair<SQLSelectQuery, String[]> withScore(final String[] projection,
final String selection,
final String[] selectionArgs,
final String sortOrder,
final UserKey accountKey,
final int limit) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
final Selectable select = Utils.getColumnsFromProjection(projection);
@ -101,8 +109,11 @@ public class TwidereQueryBuilder {
CachedRelationships.MUTING));
columns[columns.length - 1] = new Column(expr, "score");
qb.select(select);
final Pair<SQLSelectQuery, String[]> pair = withRelationship(new Columns(columns), null, null, accountKey);
final Pair<SQLSelectQuery, String[]> pair = withRelationship(new Columns(columns), null,
null, null, accountKey);
qb.from(pair.first);
final String[] mergedArgs = new String[TwidereArrayUtils.arraysLength(pair.second, selectionArgs)];
TwidereArrayUtils.mergeArray(mergedArgs, pair.second, selectionArgs);
if (selection != null) {
qb.where(new Expression(selection));
}
@ -112,7 +123,7 @@ public class TwidereQueryBuilder {
if (limit > 0) {
qb.limit(limit);
}
return Pair.create(qb.build(), pair.second);
return Pair.create(qb.build(), mergedArgs);
}
private static Object[] valueOrZero(String... columns) {

View File

@ -1322,21 +1322,21 @@ public final class Utils implements Constants {
return nf.format(number);
}
public static long[] getMatchedNicknameIds(final String str, UserColorNameManager manager) {
if (isEmpty(str)) return new long[0];
final List<Long> list = new ArrayList<>();
@NonNull
public static String[] getMatchedNicknameKeys(final String str, UserColorNameManager manager) {
if (isEmpty(str)) return new String[0];
final List<String> list = new ArrayList<>();
for (final Entry<String, ?> entry : manager.getNameEntries()) {
final String value = ParseUtils.parseString(entry.getValue());
final long def = -1;
final long key = NumberUtils.toLong(entry.getKey(), def);
if (key == -1 || isEmpty(value)) {
final String key = entry.getKey();
if (isEmpty(key) || isEmpty(value)) {
continue;
}
if (TwidereStringUtils.startsWithIgnoreCase(value, str)) {
list.add(key);
}
}
return TwidereArrayUtils.fromList(list);
return list.toArray(new String[list.size()]);
}
@NonNull
@ -1994,9 +1994,11 @@ public final class Utils implements Constants {
return orig.replaceAll("\\n+", "\n");
}
public static void updateRelationship(Context context, Relationship relationship, UserKey accountId) {
public static void updateRelationship(Context context, UserKey accountKey, UserKey userKey,
Relationship relationship) {
final ContentResolver resolver = context.getContentResolver();
final ContentValues values = ContentValuesCreator.createCachedRelationship(relationship, accountId);
final ContentValues values = ContentValuesCreator.createCachedRelationship(relationship,
accountKey, userKey);
resolver.insert(CachedRelationships.CONTENT_URI, values);
}

View File

@ -83,11 +83,11 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
db.execSQL(createTable(Activities.ByFriends.TABLE_NAME, Activities.ByFriends.COLUMNS, Activities.ByFriends.TYPES, true));
db.execSQL(createTable(Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, true));
db.execSQL(createTable(CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true,
createConflictReplaceConstraint(CachedUsers.USER_KEY, CachedUsers.USER_HOST)));
createConflictReplaceConstraint(CachedUsers.USER_KEY)));
db.execSQL(createTable(CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true));
db.execSQL(createTable(CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true));
db.execSQL(createTable(CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true,
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_ID)));
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_KEY)));
db.execSQL(createTable(Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES, true));
db.execSQL(createTable(Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES, true));
db.execSQL(createTable(Filters.Sources.TABLE_NAME, Filters.Sources.COLUMNS, Filters.Sources.TYPES, true));
@ -234,11 +234,11 @@ public final class TwidereSQLiteOpenHelper extends SQLiteOpenHelper implements C
Activities.ByFriends.TYPES, true, null);
safeUpgrade(db, Drafts.TABLE_NAME, Drafts.COLUMNS, Drafts.TYPES, false, draftsAlias);
safeUpgrade(db, CachedUsers.TABLE_NAME, CachedUsers.COLUMNS, CachedUsers.TYPES, true, null,
createConflictReplaceConstraint(CachedUsers.USER_KEY, CachedUsers.USER_HOST));
createConflictReplaceConstraint(CachedUsers.USER_KEY));
safeUpgrade(db, CachedStatuses.TABLE_NAME, CachedStatuses.COLUMNS, CachedStatuses.TYPES, true, null);
safeUpgrade(db, CachedHashtags.TABLE_NAME, CachedHashtags.COLUMNS, CachedHashtags.TYPES, true, null);
safeUpgrade(db, CachedRelationships.TABLE_NAME, CachedRelationships.COLUMNS, CachedRelationships.TYPES, true, null,
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_ID));
createConflictReplaceConstraint(CachedRelationships.ACCOUNT_KEY, CachedRelationships.USER_KEY));
safeUpgrade(db, Filters.Users.TABLE_NAME, Filters.Users.COLUMNS, Filters.Users.TYPES,
oldVersion < 49, null);
safeUpgrade(db, Filters.Keywords.TABLE_NAME, Filters.Keywords.COLUMNS, Filters.Keywords.TYPES,