migrating account

This commit is contained in:
Mariotaku Lee 2016-03-05 23:16:17 +08:00
parent c9864ec732
commit 638afe890c
81 changed files with 1135 additions and 860 deletions

Binary file not shown.

View File

@ -38,11 +38,11 @@ android {
dependencies {
apt 'com.bluelinelabs:logansquare-compiler:1.3.4'
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.2'
apt 'com.github.mariotaku.ObjectCursor:processor:0.9.5'
apt 'com.github.mariotaku.ObjectCursor:processor:0.9.6-SNAPSHOT'
compile 'com.android.support:support-annotations:23.2.0'
compile 'com.bluelinelabs:logansquare:1.3.4'
compile 'com.github.mariotaku.RestFu:library:0.9.24'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.5'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.6-SNAPSHOT'
compile fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@ -107,6 +107,7 @@ public interface IntentConstants {
String EXTRA_URI_ORIG = "uri_orig";
String EXTRA_MENTIONS = "mentions";
String EXTRA_ACCOUNT_ID = "account_id";
String EXTRA_ACCOUNT_HOST = "account_host";
String EXTRA_ACCOUNT_IDS = "account_ids";
String EXTRA_PAGE = "page";
String EXTRA_DATA = "data";

View File

@ -300,6 +300,8 @@ public interface SharedPreferenceConstants {
String KEY_API_LAST_CHANGE = "api_last_change";
@Preference(type = LONG, exportable = false)
String KEY_DEFAULT_ACCOUNT_ID = "default_account_id";
@Preference(type = STRING, exportable = false)
String KEY_DEFAULT_ACCOUNT_HOST = "default_account_host";
@Preference(type = BOOLEAN, exportable = true, defaultBoolean = true)
String KEY_RETRY_ON_NETWORK_ISSUE = "retry_on_network_issue";

View File

@ -38,6 +38,11 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
@JsonObject
public class ParcelableAccount implements Parcelable {
@ParcelableThisPlease
@JsonField(name = "id")
@CursorField(value = Accounts._ID, excludeWrite = true)
public long id;
@ParcelableThisPlease
@JsonField(name = "screen_name")
@CursorField(Accounts.SCREEN_NAME)

View File

@ -63,6 +63,10 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
@CursorField(value = Activities.ACCOUNT_ID)
public long account_id;
@ParcelableThisPlease
@JsonField(name = "account_host")
@CursorField(value = Activities.ACCOUNT_HOST)
public String account_host;
@ParcelableThisPlease
@JsonField(name = "timestamp")
@CursorField(value = Activities.TIMESTAMP)
public long timestamp;

View File

@ -64,6 +64,10 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
@CursorField(Statuses.ACCOUNT_ID)
public long account_id;
@ParcelableThisPlease
@JsonField(name = "account_host")
@CursorField(Statuses.ACCOUNT_HOST)
public String account_host;
@ParcelableThisPlease
@JsonField(name = "timestamp")
@CursorField(Statuses.STATUS_TIMESTAMP)
public long timestamp;

View File

@ -43,6 +43,9 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
@ParcelableThisPlease
@JsonField(name = "account_id")
public long account_id;
@ParcelableThisPlease
@JsonField(name = "account_host")
public String account_host;
@ParcelableThisPlease
public int account_color;

View File

@ -25,53 +25,53 @@ import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.api.twitter.model.UserList;
import org.mariotaku.twidere.util.TwitterContentUtils;
@ParcelablePlease
@JsonObject
public class ParcelableUserList implements Parcelable, Comparable<ParcelableUserList> {
public static final Parcelable.Creator<ParcelableUserList> CREATOR = new Parcelable.Creator<ParcelableUserList>() {
@Override
public ParcelableUserList createFromParcel(final Parcel in) {
return new ParcelableUserList(in);
}
@Override
public ParcelableUserList[] newArray(final int size) {
return new ParcelableUserList[size];
}
};
@ParcelableThisPlease
@JsonField(name = "members_count")
public long members_count;
@ParcelableThisPlease
@JsonField(name = "subscribers_count")
public long subscribers_count;
@ParcelableThisPlease
@JsonField(name = "account_id")
public long account_id;
@ParcelableThisPlease
@JsonField(name = "account_host")
public String account_host;
@ParcelableThisPlease
@JsonField(name = "id")
public long id;
@ParcelableThisPlease
@JsonField(name = "user_id")
public long user_id;
@ParcelableThisPlease
@JsonField(name = "position")
public long position;
@ParcelableThisPlease
@JsonField(name = "is_public")
public boolean is_public;
@ParcelableThisPlease
@JsonField(name = "is_following")
public boolean is_following;
@ParcelableThisPlease
@JsonField(name = "description")
public String description;
@ParcelableThisPlease
@JsonField(name = "name")
public String name;
@ParcelableThisPlease
@JsonField(name = "user_screen_name")
public String user_screen_name;
@ParcelableThisPlease
@JsonField(name = "user_name")
public String user_name;
@ParcelableThisPlease
@JsonField(name = "user_profile_image_url")
public String user_profile_image_url;
@ -94,42 +94,6 @@ public class ParcelableUserList implements Parcelable, Comparable<ParcelableUser
subscribers_count = in.readLong();
}
public ParcelableUserList(final UserList list, final long account_id) {
this(list, account_id, 0);
}
public ParcelableUserList(final UserList list, final long account_id, final long position) {
this(list, account_id, position, list.isFollowing());
}
public ParcelableUserList(final UserList list, final long account_id, final long position,
final boolean is_following) {
final User user = list.getUser();
this.position = position;
this.account_id = account_id;
id = list.getId();
is_public = UserList.Mode.PUBLIC.equals(list.getMode());
this.is_following = is_following;
name = list.getName();
description = list.getDescription();
user_id = user.getId();
user_name = user.getName();
user_screen_name = user.getScreenName();
user_profile_image_url = TwitterContentUtils.getProfileImageUrl(user);
members_count = list.getMemberCount();
subscribers_count = list.getSubscriberCount();
}
public static ParcelableUserList[] fromUserLists(UserList[] userLists, long accountId) {
if (userLists == null) return null;
int size = userLists.length;
final ParcelableUserList[] result = new ParcelableUserList[size];
for (int i = 0; i < size; i++) {
result[i] = new ParcelableUserList(userLists[i], accountId);
}
return result;
}
@Override
public int compareTo(@NonNull final ParcelableUserList another) {
final long diff = position - another.position;
@ -138,11 +102,6 @@ public class ParcelableUserList implements Parcelable, Comparable<ParcelableUser
return (int) diff;
}
@Override
public int describeContents() {
return 0;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) return true;
@ -165,27 +124,43 @@ public class ParcelableUserList implements Parcelable, Comparable<ParcelableUser
@Override
public String toString() {
return "ParcelableUserList{members_count=" + members_count + ", subscribers_count=" + subscribers_count
+ ", account_id=" + account_id + ", id=" + id + ", user_id=" + user_id + ", position=" + position
+ ", is_public=" + is_public + ", is_following=" + is_following + ", description=" + description
+ ", name=" + name + ", user_screen_name=" + user_screen_name + ", user_name=" + user_name
+ ", user_profile_image_url=" + user_profile_image_url + "}";
return "ParcelableUserList{" +
"members_count=" + members_count +
", subscribers_count=" + subscribers_count +
", account_id=" + account_id +
", account_host='" + account_host + '\'' +
", id=" + id +
", user_id=" + user_id +
", position=" + position +
", is_public=" + is_public +
", is_following=" + is_following +
", description='" + description + '\'' +
", name='" + name + '\'' +
", user_screen_name='" + user_screen_name + '\'' +
", user_name='" + user_name + '\'' +
", user_profile_image_url='" + user_profile_image_url + '\'' +
'}';
}
@Override
public void writeToParcel(final Parcel out, final int flags) {
out.writeLong(position);
out.writeLong(account_id);
out.writeLong(id);
out.writeInt(is_public ? 1 : 0);
out.writeInt(is_following ? 1 : 0);
out.writeString(name);
out.writeString(description);
out.writeLong(user_id);
out.writeString(user_name);
out.writeString(user_screen_name);
out.writeString(user_profile_image_url);
out.writeLong(members_count);
out.writeLong(subscribers_count);
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
ParcelableUserListParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<ParcelableUserList> CREATOR = new Creator<ParcelableUserList>() {
public ParcelableUserList createFromParcel(Parcel source) {
ParcelableUserList target = new ParcelableUserList();
ParcelableUserListParcelablePlease.readFromParcel(target, source);
return target;
}
public ParcelableUserList[] newArray(int size) {
return new ParcelableUserList[size];
}
};
}

View File

@ -71,7 +71,14 @@ public interface TwidereDataStore {
String INSERTED_DATE_TYPE = TYPE_INT;
}
interface Accounts extends BaseColumns {
interface AccountSupportColumns {
String ACCOUNT_ID = "account_id";
String ACCOUNT_HOST = "account_host";
}
interface Accounts extends BaseColumns, AccountSupportColumns {
String TABLE_NAME = "accounts";
String CONTENT_PATH = TABLE_NAME;
@ -85,11 +92,6 @@ public interface TwidereDataStore {
String NAME = "name";
/**
* Unique ID of the account<br>
* Type: INTEGER (long)
*/
String ACCOUNT_ID = "account_id";
/**
* Auth type of the account.</br> Type: INTEGER
@ -153,8 +155,6 @@ public interface TwidereDataStore {
String ACCOUNT_USER = "account_user";
String ACCOUNT_HOST = "account_host";
String[] COLUMNS_NO_CREDENTIALS = {_ID, NAME, SCREEN_NAME, ACCOUNT_ID, PROFILE_IMAGE_URL,
PROFILE_BANNER_URL, COLOR, IS_ACTIVATED, SORT_POSITION, ACCOUNT_TYPE, ACCOUNT_USER,
ACCOUNT_HOST};
@ -378,14 +378,13 @@ public interface TwidereDataStore {
String[] COLUMNS = {_ID, NAME, PATH};
}
interface DirectMessages extends BaseColumns, InsertedDateColumns {
interface DirectMessages extends BaseColumns, InsertedDateColumns, AccountSupportColumns {
String TABLE_NAME = "messages";
String CONTENT_PATH = TABLE_NAME;
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
String ACCOUNT_ID = "account_id";
String MESSAGE_ID = "message_id";
String MESSAGE_TIMESTAMP = "message_timestamp";
String SENDER_ID = "sender_id";
@ -523,7 +522,7 @@ public interface TwidereDataStore {
String[] COLUMNS = {_ID, HOST, ADDRESS};
}
interface SavedSearches extends BaseColumns {
interface SavedSearches extends BaseColumns, AccountSupportColumns {
String TABLE_NAME = "saved_searches";
@ -531,16 +530,14 @@ public interface TwidereDataStore {
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
String ACCOUNT_ID = "account_id";
String SEARCH_ID = "search_id";
String QUERY = "query";
String NAME = "name";
String CREATED_AT = "created_at";
String[] COLUMNS = {_ID, ACCOUNT_ID, SEARCH_ID, CREATED_AT,
QUERY, NAME};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_TEXT, TYPE_TEXT};
String[] COLUMNS = {_ID, ACCOUNT_ID, ACCOUNT_HOST, SEARCH_ID, CREATED_AT, QUERY, NAME};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_TEXT,
TYPE_TEXT};
String DEFAULT_SORT_ORDER = CREATED_AT + " DESC";
}
@ -721,17 +718,12 @@ public interface TwidereDataStore {
String[] COLUMNS = {_ID, KEY, VALUE, TYPE};
}
interface Statuses extends BaseColumns, InsertedDateColumns {
interface Statuses extends BaseColumns, InsertedDateColumns, AccountSupportColumns {
String TABLE_NAME = "statuses";
String CONTENT_PATH = TABLE_NAME;
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
/**
* Account ID of the status.<br>
* Type: TEXT
*/
String ACCOUNT_ID = "account_id";
/**
* Status content, in HTML. Please note, this is not actually original
@ -880,8 +872,8 @@ public interface TwidereDataStore {
String EXTRAS = "extras";
String[] COLUMNS = {_ID, ACCOUNT_ID, STATUS_ID, USER_ID,
STATUS_TIMESTAMP, TEXT_HTML, TEXT_PLAIN, TEXT_UNESCAPED, USER_NAME, USER_SCREEN_NAME,
String[] COLUMNS = {_ID, ACCOUNT_ID, ACCOUNT_HOST, STATUS_ID, USER_ID, STATUS_TIMESTAMP,
TEXT_HTML, TEXT_PLAIN, TEXT_UNESCAPED, USER_NAME, USER_SCREEN_NAME,
USER_PROFILE_IMAGE_URL, IN_REPLY_TO_STATUS_ID, IN_REPLY_TO_USER_ID, IN_REPLY_TO_USER_NAME,
IN_REPLY_TO_USER_SCREEN_NAME, SOURCE, LOCATION, RETWEET_COUNT, FAVORITE_COUNT, REPLY_COUNT,
RETWEET_ID, RETWEET_TIMESTAMP, RETWEETED_BY_USER_ID, RETWEETED_BY_USER_NAME,
@ -894,8 +886,8 @@ public interface TwidereDataStore {
PLACE_FULL_NAME, LANG, RETWEETED, QUOTED_LOCATION, QUOTED_PLACE_FULL_NAME, INSERTED_DATE,
EXTRAS};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_TEXT, TYPE_INT,
@ -907,9 +899,8 @@ public interface TwidereDataStore {
}
interface Activities extends BaseColumns, InsertedDateColumns {
interface Activities extends BaseColumns, InsertedDateColumns, AccountSupportColumns {
String ACCOUNT_ID = "account_id";
String ACTION = "action";
String TIMESTAMP = "timestamp";
String STATUS_ID = "status_id";
@ -936,13 +927,13 @@ public interface TwidereDataStore {
String TARGET_OBJECT_USER_LISTS = "target_object_user_lists";
String TARGET_OBJECT_USERS = "target_object_users";
String[] COLUMNS = {_ID, ACCOUNT_ID, ACTION, TIMESTAMP, STATUS_ID, STATUS_USER_ID,
String[] COLUMNS = {_ID, ACCOUNT_ID, ACCOUNT_HOST, ACTION, TIMESTAMP, STATUS_ID, STATUS_USER_ID,
STATUS_RETWEETED_BY_USER_ID, STATUS_QUOTED_USER_ID, STATUS_SOURCE, STATUS_QUOTE_SOURCE,
STATUS_TEXT_PLAIN, STATUS_QUOTE_TEXT_PLAIN, STATUS_TEXT_HTML, STATUS_QUOTE_TEXT_HTML,
IS_GAP, MIN_POSITION, MAX_POSITION, SOURCES, SOURCE_IDS, TARGET_STATUSES, TARGET_USERS,
TARGET_USER_LISTS, TARGET_OBJECT_STATUSES, TARGET_OBJECT_USER_LISTS, TARGET_OBJECT_USERS,
STATUS_RETWEET_ID, STATUS_USER_FOLLOWING, INSERTED_DATE};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT,
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_BOOLEAN, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN, INSERTED_DATE_TYPE};
@ -993,14 +984,13 @@ public interface TwidereDataStore {
String DEFAULT_SORT_ORDER = POSITION + " ASC";
}
interface CachedRelationships extends BaseColumns {
interface CachedRelationships extends BaseColumns, AccountSupportColumns {
String TABLE_NAME = "cached_relationships";
String CONTENT_PATH = TABLE_NAME;
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
String ACCOUNT_ID = "account_id";
String USER_ID = "user_id";
@ -1016,14 +1006,15 @@ public interface TwidereDataStore {
String RETWEET_ENABLED = "retweet_enabled";
String[] COLUMNS = {_ID, ACCOUNT_ID, USER_ID, FOLLOWING, FOLLOWED_BY, BLOCKING,
String[] COLUMNS = {_ID, ACCOUNT_ID, ACCOUNT_HOST, USER_ID, FOLLOWING, FOLLOWED_BY, BLOCKING,
BLOCKED_BY, MUTING, RETWEET_ENABLED};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_INT, TYPE_BOOLEAN_DEFAULT_FALSE,
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_INT, TYPE_TEXT, TYPE_INT, TYPE_BOOLEAN_DEFAULT_FALSE,
TYPE_BOOLEAN_DEFAULT_FALSE, TYPE_BOOLEAN_DEFAULT_FALSE, TYPE_BOOLEAN_DEFAULT_FALSE,
TYPE_BOOLEAN_DEFAULT_FALSE, TYPE_BOOLEAN_DEFAULT_TRUE};
}
interface UnreadCounts extends BaseColumns {
String CONTENT_PATH = "unread_counts";

View File

@ -25,15 +25,21 @@ android {
versionName "3.0.6.5"
multiDexEnabled true
generatedDensities = []
buildConfigField 'boolean', 'LEAK_CANARY_ENABLED', 'Boolean.parseBoolean("false")'
buildConfigField 'boolean', 'SHOW_CUSTOM_TOKEN_DIALOG', 'Boolean.parseBoolean("false")'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
aaptOptions {
additionalParameters "--no-version-vectors"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
productFlavors {
google {}
fdroid {}
@ -72,7 +78,7 @@ dependencies {
androidTestApt 'com.bluelinelabs:logansquare-compiler:1.3.4'
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.2'
apt 'com.google.dagger:dagger-compiler:2.0.2'
apt "com.github.mariotaku.ObjectCursor:processor:0.9.5"
apt "com.github.mariotaku.ObjectCursor:processor:0.9.6-SNAPSHOT"
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:support-v13:23.2.0'
@ -111,7 +117,7 @@ dependencies {
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.12'
compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view:0.9.12'
compile 'com.github.mariotaku.SQLiteQB:library:0.9.5'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.5'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.6-SNAPSHOT'
compile project(':twidere.component.common')
compile project(':twidere.component.nyan')

View File

@ -32,6 +32,7 @@ import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.AccountPreferences;
import org.mariotaku.twidere.util.DataStoreUtils;
@ -97,7 +98,7 @@ public class SessionEvent extends BaseEvent implements Parcelable {
public void dumpPreferences(Context context) {
final HashMap<String, String> preferences = new HashMap<>();
for (AccountPreferences pref : AccountPreferences.getAccountPreferences(context, DataStoreUtils.getAccountIds(context))) {
final long accountId = pref.getAccountId();
final AccountId accountId = pref.getAccountId();
preferences.put("notification_" + accountId + "_home", String.valueOf(pref.isHomeTimelineNotificationEnabled()));
preferences.put("notification_" + accountId + "_interactions", String.valueOf(pref.isInteractionsNotificationEnabled()));
}

View File

@ -5,13 +5,13 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringDef;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableUser;
/**
@ -38,7 +38,7 @@ public class UserEvent extends BaseEvent implements Parcelable {
long friendCount;
@ParcelableThisPlease
@JsonField(name = "referral")
@Referral
@UserFragment.Referral
@Nullable
String referral;
public static final Creator<UserEvent> CREATOR = new Creator<UserEvent>() {
@ -53,7 +53,7 @@ public class UserEvent extends BaseEvent implements Parcelable {
}
};
public static UserEvent create(Context context, @Referral @Nullable String referral) {
public static UserEvent create(Context context, @UserFragment.Referral @Nullable String referral) {
UserEvent event = new UserEvent();
event.markStart(context);
event.referral = referral;
@ -96,15 +96,4 @@ public class UserEvent extends BaseEvent implements Parcelable {
"} " + super.toString();
}
@StringDef({Referral.SEARCH_RESULT, Referral.USER_MENTION, Referral.TWEET,
Referral.TIMELINE_TWEET, Referral.DIRECT, Referral.EXTERNAL})
public @interface Referral {
String SEARCH_RESULT = "search_result";
String USER_MENTION = "user_mention";
String TWEET = "tweet";
String TIMELINE_TWEET = "timeline_tweet";
String DIRECT = "direct";
String EXTERNAL = "external";
}
}

View File

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

View File

@ -95,6 +95,7 @@ import com.github.johnpersano.supertoasts.SuperToast.OnDismissListener;
import com.nostra13.universalimageloader.utils.IoUtils;
import com.twitter.Extractor;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.mariotaku.restfu.RestFuUtils;
import org.mariotaku.twidere.BuildConfig;
@ -103,6 +104,7 @@ import org.mariotaku.twidere.adapter.ArrayRecyclerAdapter;
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter;
import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment;
import org.mariotaku.twidere.fragment.support.SupportProgressDialogFragment;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ConsumerKeyType;
import org.mariotaku.twidere.model.Draft;
import org.mariotaku.twidere.model.DraftValuesCreator;
@ -115,6 +117,7 @@ import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.draft.UpdateStatusActionExtra;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.preference.ServicePickerPreference;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.service.BackgroundOperationService;
@ -1130,7 +1133,11 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
private void notifyAccountSelectionChanged() {
final ParcelableCredentials[] accounts = mAccountsAdapter.getSelectedAccounts();
setSelectedAccounts(accounts);
mEditText.setAccountId(accounts.length > 0 ? accounts[0].account_id : Utils.getDefaultAccountId(this));
if (ArrayUtils.isEmpty(accounts)) {
mEditText.setAccountId(Utils.getDefaultAccountId(this));
} else {
mEditText.setAccountId(new AccountId(accounts[0]));
}
mSendTextCountView.setMaxLength(TwidereValidator.getTextLimit(accounts));
setMenu();
// mAccountActionProvider.setSelectedAccounts(mAccountsAdapter.getSelectedAccounts());
@ -1331,7 +1338,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
} else {
action = getDraftAction(getIntent().getAction());
}
update.accounts = DataStoreUtils.getAccounts(this, accountIds);
update.accounts = ParcelableAccountUtils.getAccounts(this, accountIds);
update.text = text;
update.location = statusLocation;
update.media = getMedia();

View File

@ -55,6 +55,7 @@ import android.widget.TextView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.AccountsSpinnerAdapter;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory;
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
@ -170,12 +171,13 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
switch (mUsersSearchAdapter.getItemViewType(position)) {
case SuggestionsAdapter.VIEW_TYPE_USER_SUGGESTION_ITEM: {
IntentUtils.openUserProfile(this, getAccountId(), item.extra_id, item.summary, null,
true);
true, UserFragment.Referral.DIRECT);
finish();
break;
}
case SuggestionsAdapter.VIEW_TYPE_USER_SCREEN_NAME: {
IntentUtils.openUserProfile(this, getAccountId(), -1, item.title, null, true);
IntentUtils.openUserProfile(this, getAccountId(), -1, item.title, null, true,
UserFragment.Referral.DIRECT);
finish();
break;
}

View File

@ -289,7 +289,7 @@ public class UserListSelectorActivity extends BaseSupportDialogActivity implemen
@Override
protected SingleResponse<List<ParcelableUserList>> doInBackground(final Object... params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, accountHost, false);
if (twitter == null) return SingleResponse.getInstance();
try {
final ResponseList<UserList> lists = twitter.getUserLists(mScreenName, true);
@ -351,7 +351,7 @@ public class UserListSelectorActivity extends BaseSupportDialogActivity implemen
@Override
protected SingleResponse<List<ParcelableUser>> doInBackground(final Object... params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, accountHost, false);
if (twitter == null) return SingleResponse.getInstance();
try {
final Paging paging = new Paging();

View File

@ -35,6 +35,7 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.iface.IActivitiesAdapter;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.fragment.support.CursorActivitiesFragment;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -438,7 +439,7 @@ public abstract class AbsActivitiesAdapter<Data> extends LoadMoreSupportAdapter<
final ParcelableStatus status = ParcelableActivity.getActivityStatus(activity);
assert status != null;
IntentUtils.openUserProfile(context, status.account_id, status.user_id,
status.user_screen_name, null, true);
status.user_screen_name, null, true, UserFragment.Referral.TIMELINE_STATUS);
}
@Override

View File

@ -32,6 +32,7 @@ import android.widget.TextView;
import org.apache.commons.lang3.StringUtils;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.provider.TwidereDataStore.Suggestions;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
@ -57,7 +58,7 @@ public class ComposeAutoCompleteAdapter extends SimpleCursorAdapter implements C
private final boolean mDisplayProfileImage;
private int mTypeIdx, mIconIdx, mTitleIdx, mSummaryIdx, mExtraIdIdx, mValueIdx;
private long mAccountId;
private AccountId mAccountId;
private char mToken;
public ComposeAutoCompleteAdapter(final Context context) {
@ -142,13 +143,13 @@ public class ComposeAutoCompleteAdapter extends SimpleCursorAdapter implements C
return null;
}
}
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(mAccountId));
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(mAccountId.getId()));
return mContext.getContentResolver().query(builder.build(), Suggestions.AutoComplete.COLUMNS,
null, null, null);
}
public void setAccountId(long accountId) {
public void setAccountId(AccountId accountId) {
mAccountId = accountId;
}

View File

@ -155,7 +155,7 @@ public class NetworkDiagnosticsFragment extends BaseFragment {
for (long accountId : DataStoreUtils.getAccountIds(mContext)) {
final ParcelableCredentials credentials = DataStoreUtils.getCredentials(mContext, accountId);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, accountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, accountId, accountHost, false);
if (credentials == null || twitter == null) continue;
publishProgress(new LogText("Testing connection for account " + accountId));
publishProgress(LogText.LINEBREAK);

View File

@ -47,6 +47,7 @@ import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosi
import org.mariotaku.twidere.annotation.ReadPositionTag;
import org.mariotaku.twidere.fragment.support.AbsStatusesFragment.DefaultOnLikedListener;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -187,7 +188,8 @@ public abstract class AbsActivitiesFragment<Data> extends AbsContentListRecycler
case ACTION_STATUS_FAVORITE: {
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(activity.account_id, status.id);
twitter.destroyFavoriteAsync(new AccountId(activity.account_id,
activity.account_host), status.id);
} else {
final IStatusViewHolder holder = (IStatusViewHolder)
recyclerView.findViewHolderForLayoutPosition(position);
@ -378,7 +380,8 @@ public abstract class AbsActivitiesFragment<Data> extends AbsContentListRecycler
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (twitter == null) return;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
twitter.destroyFavoriteAsync(new AccountId(status.account_id,
status.account_host), status.id);
} else {
holder.playLikeAnimation(new DefaultOnLikedListener(twitter, status));
}
@ -501,7 +504,7 @@ public abstract class AbsActivitiesFragment<Data> extends AbsContentListRecycler
return new StatusesBusCallback();
}
protected abstract long[] getAccountIds();
protected abstract AccountId[] getAccountIds();
protected Data getAdapterData() {
final AbsActivitiesAdapter<Data> adapter = getAdapter();

View File

@ -47,6 +47,7 @@ import org.mariotaku.twidere.adapter.iface.IStatusesAdapter.StatusAdapterListene
import org.mariotaku.twidere.annotation.ReadPositionTag;
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
@ -184,7 +185,8 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListRecyclerVi
case ACTION_STATUS_FAVORITE: {
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
twitter.destroyFavoriteAsync(new AccountId(status.account_id,
status.account_host), status.id);
} else {
final IStatusViewHolder holder = (IStatusViewHolder)
recyclerView.findViewHolderForLayoutPosition(position);
@ -367,7 +369,8 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListRecyclerVi
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (twitter == null) return;
if (status.is_favorite) {
twitter.destroyFavoriteAsync(status.account_id, status.id);
twitter.destroyFavoriteAsync(new AccountId(status.account_id,
status.account_host), status.id);
} else {
holder.playLikeAnimation(new DefaultOnLikedListener(twitter, status));
}
@ -401,7 +404,7 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListRecyclerVi
public void onUserProfileClick(IStatusViewHolder holder, ParcelableStatus status, int position) {
final FragmentActivity activity = getActivity();
IntentUtils.openUserProfile(activity, status.account_id, status.user_id,
status.user_screen_name, null, true);
status.user_screen_name, null, true, UserFragment.Referral.TIMELINE_STATUS);
}
@Override
@ -588,8 +591,10 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListRecyclerVi
@Override
public boolean onLiked() {
if (mStatus.is_favorite) return false;
mTwitter.createFavoriteAsync(mStatus.account_id, mStatus.id);
final ParcelableStatus status = mStatus;
if (status.is_favorite) return false;
mTwitter.createFavoriteAsync(new AccountId(status.account_id, status.account_host),
status.id);
return true;
}
}

View File

@ -31,8 +31,8 @@ import android.support.v7.widget.RecyclerView;
import android.view.KeyEvent;
import org.mariotaku.twidere.adapter.AbsUsersAdapter;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter.UserAdapterListener;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
import org.mariotaku.twidere.adapter.iface.IUsersAdapter.UserAdapterListener;
import org.mariotaku.twidere.loader.iface.IExtendedLoader;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.util.IntentUtils;
@ -112,7 +112,13 @@ abstract class AbsUsersFragment<Data> extends AbsContentListRecyclerViewFragment
public void onUserClick(UserViewHolder holder, int position) {
final ParcelableUser user = getAdapter().getUser(position);
final FragmentActivity activity = getActivity();
IntentUtils.openUserProfile(activity, user.account_id, user.id, user.screen_name, null, true);
IntentUtils.openUserProfile(activity, user.account_id, user.id, user.screen_name, null,
true, getUserReferral());
}
@UserFragment.Referral
protected String getUserReferral() {
return null;
}

View File

@ -89,6 +89,7 @@ import org.mariotaku.twidere.annotation.CustomTabType;
import org.mariotaku.twidere.menu.support.AccountToggleProvider;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.SupportTabSpec;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.DataStoreUtils;
@ -247,7 +248,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo
if (account == null) return;
final FragmentActivity activity = getActivity();
IntentUtils.openUserProfile(activity, account.account_id, account.account_id,
account.screen_name, null, true);
account.screen_name, null, true, UserFragment.Referral.SELF_PROFILE);
break;
}
}
@ -267,7 +268,7 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo
if (cursor == null) return;
final Menu menu = mAccountsToggleMenu.getMenu();
mAccountActionProvider = (AccountToggleProvider) MenuItemCompat.getActionProvider(menu.findItem(R.id.select_account));
final ParcelableAccount[] accounts = DataStoreUtils.getAccounts(cursor);
final ParcelableAccount[] accounts = ParcelableAccountUtils.getAccounts(cursor);
if (accounts.length > 0) {
mNoAccountContainer.setVisibility(View.GONE);
mAccountProfileContainer.setVisibility(View.VISIBLE);

View File

@ -149,7 +149,7 @@ public class AccountsManagerFragment extends BaseSupportFragment implements Load
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final ParcelableAccount account = mAdapter.getAccount(position);
IntentUtils.openUserProfile(getActivity(), account.account_id, account.account_id, account.screen_name,
null, true);
null, true, UserFragment.Referral.SELF_PROFILE);
}
@Override

View File

@ -28,6 +28,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v7.app.AlertDialog;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
@ -43,7 +44,8 @@ public class DestroyStatusDialogFragment extends BaseSupportDialogFragment imple
final ParcelableStatus status = getStatus();
final AsyncTwitterWrapper twitter = mTwitterWrapper;
if (status == null || twitter == null) return;
twitter.destroyStatusAsync(status.account_id, status.id);
twitter.destroyStatusAsync(new AccountId(status.account_id, status.account_host),
status.id);
break;
default:
break;

View File

@ -198,7 +198,7 @@ public class DirectMessagesFragment extends AbsContentListRecyclerViewFragment<M
@Override
public void onUserClick(int position, DirectMessageEntry entry) {
IntentUtils.openUserProfile(getActivity(), entry.account_id, entry.conversation_id,
entry.screen_name, null, true);
entry.screen_name, null, true, null);
}
@Subscribe

View File

@ -43,10 +43,12 @@ import android.widget.EditText;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.DummyStatusHolderAdapter;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.Draft;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.DataStoreUtils;
@ -241,16 +243,18 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
final String commentText = editComment.getText() + " " + statusLink;
ParcelableStatusUpdate update = new ParcelableStatusUpdate();
update.text = commentText;
update.accounts = DataStoreUtils.getAccounts(getContext(), status.account_id);
update.accounts = ParcelableAccountUtils.getAccounts(getContext(), status.account_id);
if (linkToQuotedStatus.isChecked()) {
update.in_reply_to_status = status;
}
update.is_possibly_sensitive = status.is_possibly_sensitive;
BackgroundOperationService.updateStatusesAsync(getContext(), Draft.Action.QUOTE, update);
} else if (isMyRetweet(status)) {
twitter.cancelRetweetAsync(status.account_id, status.id, status.my_retweet_id);
twitter.cancelRetweetAsync(status.account_id, status.account_host, status.id,
status.my_retweet_id);
} else {
twitter.retweetStatusAsync(status.account_id, status.id);
twitter.retweetStatusAsync(new AccountId(status.account_id, status.account_host),
status.id);
}
}

View File

@ -82,4 +82,8 @@ public class SearchUsersFragment extends ParcelableUsersFragment {
super.onDestroyView();
}
@Override
protected String getUserReferral() {
return UserFragment.Referral.SEARCH_RESULT;
}
}

View File

@ -288,8 +288,9 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
@Override
public Loader<StatusActivity> onCreateLoader(int id, Bundle args) {
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
final String accountHost = args.getString(EXTRA_ACCOUNT_HOST);
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
return new StatusActivitySummaryLoader(getActivity(), accountId, statusId);
return new StatusActivitySummaryLoader(getActivity(), accountId, accountHost, statusId);
}
@Override
@ -460,7 +461,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
public void onUserProfileClick(IStatusViewHolder holder, ParcelableStatus status, int position) {
final FragmentActivity activity = getActivity();
IntentUtils.openUserProfile(activity, status.account_id, status.user_id,
status.user_screen_name, null, true);
status.user_screen_name, null, true, UserFragment.Referral.TIMELINE_STATUS);
}
@Override
@ -815,7 +816,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
}
private void onUserClick(ParcelableUser user) {
IntentUtils.openUserProfile(getContext(), user, null, true);
IntentUtils.openUserProfile(getContext(), user, null, true,
UserFragment.Referral.TIMELINE_STATUS);
}
public static final class LoadSensitiveImageConfirmDialogFragment extends BaseSupportDialogFragment implements
@ -863,7 +865,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
protected SingleResponse<TranslationResult> doInBackground(ParcelableStatus... params) {
final ParcelableStatus status = params[0];
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, status.account_id,
true);
accountHost, true);
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE);
if (twitter == null) return SingleResponse.getInstance();
@ -1195,13 +1197,14 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
case R.id.profile_container: {
final FragmentActivity activity = fragment.getActivity();
IntentUtils.openUserProfile(activity, status.account_id, status.user_id,
status.user_screen_name, null, true);
status.user_screen_name, null, true, UserFragment.Referral.STATUS);
break;
}
case R.id.retweeted_by: {
if (status.retweet_id > 0) {
IntentUtils.openUserProfile(adapter.getContext(), status.account_id, status.retweeted_by_user_id,
status.retweeted_by_user_screen_name, null, true);
IntentUtils.openUserProfile(adapter.getContext(), status.account_id,
status.retweeted_by_user_id, status.retweeted_by_user_screen_name,
null, true, UserFragment.Referral.STATUS);
}
break;
}
@ -1212,8 +1215,9 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
break;
}
case R.id.quoted_name_container: {
IntentUtils.openUserProfile(adapter.getContext(), status.account_id, status.quoted_user_id,
status.quoted_user_screen_name, null, true);
IntentUtils.openUserProfile(adapter.getContext(), status.account_id,
status.quoted_user_id, status.quoted_user_screen_name, null, true,
UserFragment.Referral.STATUS);
break;
}
case R.id.quote_original_link: {
@ -2413,18 +2417,21 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
public static class StatusActivitySummaryLoader extends AsyncTaskLoader<StatusActivity> {
private final long mAccountId;
private final String mAccountHost;
private final long mStatusId;
public StatusActivitySummaryLoader(Context context, long accountId, long statusId) {
public StatusActivitySummaryLoader(Context context, long accountId, String accountHost,
long statusId) {
super(context);
mAccountId = accountId;
mAccountHost = accountHost;
mStatusId = statusId;
}
@Override
public StatusActivity loadInBackground() {
final Context context = getContext();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountId, accountHost, false);
final Paging paging = new Paging();
paging.setCount(10);
final StatusActivity activitySummary = new StatusActivity(mStatusId);
@ -2458,7 +2465,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
Expression.equals(Activities.STATUS_RETWEET_ID, mStatusId)
);
final ParcelableStatus pStatus = ParcelableStatusUtils.fromStatus(status, mAccountId, false);
final ParcelableStatus pStatus = ParcelableStatusUtils.fromStatus(status, mAccountId,
mAccountHost, false);
cr.insert(CachedStatuses.CONTENT_URI, ParcelableStatusValuesCreator.create(pStatus));
final Cursor activityCursor = cr.query(Activities.AboutMe.CONTENT_URI,

View File

@ -43,6 +43,7 @@ import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringDef;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
@ -697,8 +698,10 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
if (resultCode == Activity.RESULT_OK) {
if (data == null || !data.hasExtra(EXTRA_ID)) return;
final long accountId = data.getLongExtra(EXTRA_ID, -1);
@Referral
final String referral = getArguments().getString(EXTRA_REFERRAL);
IntentUtils.openUserProfile(getActivity(), accountId, user.id, user.screen_name,
null, true);
null, true, referral);
}
break;
}
@ -840,7 +843,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
super.onStart();
mBus.register(this);
@UserEvent.Referral
@Referral
final String referral = getArguments().getString(EXTRA_REFERRAL);
final Context context = getContext();
if (mUserEvent == null) {
@ -1349,7 +1352,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
if (user == null) return;
switch (type) {
case TwidereLinkify.LINK_TYPE_MENTION: {
IntentUtils.openUserProfile(getActivity(), user.account_id, -1, link, null, true);
IntentUtils.openUserProfile(getActivity(), user.account_id, -1, link, null,
true, Referral.USER_MENTION);
break;
}
case TwidereLinkify.LINK_TYPE_HASHTAG: {
@ -1670,6 +1674,19 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
}
}
@StringDef({Referral.SEARCH_RESULT, Referral.USER_MENTION, Referral.STATUS,
Referral.TIMELINE_STATUS, Referral.DIRECT, Referral.EXTERNAL, Referral.SELF_PROFILE})
public @interface Referral {
String SEARCH_RESULT = "search_result";
String USER_MENTION = "user_mention";
String STATUS = "status";
String TIMELINE_STATUS = "timeline_status";
String DIRECT = "direct";
String EXTERNAL = "external";
String SELF_PROFILE = "self_profile";
}
private static class ActionBarDrawable extends LayerDrawable {
private final Drawable mShadowDrawable;
@ -1752,7 +1769,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
final boolean isFiltering = DataStoreUtils.isFilteringUser(context, userId);
if (accountId == userId)
return SingleResponse.getInstance();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, accountHost, false);
if (twitter == null) return SingleResponse.getInstance();
try {
final Relationship relationship = twitter.showFriendship(userId);

View File

@ -68,9 +68,11 @@ import org.mariotaku.twidere.api.twitter.model.UserListUpdate;
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
import org.mariotaku.twidere.graphic.EmptyDrawable;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.util.ParcelableUserListUtils;
import org.mariotaku.twidere.text.validator.UserListNameValidator;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.IntentUtils;
@ -348,9 +350,10 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
break;
}
case R.id.profile_image: {
if (mUserList == null) return;
IntentUtils.openUserProfile(getActivity(), mUserList.account_id,
mUserList.user_id, mUserList.user_screen_name, null, true);
final ParcelableUserList userList = mUserList;
if (userList == null) return;
IntentUtils.openUserProfile(getActivity(), userList.account_id, userList.user_id,
userList.user_screen_name, null, true, null);
break;
}
}
@ -360,12 +363,12 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
@Override
public Loader<SingleResponse<ParcelableUserList>> onCreateLoader(final int id, final Bundle args) {
setProgressBarIndeterminateVisibility(true);
final long accountId = args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long userId = args != null ? args.getLong(EXTRA_USER_ID, -1) : -1;
final long listId = args != null ? args.getLong(EXTRA_LIST_ID, -1) : -1;
final String listName = args != null ? args.getString(EXTRA_LIST_NAME) : null;
final String screenName = args != null ? args.getString(EXTRA_SCREEN_NAME) : null;
final boolean omitIntentExtra = args == null || args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
final AccountId accountId = args.getParcelable(EXTRA_ACCOUNT_ID);
final long userId = args.getLong(EXTRA_USER_ID, -1);
final long listId = args.getLong(EXTRA_LIST_ID, -1);
final String listName = args.getString(EXTRA_LIST_NAME);
final String screenName = args.getString(EXTRA_SCREEN_NAME);
final boolean omitIntentExtra = args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true);
return new ParcelableUserListLoader(getActivity(), omitIntentExtra, getArguments(), accountId, listId,
listName, userId, screenName);
}
@ -434,13 +437,12 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
DialogInterface.OnClickListener {
private String mName, mDescription;
private long mAccountId;
private AccountId mAccountId;
private long mListId;
private boolean mIsPublic;
@Override
public void onClick(final DialogInterface dialog, final int which) {
if (mAccountId <= 0) return;
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {
final AlertDialog alertDialog = (AlertDialog) dialog;
@ -466,7 +468,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState;
mAccountId = bundle != null ? bundle.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
mAccountId = bundle != null ? bundle.<AccountId>getParcelable(EXTRA_ACCOUNT_ID) : null;
mListId = bundle != null ? bundle.getLong(EXTRA_LIST_ID, -1) : -1;
mName = bundle != null ? bundle.getString(EXTRA_LIST_NAME) : null;
mDescription = bundle != null ? bundle.getString(EXTRA_DESCRIPTION) : null;
@ -502,7 +504,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
@Override
public void onSaveInstanceState(final Bundle outState) {
outState.putLong(EXTRA_ACCOUNT_ID, mAccountId);
outState.putParcelable(EXTRA_ACCOUNT_ID, mAccountId);
outState.putLong(EXTRA_LIST_ID, mListId);
outState.putString(EXTRA_LIST_NAME, mName);
outState.putString(EXTRA_DESCRIPTION, mDescription);
@ -516,12 +518,13 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
private final boolean mOmitIntentExtra;
private final Bundle mExtras;
private final long mAccountId, mUserId;
private final AccountId mAccountId;
private final long mUserId;
private final long mListId;
private final String mScreenName, mListName;
private ParcelableUserListLoader(final Context context, final boolean omitIntentExtra, final Bundle extras,
final long accountId, final long listId, final String listName, final long userId,
final AccountId accountId, final long listId, final String listName, final long userId,
final String screenName) {
super(context);
mOmitIntentExtra = omitIntentExtra;
@ -539,7 +542,8 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
final ParcelableUserList cache = mExtras.getParcelable(EXTRA_USER_LIST);
if (cache != null) return SingleResponse.getInstance(cache);
}
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId,
true);
if (twitter == null) return SingleResponse.getInstance();
try {
final UserList list;
@ -551,7 +555,7 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList
list = twitter.showUserList(mListName, mScreenName);
} else
return SingleResponse.getInstance();
return SingleResponse.getInstance(new ParcelableUserList(list, mAccountId));
return SingleResponse.getInstance(ParcelableUserListUtils.from(list, mAccountId));
} catch (final TwitterException e) {
return SingleResponse.getInstance(e);
}

View File

@ -124,7 +124,7 @@ public class UserListMembersFragment extends CursorSupportUsersListFragment {
@Override
@NonNull
protected SingleResponse<ParcelableUserList> doInBackground(final Object... params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getActivity(), accountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getActivity(), accountId, accountHost, true);
if (twitter == null) return SingleResponse.getInstance();
try {
final UserList list;

View File

@ -448,7 +448,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
@Override
protected SingleResponse<ParcelableUser> doInBackground(final Object... params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, mAccountId, accountHost, true);
try {
User user = null;
if (isProfileChanged()) {
@ -547,7 +547,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
public UpdateProfileBannerImageTaskInternal(final Context context, final AsyncTaskManager manager,
final long account_id, final Uri image_uri, final boolean delete_image) {
super(context, manager, account_id, image_uri, delete_image);
super(context, account_id, accountHost, image_uri, delete_image);
}
@Override
@ -569,7 +569,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
public UpdateProfileImageTaskInternal(final Context context, final AsyncTaskManager manager,
final long account_id, final Uri image_uri, final boolean delete_image) {
super(context, account_id, image_uri, delete_image);
super(context, account_id, accountHost, image_uri, delete_image);
}
@Override

View File

@ -175,7 +175,7 @@ public class CardPollFragment extends BaseSupportFragment implements
@Override
public ParcelableCardEntity doLongOperation(CardDataMap cardDataMap) {
final TwitterCaps caps = TwitterAPIFactory.getTwitterInstance(getContext(),
card.account_id, true, true, TwitterCaps.class);
card.account_id, accountHost, true, true, TwitterCaps.class);
if (caps == null) return null;
try {
final CardEntity cardEntity = caps.sendPassThrough(cardDataMap).getCard();
@ -339,7 +339,7 @@ public class CardPollFragment extends BaseSupportFragment implements
@Override
public ParcelableCardEntity loadInBackground() {
final TwitterCaps caps = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId,
true, true, TwitterCaps.class);
accountHost, true, true, TwitterCaps.class);
if (caps == null) return null;
try {
final CardDataMap params = new CardDataMap();

View File

@ -76,7 +76,7 @@ public abstract class BaseUserListsLoader extends AsyncTaskLoader<List<Parcelabl
@Override
public List<ParcelableUserList> loadInBackground() {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, accountHost, true);
List<UserList> listLoaded = null;
try {
listLoaded = getUserLists(twitter);

View File

@ -64,7 +64,7 @@ public class ParcelableStatusLoader extends AsyncTaskLoader<SingleResponse<Parce
}
}
try {
final ParcelableStatus status = findStatus(getContext(), mAccountId, mStatusId);
final ParcelableStatus status = findStatus(getContext(), mAccountId, accountHost, mStatusId);
final ParcelableCredentials credentials = DataStoreUtils.getCredentials(getContext(), mAccountId);
final SingleResponse<ParcelableStatus> response = SingleResponse.getInstance(status);
final Bundle extras = response.getExtras();

View File

@ -39,7 +39,6 @@ import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.TwitterAPIFactory;
@ -81,7 +80,7 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
return SingleResponse.getInstance(user);
}
}
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountId, accountHost, true);
if (twitter == null) return SingleResponse.getInstance();
if (mLoadFromCache) {
final Expression where;

View File

@ -42,7 +42,7 @@ public class SavedSearchesLoader extends AsyncTaskLoader<ResponseList<SavedSearc
@Override
public ResponseList<SavedSearch> loadInBackground() {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, accountHost, false);
if (twitter == null) return null;
try {
return twitter.getSavedSearches();

View File

@ -53,7 +53,7 @@ public class ScheduledStatusesLoader extends AsyncTaskLoader<List<ScheduledStatu
@Override
public List<ScheduledStatus> loadInBackground() {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, accountHost, true);
final Paging paging = new Paging();
if (mSinceId > 0) {
paging.setSinceId(mSinceId);

View File

@ -163,7 +163,7 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
&& statuses.size() >= loadItemLimit;
for (int i = 0, j = statuses.size(); i < j; i++) {
final Status status = statuses.get(i);
data.add(ParcelableStatusUtils.fromStatus(status, mAccountId, insertGap && isGapEnabled() && minIdx == i));
data.add(ParcelableStatusUtils.fromStatus(status, mAccountId, accountHost, insertGap && isGapEnabled() && minIdx == i));
}
final SQLiteDatabase db = TwidereApplication.getInstance(context).getSQLiteDatabase();

View File

@ -44,7 +44,7 @@ public abstract class TwitterAPIUsersLoader extends ParcelableUsersLoader {
@Override
public List<ParcelableUser> loadInBackground() {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(getContext(), mAccountId, accountHost, true);
if (twitter == null) return null;
final List<ParcelableUser> data = getData();
final List<User> users;

View File

@ -11,7 +11,7 @@ import android.view.View;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
public class AccountActionProvider extends ActionProvider implements TwidereConstants {
@ -28,7 +28,7 @@ public class AccountActionProvider extends ActionProvider implements TwidereCons
}
public AccountActionProvider(final Context context) {
this(context, DataStoreUtils.getAccounts(context, false, false));
this(context, ParcelableAccountUtils.getAccounts(context, false, false));
}

View File

@ -0,0 +1,109 @@
package org.mariotaku.twidere.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
/**
* Created by mariotaku on 16/3/5.
*/
@ParcelablePlease
public class AccountId implements Comparable<AccountId>, Parcelable {
@ParcelableThisPlease
long id;
@ParcelableThisPlease
String host;
public AccountId(long id, String host) {
this.id = id;
this.host = host;
}
public AccountId(ParcelableAccount account) {
this.id = account.account_id;
this.host = account.account_host;
}
AccountId() {
}
public long getId() {
return id;
}
public String getHost() {
return host;
}
@Override
public String toString() {
if (host != null) return id + "@" + host;
return String.valueOf(id);
}
public static long[] getIds(AccountId[] ids) {
long[] result = new long[ids.length];
for (int i = 0, idsLength = ids.length; i < idsLength; i++) {
result[i] = ids[i].getId();
}
return result;
}
@Override
public int compareTo(@NonNull AccountId another) {
if (this.id == another.id) {
if (this.host != null && another.host != null) {
return this.host.compareTo(another.host);
} else if (this.host != null) {
return 1;
} else if (another.host != null) {
return -1;
}
return 0;
}
return (int) (this.id - another.id);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
AccountId accountId = (AccountId) o;
return id == accountId.id;
}
@Override
public int hashCode() {
return (int) (id ^ (id >>> 32));
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
AccountIdParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<AccountId> CREATOR = new Creator<AccountId>() {
public AccountId createFromParcel(Parcel source) {
AccountId target = new AccountId();
AccountIdParcelablePlease.readFromParcel(target, source);
return target;
}
public AccountId[] newArray(int size) {
return new AccountId[size];
}
};
}

View File

@ -29,27 +29,27 @@ import android.text.TextUtils;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.model.util.ParcelableAccountUtils;
public class AccountPreferences implements Constants {
private final Context mContext;
private final long mAccountId;
private final AccountId mAccountId;
private final SharedPreferences mPreferences;
public AccountPreferences(final Context context, final long accountId) {
public AccountPreferences(final Context context, final AccountId accountId) {
mContext = context;
mAccountId = accountId;
final String name = ACCOUNT_PREFERENCES_NAME_PREFIX + accountId;
mPreferences = context.getSharedPreferences(name, Context.MODE_PRIVATE);
}
public long getAccountId() {
public AccountId getAccountId() {
return mAccountId;
}
public int getDefaultNotificationLightColor() {
final ParcelableAccount a = DataStoreUtils.getAccount(mContext, mAccountId);
final ParcelableAccount a = ParcelableAccountUtils.getAccount(mContext, mAccountId);
if (a != null) {
return a.color;
} else {
@ -130,14 +130,14 @@ public class AccountPreferences implements Constants {
return mPreferences.getBoolean(KEY_NOTIFICATION, DEFAULT_NOTIFICATION);
}
public static AccountPreferences getAccountPreferences(final AccountPreferences[] prefs, final long accountId) {
public static AccountPreferences getAccountPreferences(final AccountPreferences[] prefs, final AccountId accountId) {
for (final AccountPreferences pref : prefs) {
if (pref.getAccountId() == accountId) return pref;
}
return null;
}
public static AccountPreferences[] getAccountPreferences(final Context context, final long[] accountIds) {
public static AccountPreferences[] getAccountPreferences(final Context context, final AccountId[] accountIds) {
if (context == null || accountIds == null) return null;
final AccountPreferences[] preferences = new AccountPreferences[accountIds.length];
for (int i = 0, j = preferences.length; i < j; i++) {
@ -147,26 +147,26 @@ public class AccountPreferences implements Constants {
}
@NonNull
public static long[] getAutoRefreshEnabledAccountIds(final Context context, final long[] accountIds) {
if (context == null || accountIds == null) return new long[0];
final long[] temp = new long[accountIds.length];
public static AccountId[] getAutoRefreshEnabledAccountIds(final Context context, final AccountId[] accountIds) {
if (context == null || accountIds == null) return new AccountId[0];
final AccountId[] temp = new AccountId[accountIds.length];
int i = 0;
for (final long accountId : accountIds) {
for (final AccountId accountId : accountIds) {
if (new AccountPreferences(context, accountId).isAutoRefreshEnabled()) {
temp[i++] = accountId;
}
}
final long[] enabledIds = new long[i];
final AccountId[] enabledIds = new AccountId[i];
System.arraycopy(temp, 0, enabledIds, 0, i);
return enabledIds;
}
@NonNull
public static AccountPreferences[] getNotificationEnabledPreferences(final Context context, final long[] accountIds) {
public static AccountPreferences[] getNotificationEnabledPreferences(final Context context, final AccountId[] accountIds) {
if (context == null || accountIds == null) return new AccountPreferences[0];
final AccountPreferences[] temp = new AccountPreferences[accountIds.length];
int i = 0;
for (final long accountId : accountIds) {
for (final AccountId accountId : accountIds) {
final AccountPreferences preference = new AccountPreferences(context, accountId);
if (preference.isNotificationEnabled()) {
temp[i++] = preference;

View File

@ -8,11 +8,13 @@ import android.support.annotation.Nullable;
*/
public class BaseRefreshTaskParam implements RefreshTaskParam {
private final long[] accountIds, maxIds, sinceIds;
private final org.mariotaku.twidere.model.AccountId[] accountIds;
private final long[] maxIds;
private final long[] sinceIds;
@NonNull
@Override
public long[] getAccountIds() {
public org.mariotaku.twidere.model.AccountId[] getAccountIds() {
return accountIds;
}
@ -28,9 +30,10 @@ public class BaseRefreshTaskParam implements RefreshTaskParam {
return sinceIds;
}
public BaseRefreshTaskParam(long[] accountIds, long[] maxIds, long[] sinceIds) {
public BaseRefreshTaskParam(org.mariotaku.twidere.model.AccountId[] accountIds, long[] maxIds, long[] sinceIds) {
this.accountIds = accountIds;
this.maxIds = maxIds;
this.sinceIds = sinceIds;
}
}

View File

@ -8,11 +8,12 @@ import android.support.annotation.Nullable;
*/
public interface RefreshTaskParam {
@NonNull
long[] getAccountIds();
org.mariotaku.twidere.model.AccountId[] getAccountIds();
@Nullable
long[] getMaxIds();
@Nullable
long[] getSinceIds();
}

View File

@ -22,6 +22,7 @@ package org.mariotaku.twidere.model.message;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableStatus;
/**
@ -30,7 +31,7 @@ import org.mariotaku.twidere.model.ParcelableStatus;
public class FavoriteTaskEvent {
private int action;
private long accountId;
private AccountId accountId;
private long statusId;
@Nullable
@ -38,7 +39,7 @@ public class FavoriteTaskEvent {
private boolean finished;
private boolean succeeded;
public FavoriteTaskEvent(@Action final int action, final long accountId, final long statusId) {
public FavoriteTaskEvent(@Action final int action, final AccountId accountId, final long statusId) {
this.action = action;
this.accountId = accountId;
this.statusId = statusId;
@ -48,7 +49,7 @@ public class FavoriteTaskEvent {
return action;
}
public long getAccountId() {
public AccountId getAccountId() {
return accountId;
}

View File

@ -2,6 +2,8 @@ package org.mariotaku.twidere.model.message;
import android.support.annotation.IntDef;
import org.mariotaku.twidere.model.AccountId;
/**
* Created by mariotaku on 16/2/15.
*/
@ -11,10 +13,10 @@ public class FollowRequestTaskEvent {
private int action;
private boolean finished;
private boolean succeeded;
private long accountId;
private AccountId accountId;
private long userId;
public FollowRequestTaskEvent(@Action int action, long accountId, long userId) {
public FollowRequestTaskEvent(@Action int action, AccountId accountId, long userId) {
this.action = action;
this.accountId = accountId;
this.userId = userId;
@ -33,7 +35,7 @@ public class FollowRequestTaskEvent {
this.finished = finished;
}
public long getAccountId() {
public AccountId getAccountId() {
return accountId;
}

View File

@ -22,18 +22,20 @@ package org.mariotaku.twidere.model.message;
import android.support.annotation.NonNull;
import org.mariotaku.twidere.api.twitter.model.Relationship;
import org.mariotaku.twidere.model.AccountId;
/**
* Created by mariotaku on 14/12/7.
*/
public class FriendshipUpdatedEvent {
public final long accountId;
@NonNull
public final AccountId accountId;
public final long userId;
@NonNull
public final Relationship relationship;
public FriendshipUpdatedEvent(long accountId, long userId,@NonNull Relationship relationship) {
public FriendshipUpdatedEvent(@NonNull AccountId accountId, long userId, @NonNull Relationship relationship) {
this.accountId = accountId;
this.userId = userId;
this.relationship = relationship;

View File

@ -1,17 +1,20 @@
package org.mariotaku.twidere.model.message;
import org.mariotaku.twidere.model.AccountId;
/**
* Created by mariotaku on 16/2/26.
*/
public class SavedSearchDestroyedEvent {
private final long accountId, searchId;
private final AccountId accountId;
private final long searchId;
public SavedSearchDestroyedEvent(long accountId, long searchId) {
public SavedSearchDestroyedEvent(AccountId accountId, long searchId) {
this.accountId = accountId;
this.searchId = searchId;
}
public long getAccountId() {
public AccountId getAccountId() {
return accountId;
}

View File

@ -1,8 +1,25 @@
package org.mariotaku.twidere.model.util;
import android.content.Context;
import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import org.mariotaku.sqliteqb.library.Columns;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.sqliteqb.library.RawItemArray;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.api.twitter.model.UserList;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.TwitterContentUtils;
import java.util.List;
/**
* Created by mariotaku on 16/2/20.
@ -17,4 +34,73 @@ public class ParcelableAccountUtils {
return ids;
}
@Nullable
public static ParcelableAccount getAccount(final Context context, final long accountId,
final String accountHost) {
if (context == null || accountId < 0) return null;
final Expression where = Expression.equals(Accounts.ACCOUNT_ID, accountId);
Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI,
Accounts.COLUMNS_NO_CREDENTIALS, where.getSQL(), null, null);
if (cur == null) return null;
try {
ParcelableAccountCursorIndices i = new ParcelableAccountCursorIndices(cur);
cur.moveToFirst();
while (!cur.isAfterLast()) {
if (TextUtils.equals(cur.getString(i.account_host), accountHost)) {
return i.newObject(cur);
}
cur.moveToNext();
}
if (cur.moveToFirst()) {
return i.newObject(cur);
}
} finally {
cur.close();
}
return null;
}
public static ParcelableAccount getAccount(final Context context, final AccountId accountId) {
return getAccount(context, accountId.getId(), accountId.getHost());
}
@NonNull
public static ParcelableAccount[] getAccounts(final Context context, final boolean activatedOnly,
final boolean officialKeyOnly) {
final List<ParcelableAccount> list = DataStoreUtils.getAccountsList(context, activatedOnly, officialKeyOnly);
return list.toArray(new ParcelableAccount[list.size()]);
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Context context, @Nullable final long... accountIds) {
if (context == null) return new ParcelableAccount[0];
final String where = accountIds != null ? Expression.in(new Columns.Column(Accounts.ACCOUNT_ID),
new RawItemArray(accountIds)).getSQL() : null;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
if (cur == null) return new ParcelableAccount[0];
return getAccounts(cur, new ParcelableAccountCursorIndices(cur));
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor) {
if (cursor == null) return new ParcelableAccount[0];
return getAccounts(cursor, new ParcelableAccountCursorIndices(cursor));
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor, @Nullable final ParcelableAccountCursorIndices indices) {
if (cursor == null || indices == null) return new ParcelableAccount[0];
try {
cursor.moveToFirst();
final ParcelableAccount[] names = new ParcelableAccount[cursor.getCount()];
while (!cursor.isAfterLast()) {
names[cursor.getPosition()] = indices.newObject(cursor);
cursor.moveToNext();
}
return names;
} finally {
cursor.close();
}
}
}

View File

@ -5,7 +5,6 @@ import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserList;
/**
* Created by mariotaku on 16/1/2.
@ -55,19 +54,21 @@ public class ParcelableActivityUtils {
return activity.after_filtered_sources = result;
}
public static ParcelableActivity fromActivity(final Activity activity, final long accountId, boolean isGap) {
public static ParcelableActivity fromActivity(final Activity activity, final long accountId,
final String accountHost, final boolean isGap) {
ParcelableActivity result = new ParcelableActivity();
result.account_id = accountId;
result.account_host = accountHost;
result.timestamp = activity.getCreatedAt().getTime();
result.action = activity.getAction();
result.max_position = activity.getMaxPosition();
result.min_position = activity.getMinPosition();
result.sources = ParcelableUserUtils.fromUsers(activity.getSources(), accountId);
result.target_users = ParcelableUserUtils.fromUsers(activity.getTargetUsers(), accountId);
result.target_user_lists = ParcelableUserList.fromUserLists(activity.getTargetUserLists(), accountId);
result.target_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetStatuses(), accountId);
result.target_object_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetObjectStatuses(), accountId);
result.target_object_user_lists = ParcelableUserList.fromUserLists(activity.getTargetObjectUserLists(), accountId);
result.target_user_lists = ParcelableUserListUtils.fromUserLists(activity.getTargetUserLists(), accountId);
result.target_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetStatuses(), accountId, accountHost);
result.target_object_statuses = ParcelableStatusUtils.fromStatuses(activity.getTargetObjectStatuses(), accountId, accountHost);
result.target_object_user_lists = ParcelableUserListUtils.fromUserLists(activity.getTargetObjectUserLists(), accountId);
result.target_object_users = ParcelableUserUtils.fromUsers(activity.getTargetObjectUsers(), accountId);
if (result.sources != null) {
result.source_ids = new long[result.sources.length];

View File

@ -9,6 +9,7 @@ import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.api.twitter.model.CardEntity;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableCardEntity;
import java.text.ParseException;
@ -21,13 +22,13 @@ import java.util.Map;
public class ParcelableCardEntityUtils implements TwidereConstants {
@Nullable
public static ParcelableCardEntity fromCardEntity(@Nullable CardEntity card, long accountId) {
public static ParcelableCardEntity fromCardEntity(@Nullable CardEntity card, AccountId accountId) {
if (card == null) return null;
final ParcelableCardEntity obj = new ParcelableCardEntity();
obj.name = card.getName();
obj.url = card.getUrl();
obj.users = ParcelableUserUtils.fromUsers(card.getUsers(), accountId);
obj.account_id = accountId;
obj.account_id = accountId.getId();
obj.values = from(card.getBindingValues());
return obj;
}

View File

@ -6,7 +6,6 @@ import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.model.Draft;
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
import org.mariotaku.twidere.model.draft.UpdateStatusActionExtra;
import org.mariotaku.twidere.util.DataStoreUtils;
/**
* Created by mariotaku on 16/2/12.
@ -15,7 +14,7 @@ public class ParcelableStatusUpdateUtils implements Constants {
public static ParcelableStatusUpdate fromDraftItem(final Context context, final Draft draft) {
ParcelableStatusUpdate statusUpdate = new ParcelableStatusUpdate();
statusUpdate.accounts = DataStoreUtils.getAccounts(context, draft.account_ids);
statusUpdate.accounts = ParcelableAccountUtils.getAccounts(context, draft.account_ids);
statusUpdate.text = draft.text;
statusUpdate.location = draft.location;
statusUpdate.media = draft.media;

View File

@ -6,6 +6,7 @@ import android.support.annotation.Nullable;
import org.mariotaku.twidere.api.twitter.model.Place;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableLocation;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUserMention;
@ -31,10 +32,12 @@ public class ParcelableStatusUtils {
status.retweet_id = -1;
}
public static ParcelableStatus fromStatus(final Status orig, final long accountId, final boolean isGap) {
public static ParcelableStatus fromStatus(final Status orig, final AccountId accountId,
final boolean isGap) {
final ParcelableStatus result = new ParcelableStatus();
result.is_gap = isGap;
result.account_id = accountId;
result.account_id = accountId.getId();
result.account_host = accountId.getHost();
result.id = orig.getId();
result.timestamp = getTime(orig.getCreatedAt());
result.extras = new ParcelableStatus.Extras();
@ -116,7 +119,11 @@ public class ParcelableStatusUtils {
result.location = ParcelableLocation.fromGeoLocation(status.getGeoLocation());
result.is_favorite = status.isFavorited();
result.text_unescaped = HtmlEscapeHelper.toPlainText(result.text_html);
result.my_retweet_id = result.retweeted_by_user_id == accountId ? result.id : status.getCurrentUserRetweet();
if (result.retweeted_by_user_id == result.account_id) {
result.my_retweet_id = result.id;
} else {
result.my_retweet_id = status.getCurrentUserRetweet();
}
result.is_possibly_sensitive = status.isPossiblySensitive();
result.mentions = ParcelableUserMention.fromUserMentionEntities(status.getUserMentionEntities());
result.card = ParcelableCardEntityUtils.fromCardEntity(status.getCard(), accountId);
@ -126,7 +133,7 @@ public class ParcelableStatusUtils {
return result;
}
public static ParcelableStatus[] fromStatuses(Status[] statuses, long accountId) {
public static ParcelableStatus[] fromStatuses(Status[] statuses, AccountId accountId) {
if (statuses == null) return null;
int size = statuses.length;
final ParcelableStatus[] result = new ParcelableStatus[size];

View File

@ -0,0 +1,46 @@
package org.mariotaku.twidere.model.util;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.api.twitter.model.UserList;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.util.TwitterContentUtils;
/**
* Created by mariotaku on 16/3/5.
*/
public class ParcelableUserListUtils {
public static ParcelableUserList from(UserList list, AccountId accountId) {
return from(list, accountId, 0, false);
}
public static ParcelableUserList from(UserList list, AccountId accountId, long position, boolean isFollowing) {
ParcelableUserList obj = new ParcelableUserList();
final User user = list.getUser();
obj.position = position;
obj.account_id = accountId.getId();
obj.account_host = accountId.getHost();
obj.id = list.getId();
obj.is_public = UserList.Mode.PUBLIC.equals(list.getMode());
obj.is_following = isFollowing;
obj.name = list.getName();
obj.description = list.getDescription();
obj.user_id = user.getId();
obj.user_name = user.getName();
obj.user_screen_name = user.getScreenName();
obj.user_profile_image_url = TwitterContentUtils.getProfileImageUrl(user);
obj.members_count = list.getMemberCount();
obj.subscribers_count = list.getSubscriberCount();
return obj;
}
public static ParcelableUserList[] fromUserLists(UserList[] userLists, long accountId) {
if (userLists == null) return null;
int size = userLists.length;
final ParcelableUserList[] result = new ParcelableUserList[size];
for (int i = 0; i < size; i++) {
result[i] = new ParcelableUserList(userLists[i], accountId);
}
return result;
}
}

View File

@ -1,11 +1,13 @@
package org.mariotaku.twidere.model.util;
import android.database.Cursor;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
@ -19,15 +21,18 @@ import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor;
*/
public class ParcelableUserUtils implements TwidereConstants {
public static ParcelableUser fromUser(User user, long accountId) {
public static ParcelableUser fromUser(@NonNull User user, @Nullable AccountId accountId) {
return fromUser(user, accountId, 0);
}
public static ParcelableUser fromUser(User user, long accountId, long position) {
public static ParcelableUser fromUser(@NonNull User user, @Nullable AccountId accountId, long position) {
final UrlEntity[] urlEntities = user.getUrlEntities();
final ParcelableUser obj = new ParcelableUser();
obj.position = position;
obj.account_id = accountId;
if (accountId != null) {
obj.account_id = accountId.getId();
obj.account_host = accountId.getHost();
}
obj.id = user.getId();
obj.created_at = user.getCreatedAt().getTime();
obj.is_protected = user.isProtected();
@ -89,7 +94,7 @@ public class ParcelableUserUtils implements TwidereConstants {
return new ParcelableUser(accountId, id, name, screenName, profileImageUrl);
}
public static ParcelableUser[] fromUsers(final User[] users, long accountId) {
public static ParcelableUser[] fromUsers(final User[] users, AccountId accountId) {
if (users == null) return null;
int size = users.length;
final ParcelableUser[] result = new ParcelableUser[size];

View File

@ -445,7 +445,7 @@ public class BackgroundOperationService extends IntentService implements Constan
final long accountId, final long recipientId,
final String text, final String imageUri) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(this, accountId, true, true);
final TwitterUpload twitterUpload = TwitterAPIFactory.getTwitterInstance(this, accountId, true, true, TwitterUpload.class);
final TwitterUpload twitterUpload = TwitterAPIFactory.getTwitterInstance(this, accountId, accountHost, true, true, TwitterUpload.class);
if (twitter == null || twitterUpload == null) return SingleResponse.getInstance();
try {
final ParcelableDirectMessage directMessage;
@ -586,7 +586,7 @@ public class BackgroundOperationService extends IntentService implements Constan
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(this, account.account_id,
true, true);
final TwitterUpload upload = TwitterAPIFactory.getTwitterInstance(this, account.account_id,
true, true, TwitterUpload.class);
accountHost, true, true, TwitterUpload.class);
// Shouldn't happen
if (twitter == null || upload == null || credentials == null) {
@ -701,7 +701,7 @@ public class BackgroundOperationService extends IntentService implements Constan
notReplyToOther = true;
}
}
final ParcelableStatus result = ParcelableStatusUtils.fromStatus(resultStatus, account.account_id, false);
final ParcelableStatus result = ParcelableStatusUtils.fromStatus(resultStatus, account.account_id, accountHost, false);
if (shouldShorten && shortener != null && shortenedResult != null) {
shortener.callback(shortenedResult, result);
}

View File

@ -332,7 +332,8 @@ public class StreamingService extends Service implements Constants {
@Override
public void onStatus(final Status status) {
final ContentValues values = ContentValuesCreator.createStatus(status, account.account_id);
final ContentValues values = ContentValuesCreator.createStatus(status, account.account_id,
account.account_host);
if (!statusStreamStarted) {
statusStreamStarted = true;
values.put(Statuses.IS_GAP, true);

View File

@ -27,6 +27,8 @@ import com.twitter.Extractor;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
@ -64,7 +66,9 @@ public class CacheUsersStatusesTask extends AbstractTask<TwitterListResponse<Sta
final Set<ContentValues> statusesValues = new HashSet<>();
final Set<ContentValues> hashTagValues = new HashSet<>();
statusesValues.add(ContentValuesCreator.createStatus(status, params.accountId));
final AccountId accountId = params.accountId;
statusesValues.add(ContentValuesCreator.createStatus(status, accountId.getId(),
accountId.getHost()));
final String text = InternalTwitterContentUtils.unescapeTwitterStatusText(status.getText());
for (final String hashtag : extractor.extractHashtags(text)) {
final ContentValues values = new ContentValues();

View File

@ -16,6 +16,7 @@ import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
import org.mariotaku.twidere.api.twitter.model.Paging;
import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.message.GetMessagesTaskEvent;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
@ -62,12 +63,12 @@ public abstract class GetDirectMessagesTask extends AbstractTask<RefreshTaskPara
@Override
public List<TwitterWrapper.MessageListResponse> doLongOperation(final RefreshTaskParam param) {
final long[] accountIds = param.getAccountIds();
final AccountId[] accountIds = param.getAccountIds();
final long[] sinceIds = param.getSinceIds(), maxIds = param.getMaxIds();
final List<TwitterWrapper.MessageListResponse> result = new ArrayList<>();
int idx = 0;
final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
for (final long accountId : accountIds) {
for (final AccountId accountId : accountIds) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
if (twitter == null) continue;
try {
@ -108,14 +109,15 @@ public abstract class GetDirectMessagesTask extends AbstractTask<RefreshTaskPara
}
private boolean storeMessages(long accountId, List<DirectMessage> messages, boolean isOutgoing, boolean notify) {
private boolean storeMessages(AccountId accountId, List<DirectMessage> messages, boolean isOutgoing, boolean notify) {
if (messages == null) return true;
final Uri uri = getDatabaseUri();
final ContentValues[] valuesArray = new ContentValues[messages.size()];
for (int i = 0, j = messages.size(); i < j; i++) {
final DirectMessage message = messages.get(i);
valuesArray[i] = ContentValuesCreator.createDirectMessage(message, accountId, isOutgoing);
valuesArray[i] = ContentValuesCreator.createDirectMessage(message, accountId.getId(),
accountId.getHost(), isOutgoing);
}
// Delete all rows conflicting before new data inserted.

View File

@ -12,8 +12,9 @@ import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.SavedSearch;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
@ -21,7 +22,7 @@ import org.mariotaku.twidere.util.content.ContentResolverUtils;
/**
* Created by mariotaku on 16/2/13.
*/
public class GetSavedSearchesTask extends AbstractTask<long[], SingleResponse<Object>, Object>
public class GetSavedSearchesTask extends AbstractTask<AccountId[], SingleResponse<Object>, Object>
implements Constants {
private final Context mContext;
@ -31,17 +32,21 @@ public class GetSavedSearchesTask extends AbstractTask<long[], SingleResponse<Ob
}
@Override
public SingleResponse<Object> doLongOperation(long[] params) {
public SingleResponse<Object> doLongOperation(AccountId[] params) {
final ContentResolver cr = mContext.getContentResolver();
for (long accountId : params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, accountId, true);
for (AccountId accountId : params) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, accountId.getId(),
accountId.getHost(), true);
if (twitter == null) continue;
try {
final ResponseList<SavedSearch> searches = twitter.getSavedSearches();
final ContentValues[] values = ContentValuesCreator.createSavedSearches(searches, accountId);
final Expression where = Expression.equals(TwidereDataStore.SavedSearches.ACCOUNT_ID, accountId);
cr.delete(TwidereDataStore.SavedSearches.CONTENT_URI, where.getSQL(), null);
ContentResolverUtils.bulkInsert(cr, TwidereDataStore.SavedSearches.CONTENT_URI, values);
final ContentValues[] values = ContentValuesCreator.createSavedSearches(searches,
accountId.getId(), accountId.getHost());
final Expression where = Expression.and(Expression.equalsArgs(SavedSearches.ACCOUNT_ID),
Expression.equalsArgs(SavedSearches.ACCOUNT_HOST));
final String[] whereArgs = {String.valueOf(accountId.getId()), accountId.getHost()};
cr.delete(SavedSearches.CONTENT_URI, where.getSQL(), whereArgs);
ContentResolverUtils.bulkInsert(cr, SavedSearches.CONTENT_URI, values);
} catch (TwitterException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);

View File

@ -34,7 +34,7 @@ public abstract class GetTrendsTask extends AbstractTask<Object, Object, Object>
@Override
public Object doLongOperation(final Object param) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountId, false);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountId, accountHost, false);
if (twitter == null) return null;
try {
final List<Trends> trends = getTrends(twitter);

View File

@ -70,7 +70,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
final long accountId = accountIds[i];
final boolean noItemsBefore = DataStoreUtils.getActivitiesCount(context, getContentUri(),
accountId) <= 0;
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, accountHost, true);
if (twitter == null) continue;
final Paging paging = new Paging();
paging.count(loadItemLimit);
@ -87,7 +87,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
// We should delete old activities has intersection with new items
try {
final ResponseList<Activity> activities = getActivities(twitter, accountId, paging);
storeActivities(cr, accountId, noItemsBefore, activities);
storeActivities(cr, loadItemLimit, accountId, noItemsBefore, activities);
// if (saveReadPosition && TwitterAPIFactory.isOfficialTwitterInstance(context, twitter)) {
if (saveReadPosition) {
saveReadPosition(accountId, twitter);
@ -112,13 +112,13 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
@NonNull
protected abstract String getErrorInfoKey();
private void storeActivities(ContentResolver cr, long accountId, boolean noItemsBefore,
ResponseList<Activity> activities) {
private void storeActivities(ContentResolver cr, int loadItemLimit, long accountId,
boolean noItemsBefore, ResponseList<Activity> activities) {
long[] deleteBound = new long[2];
Arrays.fill(deleteBound, -1);
List<ContentValues> valuesList = new ArrayList<>();
for (Activity activity : activities) {
final ParcelableActivity parcelableActivity = ParcelableActivityUtils.fromActivity(activity, accountId, false);
final ParcelableActivity parcelableActivity = ParcelableActivityUtils.fromActivity(activity, accountId, accountHost, false);
if (deleteBound[0] < 0) {
deleteBound[0] = parcelableActivity.min_position;
} else {
@ -140,7 +140,8 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
Expression.lesserEquals(Activities.MAX_POSITION, deleteBound[1])
);
int rowsDeleted = cr.delete(getContentUri(), where.getSQL(), null);
boolean insertGap = !noItemsBefore && rowsDeleted <= 0;
boolean insertGap = valuesList.size() >= loadItemLimit && !noItemsBefore
&& rowsDeleted <= 0;
if (insertGap && !valuesList.isEmpty()) {
valuesList.get(valuesList.size() - 1).put(Activities.IS_GAP, true);
}

View File

@ -23,6 +23,7 @@ import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.Paging;
import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.message.GetStatusesTaskEvent;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
@ -77,8 +78,9 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
@NonNull
protected abstract Uri getContentUri();
private void storeStatus(long accountId, List<Status> statuses,
long sinceId, long maxId, boolean notify) {
private void storeStatus(final long accountId, final String accountHost,
final List<Status> statuses,
final long sinceId, final long maxId, final boolean notify) {
if (statuses == null || statuses.isEmpty() || accountId <= 0) {
return;
}
@ -92,7 +94,7 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
boolean hasIntersection = false;
for (int i = 0, j = statuses.size(); i < j; i++) {
final Status status = statuses.get(i);
values[i] = ContentValuesCreator.createStatus(status, accountId);
values[i] = ContentValuesCreator.createStatus(status, accountId, accountHost);
values[i].put(Statuses.INSERTED_DATE, System.currentTimeMillis());
final long id = status.getId();
if (sinceId > 0 && id <= sinceId) {
@ -157,13 +159,15 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
@Override
public List<TwitterWrapper.StatusListResponse> doLongOperation(final RefreshTaskParam param) {
final long[] accountIds = param.getAccountIds(), maxIds = param.getMaxIds(), sinceIds = param.getSinceIds();
final AccountId[] accountIds = param.getAccountIds();
final long[] maxIds = param.getMaxIds();
final long[] sinceIds = param.getSinceIds();
final List<TwitterWrapper.StatusListResponse> result = new ArrayList<>();
if (accountIds == null) return result;
int idx = 0;
final int loadItemLimit = preferences.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
for (final long accountId : accountIds) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
for (final AccountId accountId : accountIds) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId.getId(),
accountId.getHost(), true);
if (twitter == null) continue;
try {
final Paging paging = new Paging();
@ -186,18 +190,18 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
}
final List<Status> statuses = getStatuses(twitter, paging);
InternalTwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
storeStatus(accountId, statuses, sinceId, maxId, true);
storeStatus(accountId.getId(), accountId.getHost(), statuses, sinceId, maxId, true);
// TODO cache related data and preload
final CacheUsersStatusesTask cacheTask = new CacheUsersStatusesTask(context);
cacheTask.setParams(new TwitterWrapper.StatusListResponse(accountId, statuses));
TaskStarter.execute(cacheTask);
errorInfoStore.remove(getErrorInfoKey(), accountId);
errorInfoStore.remove(getErrorInfoKey(), accountId.getId());
} catch (final TwitterException e) {
if (BuildConfig.DEBUG) {
Log.w(LOGTAG, e);
}
if (e.isCausedByNetworkIssue()) {
errorInfoStore.put(getErrorInfoKey(), accountId,
errorInfoStore.put(getErrorInfoKey(), accountId.getId(),
ErrorInfoStore.CODE_NETWORK_ERROR);
}
result.add(new TwitterWrapper.StatusListResponse(accountId, e));

View File

@ -32,6 +32,7 @@ import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.Trend;
import org.mariotaku.twidere.api.twitter.model.Trends;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.Draft;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityValuesCreator;
@ -146,12 +147,12 @@ public final class ContentValuesCreator implements TwidereConstants {
public static ContentValues createCachedUser(final User user) {
if (user == null) return null;
final ContentValues values = new ContentValues();
ParcelableUserValuesCreator.writeTo(ParcelableUserUtils.fromUser(user, -1), values);
ParcelableUserValuesCreator.writeTo(ParcelableUserUtils.fromUser(user, null), values);
return values;
}
public static ContentValues createDirectMessage(final DirectMessage message, final long accountId,
final boolean isOutgoing) {
final String accountHost, final boolean isOutgoing) {
if (message == null) return null;
final ContentValues values = new ContentValues();
final User sender = message.getSender(), recipient = message.getRecipient();
@ -159,6 +160,7 @@ public final class ContentValuesCreator implements TwidereConstants {
final String sender_profile_image_url = TwitterContentUtils.getProfileImageUrl(sender);
final String recipient_profile_image_url = TwitterContentUtils.getProfileImageUrl(recipient);
values.put(DirectMessages.ACCOUNT_ID, accountId);
values.put(DirectMessages.ACCOUNT_HOST, accountHost);
values.put(DirectMessages.MESSAGE_ID, message.getId());
values.put(DirectMessages.MESSAGE_TIMESTAMP, message.getCreatedAt().getTime());
values.put(DirectMessages.SENDER_ID, sender.getId());
@ -237,9 +239,11 @@ public final class ContentValuesCreator implements TwidereConstants {
return values;
}
public static ContentValues createSavedSearch(final SavedSearch savedSearch, final long accountId) {
public static ContentValues createSavedSearch(final SavedSearch savedSearch, final long accountId,
final String accountHost) {
final ContentValues values = new ContentValues();
values.put(SavedSearches.ACCOUNT_ID, accountId);
values.put(SavedSearches.ACCOUNT_HOST, accountHost);
values.put(SavedSearches.SEARCH_ID, savedSearch.getId());
values.put(SavedSearches.CREATED_AT, savedSearch.getCreatedAt().getTime());
values.put(SavedSearches.NAME, savedSearch.getName());
@ -247,17 +251,19 @@ public final class ContentValuesCreator implements TwidereConstants {
return values;
}
public static ContentValues[] createSavedSearches(final List<SavedSearch> savedSearches, long accountId) {
public static ContentValues[] createSavedSearches(final List<SavedSearch> savedSearches,
final long accountId, final String accountHost) {
final ContentValues[] resultValuesArray = new ContentValues[savedSearches.size()];
for (int i = 0, j = savedSearches.size(); i < j; i++) {
resultValuesArray[i] = createSavedSearch(savedSearches.get(i), accountId);
resultValuesArray[i] = createSavedSearch(savedSearches.get(i), accountId, accountHost);
}
return resultValuesArray;
}
@NonNull
public static ContentValues createStatus(final Status orig, final long accountId) {
return ParcelableStatusValuesCreator.create(ParcelableStatusUtils.fromStatus(orig, accountId, false));
public static ContentValues createStatus(final Status orig, final AccountId accountId) {
return ParcelableStatusValuesCreator.create(ParcelableStatusUtils.fromStatus(orig,
accountId, false));
}
@NonNull

View File

@ -49,8 +49,8 @@ import org.mariotaku.sqliteqb.library.query.SQLSelectQuery;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableAccountCursorIndices;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
import org.mariotaku.twidere.model.UserFollowState;
@ -197,44 +197,46 @@ public class DataStoreUtils implements Constants {
@NonNull
public static long[] getNewestMessageIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, DirectMessages.ACCOUNT_ID, DirectMessages.MESSAGE_ID,
@NonNull final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds),
DirectMessages.ACCOUNT_ID, DirectMessages.MESSAGE_ID,
new OrderBy(SQLFunctions.MAX(DirectMessages.MESSAGE_TIMESTAMP)));
}
@NonNull
public static long[] getNewestStatusIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, Statuses.ACCOUNT_ID, Statuses.STATUS_ID,
@NonNull final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds), Statuses.ACCOUNT_ID, Statuses.STATUS_ID,
new OrderBy(SQLFunctions.MAX(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static long[] getOldestMessageIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, DirectMessages.ACCOUNT_ID,
@NonNull final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds), DirectMessages.ACCOUNT_ID,
DirectMessages.MESSAGE_ID, new OrderBy(SQLFunctions.MIN(DirectMessages.MESSAGE_TIMESTAMP)));
}
@NonNull
public static long[] getOldestStatusIds(@NonNull final Context context, @NonNull final Uri uri,
@NonNull final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, Statuses.ACCOUNT_ID, Statuses.STATUS_ID,
@NonNull final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds), Statuses.ACCOUNT_ID, Statuses.STATUS_ID,
new OrderBy(SQLFunctions.MIN(Statuses.STATUS_TIMESTAMP)));
}
@NonNull
public static long[] getNewestActivityMaxPositions(final Context context, final Uri uri, final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, Activities.ACCOUNT_ID,
public static long[] getNewestActivityMaxPositions(final Context context, final Uri uri,
final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds), Activities.ACCOUNT_ID,
Activities.MAX_POSITION, new OrderBy(SQLFunctions.MAX(Activities.TIMESTAMP)));
}
@NonNull
public static long[] getOldestActivityMaxPositions(@NonNull final Context context,
@NonNull final Uri uri,
@NonNull final long[] accountIds) {
return getLongFieldArray(context, uri, accountIds, Activities.ACCOUNT_ID,
@NonNull final AccountId[] accountIds) {
return getLongFieldArray(context, uri, AccountId.getIds(accountIds), Activities.ACCOUNT_ID,
Activities.MAX_POSITION, new OrderBy(SQLFunctions.MIN(Activities.TIMESTAMP)));
}
@ -327,7 +329,9 @@ public class DataStoreUtils implements Constants {
if (context == null) return null;
final String cached = sAccountScreenNames.get(accountId);
if (!isEmpty(cached)) return cached;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.SCREEN_NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
final String[] projection = {Accounts.SCREEN_NAME};
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, projection,
Accounts.ACCOUNT_ID + " = " + accountId, null, null);
if (cur == null) return null;
try {
if (cur.getCount() > 0 && cur.moveToFirst()) {
@ -345,7 +349,7 @@ public class DataStoreUtils implements Constants {
return getAccountScreenNames(context, null);
}
public static String[] getAccountScreenNames(final Context context, final long[] accountIds) {
public static String[] getAccountScreenNames(final Context context, @Nullable final AccountId[] accountIds) {
if (context == null) return new String[0];
final String[] cols = new String[]{Accounts.SCREEN_NAME};
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
@ -367,16 +371,17 @@ public class DataStoreUtils implements Constants {
}
@NonNull
public static long[] getActivatedAccountIds(final Context context) {
if (context == null) return new long[0];
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID}, Accounts.IS_ACTIVATED + " = 1", null, null);
if (cur == null) return new long[0];
public static AccountId[] getActivatedAccountIds(final Context context) {
if (context == null) return new AccountId[0];
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI,
new String[]{Accounts.ACCOUNT_ID,Accounts.ACCOUNT_HOST}, Accounts.IS_ACTIVATED + " = 1", null, null);
if (cur == null) return new AccountId[0];
try {
cur.moveToFirst();
final long[] ids = new long[cur.getCount()];
final AccountId[] ids = new AccountId[cur.getCount()];
int i = 0;
while (!cur.isAfterLast()) {
ids[i++] = cur.getLong(0);
ids[i++] = new AccountId(cur.getLong(0), cur.getString(1));
cur.moveToNext();
}
return ids;
@ -634,16 +639,18 @@ public class DataStoreUtils implements Constants {
}
@NonNull
public static long[] getAccountIds(final Context context) {
if (context == null) return new long[0];
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID}, null, null, null);
if (cur == null) return new long[0];
public static AccountId[] getAccountIds(final Context context) {
if (context == null) return new AccountId[0];
final String[] projection = {Accounts.ACCOUNT_ID, Accounts.ACCOUNT_HOST};
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, projection,
null, null, null);
if (cur == null) return new AccountId[0];
try {
cur.moveToFirst();
final long[] ids = new long[cur.getCount()];
final AccountId[] ids = new AccountId[cur.getCount()];
int i = 0;
while (!cur.isAfterLast()) {
ids[i++] = cur.getLong(0);
ids[i++] = new AccountId(cur.getLong(0), cur.getString(1));
cur.moveToNext();
}
return ids;
@ -688,49 +695,61 @@ public class DataStoreUtils implements Constants {
final int itemLimit = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE).getInt(
KEY_DATABASE_ITEM_LIMIT, DEFAULT_DATABASE_ITEM_LIMIT);
for (final long accountId : getAccountIds(context)) {
for (final AccountId accountId : getAccountIds(context)) {
// Clean statuses.
for (final Uri uri : STATUSES_URIS) {
if (CachedStatuses.CONTENT_URI.equals(uri)) {
continue;
}
final String table = getTableNameByUri(uri);
final Expression accountWhere = new Expression(Statuses.ACCOUNT_ID + " = " + accountId);
final Expression accountWhere = Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_ID),
Expression.equalsArgs(Statuses.ACCOUNT_HOST));
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(new Column(Statuses._ID))
.from(new Tables(table))
.where(Expression.equals(Statuses.ACCOUNT_ID, accountId))
.where(accountWhere)
.orderBy(new OrderBy(Statuses.STATUS_ID, false))
.limit(itemLimit);
final Expression where = Expression.and(Expression.lesserThan(new Column(Statuses._ID),
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Statuses._ID))).from(qb.build()).build()), accountWhere);
resolver.delete(uri, where.getSQL(), null);
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Statuses._ID))).from(qb.build()).build()),
accountWhere);
final String[] whereArgs = {String.valueOf(accountId.getId()), accountId.getHost(),
String.valueOf(accountId.getId()), accountId.getHost()};
resolver.delete(uri, where.getSQL(), whereArgs);
}
for (final Uri uri : ACTIVITIES_URIS) {
final String table = getTableNameByUri(uri);
final Expression accountWhere = new Expression(Activities.ACCOUNT_ID + " = " + accountId);
final Expression accountWhere = Expression.and(Expression.equalsArgs(Accounts.ACCOUNT_ID),
Expression.equalsArgs(Accounts.ACCOUNT_HOST));
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(new Column(Activities._ID))
.from(new Tables(table))
.where(Expression.equals(Activities.ACCOUNT_ID, accountId))
.where(accountWhere)
.orderBy(new OrderBy(Activities.TIMESTAMP, false))
.limit(itemLimit);
final Expression where = Expression.and(Expression.lesserThan(new Column(Activities._ID),
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Activities._ID))).from(qb.build()).build()), accountWhere);
resolver.delete(uri, where.getSQL(), null);
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(Activities._ID)))
.from(qb.build()).build()), accountWhere);
final String[] whereArgs = {String.valueOf(accountId.getId()), accountId.getHost(),
String.valueOf(accountId.getId()), accountId.getHost()};
resolver.delete(uri, where.getSQL(), whereArgs);
}
for (final Uri uri : DIRECT_MESSAGES_URIS) {
final String table = getTableNameByUri(uri);
final Expression accountWhere = new Expression(DirectMessages.ACCOUNT_ID + " = " + accountId);
final Expression accountWhere = Expression.and(Expression.equalsArgs(DirectMessages.ACCOUNT_ID),
Expression.equalsArgs(DirectMessages.ACCOUNT_HOST));
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(new Column(DirectMessages._ID))
.from(new Tables(table))
.where(Expression.equals(DirectMessages.ACCOUNT_ID, accountId))
.where(accountWhere)
.orderBy(new OrderBy(DirectMessages.MESSAGE_ID, false))
.limit(itemLimit * 10);
final Expression where = Expression.and(Expression.lesserThan(new Column(DirectMessages._ID),
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(DirectMessages._ID))).from(qb.build()).build()), accountWhere);
resolver.delete(uri, where.getSQL(), null);
SQLQueryBuilder.select(SQLFunctions.MIN(new Column(DirectMessages._ID)))
.from(qb.build()).build()), accountWhere);
final String[] whereArgs = {String.valueOf(accountId.getId()), accountId.getHost(),
String.valueOf(accountId.getId()), accountId.getHost()};
resolver.delete(uri, where.getSQL(), whereArgs);
}
}
// Clean cached values.
@ -787,7 +806,8 @@ public class DataStoreUtils implements Constants {
if (sortExpression != null) {
builder.orderBy(sortExpression);
}
final Cursor cur = resolver.query(Uri.withAppendedPath(TwidereDataStore.CONTENT_URI_RAW_QUERY, builder.buildSQL()), null, null, selectionArgs, null);
final Cursor cur = resolver.query(Uri.withAppendedPath(TwidereDataStore.CONTENT_URI_RAW_QUERY,
builder.buildSQL()), null, null, selectionArgs, null);
if (cur == null) return messageIds;
try {
while (cur.moveToNext()) {
@ -818,20 +838,6 @@ public class DataStoreUtils implements Constants {
}
}
public static ParcelableAccount getAccount(final Context context, final long accountId) {
if (context == null) return null;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
if (cur == null) return null;
try {
if (cur.moveToFirst()) {
return ParcelableAccountCursorIndices.fromCursor(cur);
}
} finally {
cur.close();
}
return null;
}
@NonNull
public static long[] getAccountIds(final ParcelableAccount[] accounts) {
final long[] ids = new long[accounts.length];
@ -841,45 +847,6 @@ public class DataStoreUtils implements Constants {
return ids;
}
@NonNull
public static ParcelableAccount[] getAccounts(final Context context, final boolean activatedOnly,
final boolean officialKeyOnly) {
final List<ParcelableAccount> list = getAccountsList(context, activatedOnly, officialKeyOnly);
return list.toArray(new ParcelableAccount[list.size()]);
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Context context, @Nullable final long... accountIds) {
if (context == null) return new ParcelableAccount[0];
final String where = accountIds != null ? Expression.in(new Column(Accounts.ACCOUNT_ID),
new RawItemArray(accountIds)).getSQL() : null;
final Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS_NO_CREDENTIALS, where, null, null);
if (cur == null) return new ParcelableAccount[0];
return getAccounts(cur, new ParcelableAccountCursorIndices(cur));
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor) {
if (cursor == null) return new ParcelableAccount[0];
return getAccounts(cursor, new ParcelableAccountCursorIndices(cursor));
}
@NonNull
public static ParcelableAccount[] getAccounts(@Nullable final Cursor cursor, @Nullable final ParcelableAccountCursorIndices indices) {
if (cursor == null || indices == null) return new ParcelableAccount[0];
try {
cursor.moveToFirst();
final ParcelableAccount[] names = new ParcelableAccount[cursor.getCount()];
while (!cursor.isAfterLast()) {
names[cursor.getPosition()] = indices.newObject(cursor);
cursor.moveToNext();
}
return names;
} finally {
cursor.close();
}
}
public static List<ParcelableAccount> getAccountsList(final Context context, final boolean activatedOnly) {
return getAccountsList(context, activatedOnly, false);
}
@ -910,14 +877,27 @@ public class DataStoreUtils implements Constants {
}
@Nullable
public static ParcelableCredentials getCredentials(final Context context, final long accountId) {
if (context == null || accountId < 0) return null;
public static ParcelableCredentials getCredentials(@NonNull final Context context, final AccountId accountId) {
return getCredentials(context, accountId.getId(), accountId.getHost());
}
@Nullable
public static ParcelableCredentials getCredentials(@NonNull final Context context, final long accountId,
final String accountHost) {
Cursor cur = context.getContentResolver().query(Accounts.CONTENT_URI, Accounts.COLUMNS,
Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(), null, null);
if (cur == null) return null;
try {
ParcelableCredentialsCursorIndices i = new ParcelableCredentialsCursorIndices(cur);
cur.moveToFirst();
while (!cur.isAfterLast()) {
if (TextUtils.equals(cur.getString(i.account_host), accountHost)) {
return i.newObject(cur);
}
cur.moveToNext();
}
if (cur.moveToFirst()) {
return ParcelableCredentialsCursorIndices.fromCursor(cur);
return i.newObject(cur);
}
} finally {
cur.close();

View File

@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.AccountId;
/**
@ -45,6 +46,15 @@ public class ErrorInfoStore {
put(key + "_" + extraId, code);
}
public void put(String key, AccountId extraId, int code) {
final String host = extraId.getHost();
if (host == null) {
put(key, extraId.getId(), code);
} else {
put(key + "_" + extraId.getId() + "_" + host, code);
}
}
@Nullable
public static DisplayErrorInfo getErrorInfo(@NonNull Context context, int code) {
switch (code) {
@ -68,6 +78,15 @@ public class ErrorInfoStore {
remove(key + "_" + extraId);
}
public void remove(String key, AccountId extraId) {
final String host = extraId.getHost();
if (host == null) {
remove(key, extraId.getId());
} else {
remove(key + "_" + extraId.getId() + "_" + host);
}
}
public void remove(String key) {
mPreferences.edit().remove(key).apply();
}

View File

@ -21,6 +21,7 @@ import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.activity.support.MediaViewerActivity;
import org.mariotaku.twidere.constant.SharedPreferenceConstants;
import org.mariotaku.twidere.fragment.support.SensitiveContentWarningDialogFragment;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableDirectMessage;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
@ -48,7 +49,8 @@ public class IntentUtils implements Constants {
}
public static void openUserProfile(final Context context, final ParcelableUser user,
final Bundle activityOptions, final boolean newDocument) {
final Bundle activityOptions, final boolean newDocument,
@UserFragment.Referral final String referral) {
if (context == null || user == null) return;
final Bundle extras = new Bundle();
extras.putParcelable(EXTRA_USER, user);
@ -65,6 +67,7 @@ public class IntentUtils implements Constants {
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
intent.setExtrasClassLoader(context.getClassLoader());
intent.putExtras(extras);
intent.putExtra(EXTRA_REFERRAL, referral);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && newDocument) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
}
@ -77,10 +80,12 @@ public class IntentUtils implements Constants {
public static void openUserProfile(final Context context, final long accountId, final long userId,
final String screenName, final Bundle activityOptions,
final boolean newDocument) {
final boolean newDocument,
@UserFragment.Referral final String referral) {
if (context == null || accountId <= 0 || userId <= 0 && isEmpty(screenName)) return;
final Uri uri = LinkCreator.getTwidereUserLink(accountId, userId, screenName);
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(EXTRA_REFERRAL, referral);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && newDocument) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
}

View File

@ -55,6 +55,7 @@ import org.mariotaku.twidere.graphic.ActionIconDrawable;
import org.mariotaku.twidere.graphic.PaddingDrawable;
import org.mariotaku.twidere.menu.SupportStatusShareProvider;
import org.mariotaku.twidere.menu.support.FavoriteItemProvider;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.menu.TwidereMenuInfo;
@ -137,7 +138,8 @@ public class MenuUtils implements Constants {
@NonNull final ParcelableStatus status,
@NonNull UserColorNameManager manager,
@NonNull final AsyncTwitterWrapper twitter) {
final ParcelableCredentials account = DataStoreUtils.getCredentials(context, status.account_id);
final ParcelableCredentials account = DataStoreUtils.getCredentials(context, new AccountId(status.account_id,
status.account_host));
if (account == null) return;
setupForStatus(context, preferences, menu, status, account, manager, twitter);
}
@ -255,9 +257,11 @@ public class MenuUtils implements Constants {
}
case R.id.retweet: {
if (Utils.isMyRetweet(status)) {
twitter.cancelRetweetAsync(status.account_id, status.id, status.my_retweet_id);
twitter.cancelRetweetAsync(new AccountId(status.account_id, status.account_host),
status.id, status.my_retweet_id);
} else {
twitter.retweetStatusAsync(status.account_id, status.id);
twitter.retweetStatusAsync(new AccountId(status.account_id, status.account_host),
status.id);
}
break;
}
@ -282,7 +286,8 @@ public class MenuUtils implements Constants {
((FavoriteItemProvider) provider).invokeItem(item,
new AbsStatusesFragment.DefaultOnLikedListener(twitter, status));
} else {
twitter.createFavoriteAsync(status.account_id, status.id);
twitter.createFavoriteAsync(new AccountId(status.account_id, status.account_host),
status.id);
}
}
break;

View File

@ -28,6 +28,7 @@ import android.support.annotation.Nullable;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
import org.mariotaku.twidere.util.TwidereLinkify.OnLinkClickListener;
@ -62,7 +63,8 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants {
switch (type) {
case TwidereLinkify.LINK_TYPE_MENTION: {
IntentUtils.openUserProfile(context, accountId, -1, link, null, true);
IntentUtils.openUserProfile(context, accountId, -1, link, null, true,
UserFragment.Referral.USER_MENTION);
break;
}
case TwidereLinkify.LINK_TYPE_HASHTAG: {
@ -90,7 +92,8 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants {
break;
}
case TwidereLinkify.LINK_TYPE_USER_ID: {
IntentUtils.openUserProfile(context, accountId, NumberUtils.toLong(link, -1), null, null, true);
IntentUtils.openUserProfile(context, accountId, NumberUtils.toLong(link, -1), null,
null, true, UserFragment.Referral.USER_MENTION);
break;
}
case TwidereLinkify.LINK_TYPE_STATUS: {

View File

@ -148,8 +148,10 @@ public final class TwidereLinkify implements Constants {
return applyUserProfileLink(text, accountId, extraId, userId, screenName, highlightOption, mOnLinkClickListener);
}
public final SpannableString applyUserProfileLink(final CharSequence text, final long accountId, final long extraId,
final long userId, final String screenName, final int highlightOption, final OnLinkClickListener listener) {
public final SpannableString applyUserProfileLink(final CharSequence text, final long accountId,
final long extraId, final long userId,
final String screenName, final int highlightOption,
final OnLinkClickListener listener) {
final SpannableString string = SpannableString.valueOf(text);
final URLSpan[] spans = string.getSpans(0, string.length(), URLSpan.class);
for (final URLSpan span : spans) {

View File

@ -39,6 +39,7 @@ import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint;
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
import org.mariotaku.twidere.api.twitter.util.TwitterConverterFactory;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ConsumerKeyType;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils;
@ -87,18 +88,20 @@ public class TwitterAPIFactory implements TwidereConstants {
public static Twitter getDefaultTwitterInstance(final Context context, final boolean includeEntities,
final boolean includeRetweets) {
if (context == null) return null;
return getTwitterInstance(context, Utils.getDefaultAccountId(context), includeEntities, includeRetweets);
final AccountId accountId = Utils.getDefaultAccountId(context);
if (accountId == null) return null;
return getTwitterInstance(context, accountId, includeEntities, includeRetweets);
}
@WorkerThread
public static Twitter getTwitterInstance(final Context context, final long accountId,
public static Twitter getTwitterInstance(final Context context, final AccountId accountId,
final boolean includeEntities) {
return getTwitterInstance(context, accountId, includeEntities, true);
}
@Nullable
@WorkerThread
public static Twitter getTwitterInstance(final Context context, final long accountId,
public static Twitter getTwitterInstance(final Context context, final AccountId accountId,
final boolean includeEntities,
final boolean includeRetweets) {
return getTwitterInstance(context, accountId, includeEntities, includeRetweets, Twitter.class);
@ -106,11 +109,12 @@ public class TwitterAPIFactory implements TwidereConstants {
@Nullable
@WorkerThread
public static <T> T getTwitterInstance(final Context context, final long accountId,
final boolean includeEntities,
final boolean includeRetweets, Class<T> cls) {
public static <T> T getTwitterInstance(final Context context, final AccountId accountId,
final boolean includeEntities, final boolean includeRetweets,
Class<T> cls) {
if (context == null) return null;
final ParcelableCredentials credentials = DataStoreUtils.getCredentials(context, accountId);
final ParcelableCredentials credentials = DataStoreUtils.getCredentials(context,
accountId.getId(), accountId.getHost());
final HashMap<String, String> extraParams = new HashMap<>();
extraParams.put("include_entities", String.valueOf(includeEntities));
extraParams.put("include_retweets", String.valueOf(includeRetweets));

View File

@ -29,13 +29,14 @@ import org.mariotaku.restfu.http.mime.FileBody;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
import org.mariotaku.twidere.api.twitter.model.Paging;
import org.mariotaku.twidere.api.twitter.model.ResponseList;
import org.mariotaku.twidere.api.twitter.model.Status;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.ListResponse;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.provider.TwidereDataStore.Notifications;
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
@ -63,8 +64,9 @@ public class TwitterWrapper implements Constants {
return context.getContentResolver().delete(uri, null, null);
}
public static SingleResponse<Boolean> deleteProfileBannerImage(final Context context, final long account_id) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, account_id, false);
public static SingleResponse<Boolean> deleteProfileBannerImage(final Context context,
final AccountId accountId) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, false);
if (twitter == null) return new SingleResponse<>(false, null);
try {
twitter.removeProfileBannerImage();
@ -159,13 +161,6 @@ public class TwitterWrapper implements Constants {
}
}
public static void updateProfileBannerImage(final Context context, final long accountId,
final Uri imageUri, final boolean deleteImage)
throws FileNotFoundException, TwitterException {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, false);
updateProfileBannerImage(context, twitter, imageUri, deleteImage);
}
public static void updateProfileBannerImage(final Context context, final Twitter twitter,
final Uri imageUri, final boolean deleteImage)
throws FileNotFoundException, TwitterException {
@ -202,31 +197,24 @@ public class TwitterWrapper implements Constants {
}
}
public static User updateProfileImage(final Context context, final long accountId,
final Uri imageUri, final boolean deleteImage)
throws FileNotFoundException, TwitterException {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
return updateProfileImage(context, twitter, imageUri, deleteImage);
}
public static final class MessageListResponse extends TwitterListResponse<DirectMessage> {
public final boolean truncated;
public MessageListResponse(final long accountId, final Exception exception) {
public MessageListResponse(final AccountId accountId, final Exception exception) {
this(accountId, -1, -1, null, false, exception);
}
public MessageListResponse(final long accountId, final List<DirectMessage> list) {
public MessageListResponse(final AccountId accountId, final List<DirectMessage> list) {
this(accountId, -1, -1, list, false, null);
}
public MessageListResponse(final long accountId, final long maxId, final long sinceId,
public MessageListResponse(final AccountId accountId, final long maxId, final long sinceId,
final List<DirectMessage> list, final boolean truncated) {
this(accountId, maxId, sinceId, list, truncated, null);
}
MessageListResponse(final long accountId, final long maxId, final long sinceId,
MessageListResponse(final AccountId accountId, final long maxId, final long sinceId,
final List<DirectMessage> list, final boolean truncated, final Exception exception) {
super(accountId, maxId, sinceId, list, exception);
this.truncated = truncated;
@ -238,45 +226,20 @@ public class TwitterWrapper implements Constants {
public final boolean truncated;
public StatusListResponse(final long accountId, final Exception exception) {
public StatusListResponse(final AccountId accountId, final Exception exception) {
this(accountId, -1, -1, null, false, exception);
}
public StatusListResponse(final long accountId, final List<Status> list) {
public StatusListResponse(final AccountId accountId, final List<Status> list) {
this(accountId, -1, -1, list, false, null);
}
public StatusListResponse(final long accountId, final long maxId, final long sinceId,
public StatusListResponse(final AccountId accountId, final long maxId, final long sinceId,
final List<Status> list, final boolean truncated) {
this(accountId, maxId, sinceId, list, truncated, null);
}
StatusListResponse(final long accountId, final long maxId, final long sinceId, final List<Status> list,
final boolean truncated, final Exception exception) {
super(accountId, maxId, sinceId, list, exception);
this.truncated = truncated;
}
}
public static final class ActivityListResponse extends TwitterListResponse<Activity> {
public final boolean truncated;
public ActivityListResponse(final long accountId, final Exception exception) {
this(accountId, -1, -1, null, false, exception);
}
public ActivityListResponse(final long accountId, final List<Activity> list) {
this(accountId, -1, -1, list, false, null);
}
public ActivityListResponse(final long accountId, final long maxId, final long sinceId,
final List<Activity> list, final boolean truncated) {
this(accountId, maxId, sinceId, list, truncated, null);
}
ActivityListResponse(final long accountId, final long maxId, final long sinceId, final List<Activity> list,
StatusListResponse(final AccountId accountId, final long maxId, final long sinceId, final List<Status> list,
final boolean truncated, final Exception exception) {
super(accountId, maxId, sinceId, list, exception);
this.truncated = truncated;
@ -286,18 +249,22 @@ public class TwitterWrapper implements Constants {
public static class TwitterListResponse<Data> extends ListResponse<Data> {
public final long accountId, maxId, sinceId;
public final AccountId accountId;
public final long maxId;
public final long sinceId;
public TwitterListResponse(final long accountId, final Exception exception) {
public TwitterListResponse(final AccountId accountId,
final Exception exception) {
this(accountId, -1, -1, null, exception);
}
public TwitterListResponse(final long accountId, final long maxId, final long sinceId, final List<Data> list) {
public TwitterListResponse(final AccountId accountId, final long maxId,
final long sinceId, final List<Data> list) {
this(accountId, maxId, sinceId, list, null);
}
TwitterListResponse(final long accountId, final long maxId, final long sinceId, final List<Data> list,
final Exception exception) {
TwitterListResponse(final AccountId accountId, final long maxId,
final long sinceId, final List<Data> list, final Exception exception) {
super(list, exception);
this.accountId = accountId;
this.maxId = maxId;

View File

@ -162,6 +162,7 @@ import org.mariotaku.twidere.fragment.support.UserProfileEditorFragment;
import org.mariotaku.twidere.fragment.support.UserTimelineFragment;
import org.mariotaku.twidere.fragment.support.UsersListFragment;
import org.mariotaku.twidere.graphic.PaddingDrawable;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.model.AccountPreferences;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
@ -503,6 +504,7 @@ public final class Utils implements Constants {
if (!args.containsKey(EXTRA_USER_ID)) {
args.putLong(EXTRA_USER_ID, NumberUtils.toLong(param_user_id, -1));
}
args.putString(EXTRA_REFERRAL, intent.getStringExtra(EXTRA_REFERRAL));
break;
}
case LINK_ID_USER_LIST_MEMBERSHIPS: {
@ -765,9 +767,9 @@ public final class Utils implements Constants {
if (paramAccountName != null) {
args.putLong(EXTRA_ACCOUNT_ID, DataStoreUtils.getAccountId(context, paramAccountName));
} else if (isAccountIdRequired) {
final long accountId = getDefaultAccountId(context);
final AccountId accountId = getDefaultAccountId(context);
if (isMyAccount(context, accountId)) {
args.putLong(EXTRA_ACCOUNT_ID, accountId);
args.putLong(EXTRA_ACCOUNT_ID, accountId.getId());
}
}
}
@ -786,11 +788,11 @@ public final class Utils implements Constants {
public static String getReadPositionTagWithAccounts(@ReadPositionTag String tag, Bundle args) {
final long[] accountIds = getAccountIds(args);
final AccountId[] accountIds = getAccountIds(args);
return getReadPositionTagWithAccounts(tag, accountIds);
}
public static long[] getAccountIds(Bundle args) {
public static AccountId[] getAccountIds(Bundle args) {
final long[] accountIds;
if (args.containsKey(EXTRA_ACCOUNT_IDS)) {
accountIds = args.getLongArray(EXTRA_ACCOUNT_IDS);
@ -804,11 +806,10 @@ public final class Utils implements Constants {
@Nullable
public static String getReadPositionTagWithAccounts(@Nullable final String tag,
final long... accountIds) {
final AccountId... accountIds) {
if (tag == null) return null;
if (accountIds == null || accountIds.length == 0 || (accountIds.length == 1 && accountIds[0] < 0))
return tag;
final long[] accountIdsClone = accountIds.clone();
if (ArrayUtils.isEmpty(accountIds)) return tag;
final AccountId[] accountIdsClone = accountIds.clone();
Arrays.sort(accountIdsClone);
return tag + "_" + TwidereArrayUtils.toString(accountIdsClone, '_', false);
}
@ -819,7 +820,7 @@ public final class Utils implements Constants {
long... accountIds) {
if (tag == null) return null;
if (accountIds == null || accountIds.length == 0 || (accountIds.length == 1 && accountIds[0] < 0)) {
final long[] activatedIds = DataStoreUtils.getActivatedAccountIds(context);
final AccountId[] activatedIds = DataStoreUtils.getActivatedAccountIds(context);
Arrays.sort(activatedIds);
return tag + "_" + TwidereArrayUtils.toString(activatedIds, '_', false);
}
@ -871,7 +872,8 @@ public final class Utils implements Constants {
}
@NonNull
public static ParcelableStatus findStatus(final Context context, final long accountId, final long statusId)
public static ParcelableStatus findStatus(final Context context, final AccountId accountId,
final String accountHost, final long statusId)
throws TwitterException {
if (context == null) throw new NullPointerException();
final ParcelableStatus cached = findStatusInDatabases(context, accountId, statusId);
@ -879,7 +881,7 @@ public final class Utils implements Constants {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountId, true);
if (twitter == null) throw new TwitterException("Account does not exist");
final Status status = twitter.showStatus(statusId);
final String where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
final String where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId.getId()),
Expression.equals(Statuses.STATUS_ID, statusId)).getSQL();
final ContentResolver resolver = context.getContentResolver();
resolver.delete(CachedStatuses.CONTENT_URI, where, null);
@ -888,12 +890,12 @@ public final class Utils implements Constants {
}
@Nullable
public static ParcelableStatus findStatusInDatabases(final Context context, final long accountId,
public static ParcelableStatus findStatusInDatabases(final Context context, final AccountId accountId,
final long statusId) {
if (context == null) return null;
final ContentResolver resolver = context.getContentResolver();
ParcelableStatus status = null;
final String where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
final String where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId.getId()),
Expression.equals(Statuses.STATUS_ID, statusId)).getSQL();
for (final Uri uri : STATUSES_URIS) {
final Cursor cur = resolver.query(uri, Statuses.COLUMNS, where, null, null);
@ -970,7 +972,7 @@ public final class Utils implements Constants {
return hasNavBar(context);
}
public static boolean isOfficialCredentials(@NonNull final Context context, final long accountId) {
public static boolean isOfficialCredentials(@NonNull final Context context, final AccountId accountId) {
final ParcelableCredentials credentials = DataStoreUtils.getCredentials(context, accountId);
if (credentials == null) return false;
return isOfficialCredentials(context, credentials);
@ -1115,21 +1117,30 @@ public final class Utils implements Constants {
return new Columns(columns);
}
public static long getDefaultAccountId(final Context context) {
if (context == null) return -1;
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
@Nullable
public static AccountId getDefaultAccountId(final Context context) {
if (context == null) return null;
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE);
final long accountId = prefs.getLong(KEY_DEFAULT_ACCOUNT_ID, -1);
final long[] accountIds = DataStoreUtils.getAccountIds(context);
final String accountHost = prefs.getString(KEY_DEFAULT_ACCOUNT_HOST, null);
final AccountId[] accountIds = DataStoreUtils.getAccountIds(context);
int idMatchIdx = -1;
for (int i = 0, accountIdsLength = accountIds.length; i < accountIdsLength; i++) {
AccountId id = accountIds[i];
if (accountId == id.getId()) {
idMatchIdx = i;
if (TextUtils.equals(accountHost, id.getHost())) return id;
}
}
if (idMatchIdx != -1) {
return accountIds[idMatchIdx];
}
if (accountIds.length > 0 && !ArrayUtils.contains(accountIds, accountId)) {
/* TODO: this is just a quick fix */
return accountIds[0];
}
return accountId;
}
public static String getDefaultAccountScreenName(final Context context) {
if (context == null) return null;
return DataStoreUtils.getAccountScreenName(context, getDefaultAccountId(context));
return null;
}
public static int getDefaultTextSize(final Context context) {
@ -1537,7 +1548,7 @@ public final class Utils implements Constants {
}
public static boolean hasAutoRefreshAccounts(final Context context) {
final long[] accountIds = DataStoreUtils.getAccountIds(context);
final AccountId[] accountIds = DataStoreUtils.getAccountIds(context);
return !ArrayUtils.isEmpty(AccountPreferences.getAutoRefreshEnabledAccountIds(context, accountIds));
}
@ -1588,10 +1599,10 @@ public final class Utils implements Constants {
}
}
public static boolean isMyAccount(final Context context, final long accountId) {
if (context == null) return false;
public static boolean isMyAccount(final Context context, @Nullable final AccountId accountId) {
if (context == null || accountId == null) return false;
final ContentResolver resolver = context.getContentResolver();
final String where = Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL();
final String where = Expression.equals(Accounts.ACCOUNT_ID, accountId.getId()).getSQL();
final String[] projection = new String[0];
final Cursor cur = resolver.query(Accounts.CONTENT_URI, projection, where, null, null);
try {
@ -1647,9 +1658,9 @@ public final class Utils implements Constants {
public static boolean isUserLoggedIn(final Context context, final long accountId) {
if (context == null) return false;
final long[] ids = DataStoreUtils.getAccountIds(context);
for (final long id : ids) {
if (id == accountId) return true;
final AccountId[] ids = DataStoreUtils.getAccountIds(context);
for (final AccountId id : ids) {
if (id.getId() == accountId) return true;
}
return false;
}
@ -2674,6 +2685,12 @@ public final class Utils implements Constants {
return !ConnectivityManagerCompat.isActiveNetworkMetered(cm) || !preferences.getBoolean(KEY_BANDWIDTH_SAVING_MODE);
}
public static Expression getAccountCompareExpression() {
return Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_ID),
Expression.or(Expression.isNull(new Column(Statuses.ACCOUNT_HOST)),
Expression.equalsArgs(Statuses.ACCOUNT_HOST)));
}
static class UtilsL {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)

View File

@ -188,12 +188,9 @@ public class ApplicationModule implements Constants {
@Provides
@Singleton
public AsyncTwitterWrapper asyncTwitterWrapper(UserColorNameManager userColorNameManager,
ReadStateManager readStateManager,
Bus bus, SharedPreferencesWrapper preferences,
AsyncTaskManager asyncTaskManager, ErrorInfoStore errorInfoStore) {
return new AsyncTwitterWrapper(application, userColorNameManager, bus,
preferences, asyncTaskManager, errorInfoStore);
public AsyncTwitterWrapper asyncTwitterWrapper(Bus bus, SharedPreferencesWrapper preferences,
AsyncTaskManager asyncTaskManager) {
return new AsyncTwitterWrapper(application, bus, preferences, asyncTaskManager);
}
@Provides

View File

@ -33,6 +33,7 @@ import android.widget.AdapterView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter;
import org.mariotaku.twidere.model.AccountId;
import org.mariotaku.twidere.util.EmojiSupportUtils;
import org.mariotaku.twidere.util.widget.StatusTextTokenizer;
import org.mariotaku.twidere.view.iface.IThemeBackgroundTintView;
@ -40,7 +41,7 @@ import org.mariotaku.twidere.view.iface.IThemeBackgroundTintView;
public class ComposeEditText extends AppCompatMultiAutoCompleteTextView implements IThemeBackgroundTintView {
private ComposeAutoCompleteAdapter mAdapter;
private long mAccountId;
private AccountId mAccountId;
public ComposeEditText(final Context context) {
this(context, null);
@ -69,7 +70,7 @@ public class ComposeEditText extends AppCompatMultiAutoCompleteTextView implemen
setSupportBackgroundTintList(color);
}
public void setAccountId(long accountId) {
public void setAccountId(AccountId accountId) {
mAccountId = accountId;
updateAccountId();
}

View File

@ -80,6 +80,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/element_spacing_normal"
android:layout_marginRight="@dimen/element_spacing_normal"
android:layout_marginTop="@dimen/element_spacing_xsmall"
android:layout_toEndOf="@+id/status_info_space"
android:layout_toRightOf="@+id/status_info_space"
android:ellipsize="end"

View File

@ -23,6 +23,7 @@
<style name="Theme.Compat.Base" parent="Theme.AppCompat">
<!-- Window attributes -->
<item name="android:windowBackground">@color/background_color_window_dark</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_dark</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_light</item>
@ -31,6 +32,7 @@
<style name="Theme.Compat.Base.NoActionBar" parent="Theme.AppCompat.NoActionBar">
<!-- Window attributes -->
<item name="android:windowBackground">@color/background_color_window_dark</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_dark</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_light</item>
@ -45,6 +47,7 @@
<style name="Theme.Compat.Base.DialogWhenLarge" parent="Theme.AppCompat.DialogWhenLarge">
<!-- Window attributes -->
<item name="windowNormalBackground">@color/background_color_window_dark</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_dark</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_light</item>
@ -53,6 +56,7 @@
<style name="Theme.Compat.Base.Light" parent="Theme.AppCompat.Light">
<!-- Window attributes -->
<item name="android:windowBackground">@color/background_color_window_light</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_light</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_dark</item>
@ -61,6 +65,7 @@
<style name="Theme.Compat.Base.Light.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Window attributes -->
<item name="android:windowBackground">@color/background_color_window_light</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_light</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_dark</item>
@ -75,6 +80,7 @@
<style name="Theme.Compat.Base.Light.DialogWhenLarge" parent="Theme.AppCompat.Light.DialogWhenLarge">
<!-- Window attributes -->
<item name="windowNormalBackground">@color/background_color_window_light</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:textColorTertiary">@color/tertiary_text_mtrl_light</item>
<item name="android:textColorTertiaryInverse">@color/tertiary_text_mtrl_dark</item>