diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/provider/TwidereDataStore.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/provider/TwidereDataStore.java index 659038423..7cc4b5828 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/provider/TwidereDataStore.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/provider/TwidereDataStore.java @@ -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, diff --git a/twidere/src/androidTest/java/org/mariotaku/twidere/util/TwidereArrayUtilsTest.java b/twidere/src/androidTest/java/org/mariotaku/twidere/util/TwidereArrayUtilsTest.java index fcde70abc..9470063e5 100644 --- a/twidere/src/androidTest/java/org/mariotaku/twidere/util/TwidereArrayUtilsTest.java +++ b/twidere/src/androidTest/java/org/mariotaku/twidere/util/TwidereArrayUtilsTest.java @@ -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)); } } \ No newline at end of file diff --git a/twidere/src/main/java/org/mariotaku/twidere/Constants.java b/twidere/src/main/java/org/mariotaku/twidere/Constants.java index 3b09895ee..7f044a615 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/Constants.java +++ b/twidere/src/main/java/org/mariotaku/twidere/Constants.java @@ -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; diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/UserAutoCompleteAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/UserAutoCompleteAdapter.java index f15dd60a9..622f6d979 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/UserAutoCompleteAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/UserAutoCompleteAdapter.java @@ -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}; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorActivitiesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorActivitiesFragment.java index 1f08de007..cecefd05a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorActivitiesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorActivitiesFragment.java @@ -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; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorStatusesFragment.java index fda97fc68..3fb7d0c35 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorStatusesFragment.java @@ -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; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesConversationFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesConversationFragment.java index 6a6874946..04ebd25d4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesConversationFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesConversationFragment.java @@ -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; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableStatusesFragment.java index a8db0e501..c7031ec7d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableStatusesFragment.java @@ -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); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java index 678535a99..a9475474a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java @@ -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 data = adapter.getData(); + if (position < 0 || position >= data.size()) return; if (shouldRemoveUser(position, event)) { data.remove(position); adapter.notifyItemRemoved(position); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java index 377652697..d5f98c231 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java @@ -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); diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/BaseRefreshTaskParam.java b/twidere/src/main/java/org/mariotaku/twidere/model/BaseRefreshTaskParam.java index 576acdff1..ea27b0c5c 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/BaseRefreshTaskParam.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/BaseRefreshTaskParam.java @@ -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; + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/CachedRelationship.java b/twidere/src/main/java/org/mariotaku/twidere/model/CachedRelationship.java index 5d7de11fc..2761d3e3b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/CachedRelationship.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/CachedRelationship.java @@ -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) diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/RefreshTaskParam.java b/twidere/src/main/java/org/mariotaku/twidere/model/RefreshTaskParam.java index 2fd991fc0..e9fd2533b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/RefreshTaskParam.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/RefreshTaskParam.java @@ -28,4 +28,6 @@ public interface RefreshTaskParam { boolean isLoadingMore(); + boolean shouldAbort(); + } diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/SimpleRefreshTaskParam.java b/twidere/src/main/java/org/mariotaku/twidere/model/SimpleRefreshTaskParam.java index f26451f9b..4bfebbf87 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/SimpleRefreshTaskParam.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/SimpleRefreshTaskParam.java @@ -58,4 +58,9 @@ public abstract class SimpleRefreshTaskParam implements RefreshTaskParam { public boolean isLoadingMore() { return false; } + + @Override + public boolean shouldAbort() { + return false; + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/provider/TwidereDataProvider.java b/twidere/src/main/java/org/mariotaku/twidere/provider/TwidereDataProvider.java index cd9567023..d4e15ace4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/provider/TwidereDataProvider.java +++ b/twidere/src/main/java/org/mariotaku/twidere/provider/TwidereDataProvider.java @@ -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 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 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 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(), diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserBlockTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserBlockTask.java index d7f838688..53411653e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserBlockTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserBlockTask.java @@ -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); diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserMuteTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserMuteTask.java index 0253095d9..60938bf55 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserMuteTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/CreateUserMuteTask.java @@ -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); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserBlockTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserBlockTask.java index 49dad0936..e0b0ffff8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserBlockTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserBlockTask.java @@ -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); diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserMuteTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserMuteTask.java index f76d70468..387af5896 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserMuteTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/DestroyUserMuteTask.java @@ -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); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/twitter/GetActivitiesTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/twitter/GetActivitiesTask.java index 54347b4a7..b4ad89b73 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/twitter/GetActivitiesTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/twitter/GetActivitiesTask.java @@ -64,6 +64,7 @@ public abstract class GetActivitiesTask extends AbstractTask 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 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 withScore(final String[] projection, final String selection, - final String sortOrder, final UserKey accountKey, + public static Pair 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 pair = withRelationship(new Columns(columns), null, null, accountKey); + final Pair 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) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index 070c9c718..1a042d3d4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -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 list = new ArrayList<>(); + @NonNull + public static String[] getMatchedNicknameKeys(final String str, UserColorNameManager manager) { + if (isEmpty(str)) return new String[0]; + final List list = new ArrayList<>(); for (final Entry 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); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java b/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java index 63c5925c1..b21cdb83d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/content/TwidereSQLiteOpenHelper.java @@ -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,