mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-01 01:06:53 +01:00
parent
0fcf75b21e
commit
d12e331583
@ -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,
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -28,4 +28,6 @@ public interface RefreshTaskParam {
|
||||
|
||||
boolean isLoadingMore();
|
||||
|
||||
boolean shouldAbort();
|
||||
|
||||
}
|
||||
|
@ -58,4 +58,9 @@ public abstract class SimpleRefreshTaskParam implements RefreshTaskParam {
|
||||
public boolean isLoadingMore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldAbort() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -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(),
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user