added some default api configs

bug fixes
This commit is contained in:
Mariotaku Lee 2016-03-31 21:18:44 +08:00
parent ba9518ec22
commit 16201b8142
41 changed files with 594 additions and 291 deletions

View File

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

View File

@ -53,11 +53,8 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
String TWITTER_CONSUMER_SECRET_LEGACY = "JARXkJTfxo0F8MyctYy9bUmrLISjo8vXAHsZHYuk2E";
String TWITTER_CONSUMER_KEY = "i5XtSVfoWjLjKlnrvhiLPMZC0";
String TWITTER_CONSUMER_SECRET = "sQncmZ2atQR6tKbqnnAtqjrECqN8k6FD4p4OoNS0XTDkUz3HGH";
String FANFOU_CONSUMER_KEY = "86d1146dda1d21d59351008a1d1058fd";
String FANFOU_CONSUMER_SECRET = "c00f4b83dbfc52e2ed78a21d4edfc3cc";
String DEFAULT_TWITTER_API_URL_FORMAT = "https://[DOMAIN.]twitter.com/";
String DEFAULT_FANFOU_API_URL_FORMAT = "http://api.fanfou.com/";
String SCHEME_HTTP = "http";
String SCHEME_HTTPS = "https";

View File

@ -7,10 +7,11 @@ import org.mariotaku.twidere.api.fanfou.api.PhotosResources;
import org.mariotaku.twidere.api.fanfou.api.SearchResources;
import org.mariotaku.twidere.api.fanfou.api.StatusesResources;
import org.mariotaku.twidere.api.fanfou.api.UsersResources;
import org.mariotaku.twidere.api.fanfou.api.DirectMessagesResources;
/**
* Created by mariotaku on 16/3/10.
*/
public interface Fanfou extends StatusesResources, SearchResources, UsersResources, PhotosResources,
FriendshipsResources, BlocksResources, FavoritesResources {
FriendshipsResources, BlocksResources, FavoritesResources, DirectMessagesResources {
}

View File

@ -0,0 +1,18 @@
package org.mariotaku.twidere.api.fanfou.api;
import org.mariotaku.restfu.annotation.method.POST;
import org.mariotaku.restfu.annotation.param.Param;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
/**
* Created by mariotaku on 16/3/31.
*/
public interface DirectMessagesResources {
@POST("/direct_messages/new.json")
DirectMessage sendFanfouDirectMessage(@Param("user") String user, @Param("text") String text,
@Param("in_reply_to_id") String inReplyToId)
throws TwitterException;
}

View File

@ -49,22 +49,18 @@ public interface DirectMessagesResources {
ResponseList<DirectMessage> getSentDirectMessages(@Query Paging paging) throws TwitterException;
@POST("/direct_messages/new.json")
@BodyType(BodyType.FORM)
DirectMessage sendDirectMessage(@Param("user_id") String userId, @Param("text") String text)
throws TwitterException;
@POST("/direct_messages/new.json")
@BodyType(BodyType.FORM)
DirectMessage sendDirectMessage(@Param("user_id") String userId, @Param("text") String text,
@Param("media_id") String mediaId) throws TwitterException;
@POST("/direct_messages/new.json")
@BodyType(BodyType.FORM)
DirectMessage sendDirectMessageToScreenName(@Param("screen_name") String screenName, @Param("text") String text)
throws TwitterException;
@POST("/direct_messages/new.json")
@BodyType(BodyType.FORM)
DirectMessage sendDirectMessageToScreenName(@Param("screen_name") String screenName, @Param("text") String text,
@Param("media_id") String mediaId) throws TwitterException;

View File

@ -251,7 +251,7 @@ public interface SharedPreferenceConstants {
String KEY_SAME_OAUTH_SIGNING_URL = "same_oauth_signing_url";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
String KEY_NO_VERSION_SUFFIX = "no_version_suffix";
@Preference(type = INT, hasDefault = true, defaultInt = ParcelableCredentials.AUTH_TYPE_OAUTH)
@Preference(type = INT, hasDefault = true, defaultInt = ParcelableCredentials.AuthType.OAUTH)
String KEY_AUTH_TYPE = "auth_type";
@Preference(type = STRING, hasDefault = true, defaultString = TwidereConstants.TWITTER_CONSUMER_KEY)
String KEY_CONSUMER_KEY = "consumer_key";

View File

@ -35,31 +35,38 @@ import org.mariotaku.twidere.model.util.UserKeyConverter;
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
import org.mariotaku.twidere.model.util.UserKeysConverter;
import org.mariotaku.twidere.model.util.UserKeysCursorFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import java.util.Arrays;
@ParcelablePlease(allFields = false)
@JsonObject
@CursorObject(valuesCreator = true)
@CursorObject(valuesCreator = true, tableInfo = true)
public class ParcelableActivity implements Comparable<ParcelableActivity>, Parcelable {
public static final Creator<ParcelableActivity> CREATOR = new Creator<ParcelableActivity>() {
@Override
public ParcelableActivity createFromParcel(Parcel source) {
ParcelableActivity target = new ParcelableActivity();
ParcelableActivityParcelablePlease.readFromParcel(target, source);
return target;
}
@Override
public ParcelableActivity[] newArray(int size) {
return new ParcelableActivity[size];
}
};
@ParcelableThisPlease
@CursorField(value = Activities._ID, excludeWrite = true)
@CursorField(value = Activities._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
public long _id;
@ParcelableThisPlease
@JsonField(name = "position_key")
@CursorField(Activities.POSITION_KEY)
public long position_key;
@ParcelableThisPlease
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
@CursorField(value = Activities.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey account_key;
@ -165,6 +172,42 @@ public class ParcelableActivity implements Comparable<ParcelableActivity>, Parce
public String status_in_reply_to_user_nickname;
@CursorField(value = Activities.STATUS_QUOTE_SPANS, converter = LoganSquareCursorFieldConverter.class)
public SpanItem[] status_quote_spans;
@CursorField(Activities.STATUS_QUOTE_TEXT_PLAIN)
public String status_quote_text_plain;
@CursorField(Activities.STATUS_QUOTE_SOURCE)
public String status_quote_source;
@CursorField(value = Activities.STATUS_QUOTED_USER_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey status_quoted_user_key;
@CursorField(value = Activities.STATUS_USER_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey status_user_key;
@CursorField(value = Activities.STATUS_SPANS, converter = LoganSquareCursorFieldConverter.class)
public SpanItem[] status_spans;
@CursorField(Activities.STATUS_TEXT_PLAIN)
public String status_text_plain;
@CursorField(Activities.STATUS_SOURCE)
public String status_source;
@CursorField(value = Activities.STATUS_RETWEETED_BY_USER_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey status_retweeted_by_user_key;
@CursorField(Activities.INSERTED_DATE)
public long inserted_date;
@CursorField(Activities.STATUS_ID)
public String status_id;
@CursorField(Activities.STATUS_RETWEET_ID)
public String status_retweet_id;
public transient UserKey[] after_filtered_source_ids;
public transient ParcelableUser[] after_filtered_sources;

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.model;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import com.bluelinelabs.logansquare.annotation.JsonField;
@ -32,6 +33,9 @@ import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by mariotaku on 15/5/26.
*/
@ -41,25 +45,23 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
public class ParcelableCredentials extends ParcelableAccount implements Parcelable {
public static final Creator<ParcelableCredentials> CREATOR = new Creator<ParcelableCredentials>() {
@Override
public ParcelableCredentials createFromParcel(Parcel source) {
ParcelableCredentials target = new ParcelableCredentials();
ParcelableCredentialsParcelablePlease.readFromParcel(target, source);
return target;
}
@Override
public ParcelableCredentials[] newArray(int size) {
return new ParcelableCredentials[size];
}
};
public static final int AUTH_TYPE_OAUTH = 0;
public static final int AUTH_TYPE_XAUTH = 1;
public static final int AUTH_TYPE_BASIC = 2;
public static final int AUTH_TYPE_TWIP_O_MODE = 3;
@ParcelableThisPlease
@JsonField(name = "auth_type")
@CursorField(Accounts.AUTH_TYPE)
@AuthType
public int auth_type;
@ParcelableThisPlease
@JsonField(name = "consumer_key")
@ -133,4 +135,14 @@ public class ParcelableCredentials extends ParcelableAccount implements Parcelab
public void writeToParcel(Parcel dest, int flags) {
ParcelableCredentialsParcelablePlease.writeToParcel(this, dest, flags);
}
@IntDef({AuthType.OAUTH, AuthType.XAUTH, AuthType.BASIC, AuthType.TWIP_O_MODE})
@Retention(RetentionPolicy.SOURCE)
public @interface AuthType {
int OAUTH = 0;
int XAUTH = 1;
int BASIC = 2;
int TWIP_O_MODE = 3;
}
}

View File

@ -37,13 +37,14 @@ import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.model.util.LoganSquareCursorFieldConverter;
import org.mariotaku.twidere.model.util.UserKeyConverter;
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
@CursorObject(valuesCreator = true)
@CursorObject(valuesCreator = true, tableInfo = true)
@JsonObject
@ParcelablePlease
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus>, Cloneable {
@ -68,29 +69,38 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
return new ParcelableStatus[size];
}
};
@CursorField(value = Statuses._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
long _id;
@SuppressWarnings("NullableProblems")
@ParcelableThisPlease
@JsonField(name = "id")
@CursorField(Statuses.STATUS_ID)
@NonNull
public String id;
@SuppressWarnings("NullableProblems")
@ParcelableThisPlease
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
@CursorField(value = Statuses.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
@NonNull
public UserKey account_key;
@ParcelableThisPlease
@JsonField(name = "sort_id")
@CursorField(Statuses.SORT_ID)
public long sort_id = -1;
@ParcelableThisPlease
@JsonField(name = "account_id", typeConverter = UserKeyConverter.class)
@CursorField(value = Statuses.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey account_key;
@ParcelableThisPlease
@JsonField(name = "timestamp")
@CursorField(Statuses.STATUS_TIMESTAMP)
public long timestamp;
@ParcelableThisPlease
@JsonField(name = "position_key")
@CursorField(Statuses.POSITION_KEY)
public long position_key;
@ParcelableThisPlease
@JsonField(name = "timestamp")
@CursorField(Statuses.STATUS_TIMESTAMP)
public long timestamp;
@SuppressWarnings("NullableProblems")
@ParcelableThisPlease
@JsonField(name = "user_id", typeConverter = UserKeyConverter.class)
@CursorField(value = Statuses.USER_KEY, converter = UserKeyCursorFieldConverter.class)
@NonNull
public UserKey user_key;
@ParcelableThisPlease
@JsonField(name = "retweet_id")
@ -266,11 +276,11 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
public String quoted_user_profile_image;
@ParcelableThisPlease
@JsonField(name = "quoted_location")
@CursorField(value = Statuses.LOCATION, converter = ParcelableLocation.Converter.class)
@CursorField(value = Statuses.QUOTED_LOCATION, converter = ParcelableLocation.Converter.class)
public ParcelableLocation quoted_location;
@ParcelableThisPlease
@JsonField(name = "quoted_place_full_name")
@CursorField(value = Statuses.PLACE_FULL_NAME, converter = LoganSquareCursorFieldConverter.class)
@CursorField(value = Statuses.QUOTED_PLACE_FULL_NAME, converter = LoganSquareCursorFieldConverter.class)
public String quoted_place_full_name;
@ParcelableThisPlease
@JsonField(name = "location")
@ -343,9 +353,8 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
@CursorField(Statuses.IN_REPLY_TO_USER_NICKNAME)
public String in_reply_to_user_nickname;
@CursorField(value = Statuses._ID, excludeWrite = true)
long _id;
@CursorField(Statuses.INSERTED_DATE)
public long inserted_date;
public ParcelableStatus() {
}

View File

@ -23,6 +23,9 @@ import android.content.ContentResolver;
import android.net.Uri;
import android.provider.BaseColumns;
import org.mariotaku.twidere.model.ParcelableActivityTableInfo;
import org.mariotaku.twidere.model.ParcelableStatusTableInfo;
@SuppressWarnings("unused")
public interface TwidereDataStore {
@ -855,10 +858,8 @@ public interface TwidereDataStore {
String CARD_NAME = "card_type";
String DEFAULT_SORT_ORDER = STATUS_TIMESTAMP + " DESC, " + SORT_ID + " DESC, " + STATUS_ID
+ " DESC";
String QUOTED_ID = "quoted_id";
String QUOTED_TEXT_PLAIN = "quoted_text_plain";
String QUOTED_TEXT_UNESCAPED = "quoted_text_unescaped";
String QUOTED_MEDIA_JSON = "quoted_media_json";
@ -872,52 +873,32 @@ public interface TwidereDataStore {
String QUOTED_USER_IS_PROTECTED = "quoted_user_is_protected";
String QUOTED_LOCATION = "quoted_location";
String QUOTED_PLACE_FULL_NAME = "quoted_place_full_name";
String RETWEETED = "retweeted";
String EXTRAS = "extras";
String SPANS = "spans";
String QUOTED_SPANS = "quoted_spans";
String POSITION_KEY = "position_key";
String ACCOUNT_COLOR = "account_color";
String USER_COLOR = "user_color";
String QUOTED_USER_COLOR = "quoted_user_color";
String RETWEET_USER_COLOR = "retweet_user_color";
String USER_NICKNAME = "user_nickname";
String QUOTED_USER_NICKNAME = "quoted_user_nickname";
String RETWEET_USER_NICKNAME = "retweet_user_nickname";
String IN_REPLY_TO_USER_NICKNAME = "in_reply_to_user_nickname";
String[] COLUMNS = {_ID, ACCOUNT_KEY, STATUS_ID, SORT_ID, USER_KEY, STATUS_TIMESTAMP,
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_KEY, RETWEETED_BY_USER_NAME,
RETWEETED_BY_USER_SCREEN_NAME, RETWEETED_BY_USER_PROFILE_IMAGE, QUOTED_ID,
QUOTED_TEXT_PLAIN, QUOTED_TEXT_UNESCAPED, QUOTED_TIMESTAMP, QUOTED_SOURCE,
QUOTED_USER_KEY, QUOTED_USER_NAME, QUOTED_USER_SCREEN_NAME, QUOTED_USER_PROFILE_IMAGE,
QUOTED_USER_IS_VERIFIED, QUOTED_USER_IS_PROTECTED, MY_RETWEET_ID, IS_RETWEET,
IS_QUOTE, IS_FAVORITE, IS_PROTECTED, IS_VERIFIED, IS_FOLLOWING, IS_GAP,
IS_POSSIBLY_SENSITIVE, MEDIA_JSON, MENTIONS_JSON, QUOTED_MEDIA_JSON, CARD_NAME, CARD,
PLACE_FULL_NAME, LANG, RETWEETED, QUOTED_LOCATION, QUOTED_PLACE_FULL_NAME, INSERTED_DATE,
EXTRAS, POSITION_KEY, /*spans*/ SPANS, QUOTED_SPANS, /*colors*/ ACCOUNT_COLOR, USER_COLOR,
QUOTED_USER_COLOR, RETWEET_USER_COLOR, /*nicknames*/ USER_NICKNAME,
QUOTED_USER_NICKNAME, RETWEET_USER_NICKNAME, IN_REPLY_TO_USER_NICKNAME};
String[] TYPES = {TYPE_PRIMARY_KEY, TYPE_TEXT_NOT_NULL, TYPE_TEXT_NOT_NULL, TYPE_INT,
TYPE_TEXT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT,
TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_INT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_TEXT, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN, TYPE_BOOLEAN,
TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_BOOLEAN, TYPE_TEXT, TYPE_TEXT, INSERTED_DATE_TYPE, TYPE_TEXT,
TYPE_INT, /*spans*/ TYPE_TEXT, TYPE_TEXT, /*colors*/ TYPE_INT, TYPE_INT, TYPE_INT,
TYPE_INT, /*nicknames*/TYPE_TEXT, TYPE_TEXT, TYPE_TEXT, TYPE_TEXT};
String DEFAULT_SORT_ORDER = STATUS_TIMESTAMP + " DESC, " + SORT_ID + " DESC, " + STATUS_ID
+ " DESC";
String[] COLUMNS = ParcelableStatusTableInfo.COLUMNS;
String[] TYPES = ParcelableStatusTableInfo.TYPES;
}
@ -928,8 +909,8 @@ public interface TwidereDataStore {
String STATUS_ID = "status_id";
String STATUS_RETWEET_ID = "status_retweet_id";
String STATUS_USER_KEY = "status_user_id";
String STATUS_RETWEETED_BY_USER_ID = "status_retweeted_by_user_id";
String STATUS_QUOTED_USER_ID = "status_quoted_user_id";
String STATUS_RETWEETED_BY_USER_KEY = "status_retweeted_by_user_id";
String STATUS_QUOTED_USER_KEY = "status_quoted_user_id";
String STATUS_SOURCE = "status_source";
String STATUS_QUOTE_SOURCE = "status_quote_source";
String STATUS_TEXT_PLAIN = "status_text_plain";
@ -965,22 +946,8 @@ public interface TwidereDataStore {
String POSITION_KEY = "position_key";
String[] COLUMNS = {_ID, ACCOUNT_KEY, ACTION, TIMESTAMP, STATUS_ID, STATUS_USER_KEY,
STATUS_RETWEETED_BY_USER_ID, STATUS_QUOTED_USER_ID, STATUS_SOURCE, STATUS_QUOTE_SOURCE,
STATUS_TEXT_PLAIN, STATUS_QUOTE_TEXT_PLAIN, STATUS_SPANS, STATUS_QUOTE_SPANS,
IS_GAP, MIN_SORT_POSITION, MAX_SORT_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, MIN_REQUEST_POSITION,
MAX_REQUEST_POSITION, POSITION_KEY, ACCOUNT_COLOR, STATUS_USER_COLOR,
STATUS_QUOTED_USER_COLOR, STATUS_RETWEET_USER_COLOR, STATUS_USER_NICKNAME,
STATUS_QUOTED_USER_NICKNAME, STATUS_RETWEET_USER_NICKNAME,
STATUS_IN_REPLY_TO_USER_NICKNAME};
String[] TYPES = {TYPE_PRIMARY_KEY, 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, TYPE_TEXT,
TYPE_TEXT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_TEXT,
TYPE_TEXT, TYPE_TEXT};
String[] COLUMNS = ParcelableActivityTableInfo.COLUMNS;
String[] TYPES = ParcelableActivityTableInfo.TYPES;
String DEFAULT_SORT_ORDER = TIMESTAMP + " DESC";

View File

@ -78,7 +78,7 @@ dependencies {
androidTestApt 'com.bluelinelabs:logansquare-compiler:1.3.7'
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.2'
apt 'com.google.dagger:dagger-compiler:2.1'
apt "com.github.mariotaku.ObjectCursor:processor:0.9.6"
apt "com.github.mariotaku.ObjectCursor:processor:0.9.7"
compile('com.github.mariotaku:app-theme-engine:1efc6237e1@aar') {
transitive = true
@ -148,7 +148,7 @@ dependencies {
compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.14'
compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view:0.9.14'
compile 'com.github.mariotaku.SQLiteQB:library:0.9.6'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.6'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.7'
compile 'com.github.mariotaku:MultiValueSwitch:0.9.4'
compile 'com.github.mariotaku:AbstractTask:0.9'
}

View File

@ -0,0 +1,52 @@
[
{
"name": "Twidere",
"localized_name": "@string/provider_default",
"api_url_format": "https://[DOMAIN.]twitter.com/",
"auth_type": "oauth",
"same_oauth_url": true,
"no_version_suffix": false,
"consumer_key": "i5XtSVfoWjLjKlnrvhiLPMZC0",
"consumer_secret": "sQncmZ2atQR6tKbqnnAtqjrECqN8k6FD4p4OoNS0XTDkUz3HGH"
},
{
"name": "Fanfou",
"localized_name": "@string/provider_fanfou",
"api_url_format": "http://api.fanfou.com/",
"auth_type": "oauth",
"same_oauth_url": true,
"no_version_suffix": true,
"consumer_key": "86d1146dda1d21d59351008a1d1058fd",
"consumer_secret": "c00f4b83dbfc52e2ed78a21d4edfc3cc"
},
{
"name": "Quitter.se",
"localized_name": "@string/provider_quitter_se",
"api_url_format": "https://quitter.se/api/",
"auth_type": "oauth",
"same_oauth_url": true,
"no_version_suffix": true,
"consumer_key": "3584cd86bd8e04948be15650acbd0d59",
"consumer_secret": "84a39eff81c0a0ecbfba5239d25c0367"
},
{
"name": "LoadAverage.org",
"localized_name": "@string/provider_loadaverage_org",
"api_url_format": "https://loadaverage.org/api/",
"auth_type": "oauth",
"same_oauth_url": true,
"no_version_suffix": true,
"consumer_key": "b6ec1e0db2664a2c8672fd85d0a247ae",
"consumer_secret": "267ab1bb064b8268283ca38835d1f45a"
},
{
"name": "GNU Social.net",
"localized_name": "@string/provider_gnusocial_net",
"api_url_format": "https://gnusocial.net/api/",
"auth_type": "oauth",
"same_oauth_url": true,
"no_version_suffix": true,
"consumer_key": "0d3f84140b97cefec01e9583d88dc760",
"consumer_secret": "da3b203278ab34eadf7e578eb2f6f9d7"
}
]

View File

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

View File

@ -66,16 +66,16 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
public static int getCheckedAuthType(final int checkedId) {
switch (checkedId) {
case R.id.xauth: {
return ParcelableCredentials.AUTH_TYPE_XAUTH;
return ParcelableCredentials.AuthType.XAUTH;
}
case R.id.basic: {
return ParcelableCredentials.AUTH_TYPE_BASIC;
return ParcelableCredentials.AuthType.BASIC;
}
case R.id.twip_o: {
return ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE;
return ParcelableCredentials.AuthType.TWIP_O_MODE;
}
default: {
return ParcelableCredentials.AUTH_TYPE_OAUTH;
return ParcelableCredentials.AuthType.OAUTH;
}
}
}
@ -83,12 +83,12 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
@Override
public void onCheckedChanged(final RadioGroup group, final int checkedId) {
final int authType = getCheckedAuthType(checkedId);
final boolean isOAuth = authType == ParcelableCredentials.AUTH_TYPE_OAUTH || authType == ParcelableCredentials.AUTH_TYPE_XAUTH;
final boolean isOAuth = authType == ParcelableCredentials.AuthType.OAUTH || authType == ParcelableCredentials.AuthType.XAUTH;
mEditSameOAuthSigningUrl.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
mEditConsumerKey.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
mEditConsumerSecret.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
if (!mEditNoVersionSuffixChanged) {
mEditNoVersionSuffix.setChecked(authType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
mEditNoVersionSuffix.setChecked(authType == ParcelableCredentials.AuthType.TWIP_O_MODE);
}
}
@ -193,7 +193,7 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
final SharedPreferences pref = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
final String prefApiUrlFormat = getNonEmptyString(pref, KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT);
final int prefAuthType = pref.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_OAUTH);
final int prefAuthType = pref.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AuthType.OAUTH);
final boolean prefSameOAuthSigningUrl = pref.getBoolean(KEY_SAME_OAUTH_SIGNING_URL, false);
final boolean prefNoVersionSuffix = pref.getBoolean(KEY_NO_VERSION_SUFFIX, false);
final String prefConsumerKey = getNonEmptyString(pref, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY);
@ -227,10 +227,10 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
mEditConsumerKey.setText(consumerKey);
mEditConsumerSecret.setText(consumerSecret);
mButtonOAuth.setChecked(authType == ParcelableCredentials.AUTH_TYPE_OAUTH);
mButtonXAuth.setChecked(authType == ParcelableCredentials.AUTH_TYPE_XAUTH);
mButtonBasic.setChecked(authType == ParcelableCredentials.AUTH_TYPE_BASIC);
mButtonTWIPOMode.setChecked(authType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
mButtonOAuth.setChecked(authType == ParcelableCredentials.AuthType.OAUTH);
mButtonXAuth.setChecked(authType == ParcelableCredentials.AuthType.XAUTH);
mButtonBasic.setChecked(authType == ParcelableCredentials.AuthType.BASIC);
mButtonTWIPOMode.setChecked(authType == ParcelableCredentials.AuthType.TWIP_O_MODE);
if (mEditAuthType.getCheckedRadioButtonId() == -1) {
mButtonOAuth.setChecked(true);
}
@ -239,13 +239,13 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
private int getAuthTypeId(final int authType) {
switch (authType) {
case ParcelableCredentials.AUTH_TYPE_XAUTH: {
case ParcelableCredentials.AuthType.XAUTH: {
return R.id.xauth;
}
case ParcelableCredentials.AUTH_TYPE_BASIC: {
case ParcelableCredentials.AuthType.BASIC: {
return R.id.basic;
}
case ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE: {
case ParcelableCredentials.AuthType.TWIP_O_MODE: {
return R.id.twip_o;
}
default: {
@ -270,11 +270,12 @@ public class APIEditorActivity extends BaseActivity implements OnCheckedChangeLi
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
mAPIConfigs = CustomAPIConfig.listDefault(getContext());
final AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(getContext());
final Context context = getContext();
mAPIConfigs = CustomAPIConfig.listDefault(context);
final AlertDialogWrapper.Builder builder = new AlertDialogWrapper.Builder(context);
String[] entries = new String[mAPIConfigs.length];
for (int i = 0, mAPIConfigsLength = mAPIConfigs.length; i < mAPIConfigsLength; i++) {
entries[i] = mAPIConfigs[i].getName();
entries[i] = mAPIConfigs[i].getLocalizedName(context);
}
builder.setItems(entries, this);
return builder.create();

View File

@ -102,7 +102,7 @@ public class AccountSelectorActivity extends BaseActivity implements
final String[] whereArgs;
if (isOAuthOnly()) {
where = Expression.equalsArgs(Accounts.AUTH_TYPE).getSQL();
whereArgs = new String[]{String.valueOf(ParcelableCredentials.AUTH_TYPE_OAUTH)};
whereArgs = new String[]{String.valueOf(ParcelableCredentials.AuthType.OAUTH)};
} else {
where = null;
whereArgs = null;

View File

@ -50,11 +50,13 @@ import android.support.v4.widget.DrawerLayoutAccessor;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.SparseIntArray;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
@ -97,9 +99,11 @@ import org.mariotaku.twidere.util.MultiSelectEventHandler;
import org.mariotaku.twidere.util.ReadStateManager;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereMathUtils;
import org.mariotaku.twidere.util.TwidereViewUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.ExtendedRelativeLayout;
import org.mariotaku.twidere.view.ExtendedViewPager;
import org.mariotaku.twidere.view.HomeDrawerLayout;
import org.mariotaku.twidere.view.TabPagerIndicator;
import java.util.Collections;
@ -122,7 +126,7 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag
private Toolbar mToolbar;
private View mWindowOverlay;
private TabPagerIndicator mTabIndicator;
private DrawerLayout mDrawerLayout;
private HomeDrawerLayout mDrawerLayout;
private View mEmptyTabHint;
private FloatingActionButton mActionsButton;
private ExtendedRelativeLayout mHomeContent;
@ -666,7 +670,7 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag
super.onContentChanged();
mTabIndicator = (TabPagerIndicator) findViewById(R.id.main_tabs);
mToolbar = (Toolbar) findViewById(R.id.action_bar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.home_menu);
mDrawerLayout = (HomeDrawerLayout) findViewById(R.id.home_menu);
mViewPager = (ExtendedViewPager) findViewById(R.id.main_pager);
mEmptyTabHint = findViewById(R.id.empty_tab_hint);
mActionsButton = (FloatingActionButton) findViewById(R.id.actions_button);
@ -861,6 +865,20 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow_start, GravityCompat.START);
mDrawerLayout.addDrawerListener(mDrawerToggle);
mDrawerLayout.addDrawerListener(this);
mDrawerLayout.setShouldDisableDecider(new HomeDrawerLayout.ShouldDisableDecider() {
@Override
public boolean shouldDisableTouch(MotionEvent e) {
final Fragment fragment = getLeftDrawerFragment();
if (fragment instanceof AccountsDashboardFragment) {
RecyclerView accountsSelector = ((AccountsDashboardFragment) fragment)
.getAccountsSelector();
if (accountsSelector != null) {
return TwidereViewUtils.hitView(e.getRawX(), e.getRawY(), accountsSelector);
}
}
return false;
}
});
}
private void showDataProfilingRequest() {
@ -970,7 +988,7 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag
true, ReadPositionTag.HOME_TIMELINE, accountKeys);
final long position = mReadStateManager.getPosition(tagWithAccounts);
final int count = DataStoreUtils.getStatusesCount(mContext, Statuses.CONTENT_URI,
position, Statuses.STATUS_TIMESTAMP, accountKeys);
position, Statuses.STATUS_TIMESTAMP, true, accountKeys);
result.put(i, count);
publishProgress(new TabBadge(i, count));
break;

View File

@ -140,12 +140,12 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
case REQUEST_EDIT_API: {
if (resultCode == RESULT_OK) {
mAPIUrlFormat = data.getStringExtra(Accounts.API_URL_FORMAT);
mAuthType = data.getIntExtra(Accounts.AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_OAUTH);
mAuthType = data.getIntExtra(Accounts.AUTH_TYPE, ParcelableCredentials.AuthType.OAUTH);
mSameOAuthSigningUrl = data.getBooleanExtra(Accounts.SAME_OAUTH_SIGNING_URL, false);
mNoVersionSuffix = data.getBooleanExtra(Accounts.NO_VERSION_SUFFIX, false);
mConsumerKey = data.getStringExtra(Accounts.CONSUMER_KEY);
mConsumerSecret = data.getStringExtra(Accounts.CONSUMER_SECRET);
final boolean isTwipOMode = mAuthType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE;
final boolean isTwipOMode = mAuthType == ParcelableCredentials.AuthType.TWIP_O_MODE;
mUsernamePasswordContainer.setVisibility(isTwipOMode ? View.GONE : View.VISIBLE);
mSignInSignUpContainer.setOrientation(isTwipOMode ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
}
@ -240,7 +240,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
break;
}
case R.id.open_in_browser: {
if (mAuthType != ParcelableCredentials.AUTH_TYPE_OAUTH || mTask != null
if (mAuthType != ParcelableCredentials.AuthType.OAUTH || mTask != null
&& mTask.getStatus() == AsyncTask.Status.RUNNING) return false;
saveEditedText();
final Intent intent = new Intent(this, BrowserSignInActivity.class);
@ -258,7 +258,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
public boolean onPrepareOptionsMenu(final Menu menu) {
final MenuItem itemBrowser = menu.findItem(R.id.open_in_browser);
if (itemBrowser != null) {
final boolean is_oauth = mAuthType == ParcelableCredentials.AUTH_TYPE_OAUTH;
final boolean is_oauth = mAuthType == ParcelableCredentials.AuthType.OAUTH;
itemBrowser.setVisible(is_oauth);
itemBrowser.setEnabled(is_oauth);
}
@ -304,7 +304,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
mAPIChangeTimestamp = savedInstanceState.getLong(EXTRA_API_LAST_CHANGE);
}
final boolean isTwipOMode = mAuthType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE;
final boolean isTwipOMode = mAuthType == ParcelableCredentials.AuthType.TWIP_O_MODE;
mUsernamePasswordContainer.setVisibility(isTwipOMode ? View.GONE : View.VISIBLE);
mSignInSignUpContainer.setOrientation(isTwipOMode ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
@ -373,7 +373,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final long apiLastChange = mPreferences.getLong(KEY_API_LAST_CHANGE, mAPIChangeTimestamp);
final boolean defaultApiChanged = apiLastChange != mAPIChangeTimestamp;
final String apiUrlFormat = Utils.getNonEmptyString(mPreferences, KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT);
final int authType = mPreferences.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_OAUTH);
final int authType = mPreferences.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AuthType.OAUTH);
final boolean sameOAuthSigningUrl = mPreferences.getBoolean(KEY_SAME_OAUTH_SIGNING_URL, false);
final boolean noVersionSuffix = mPreferences.getBoolean(KEY_NO_VERSION_SUFFIX, false);
final String consumerKey = Utils.getNonEmptyString(mPreferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY);
@ -403,7 +403,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
private void setSignInButton() {
mSignInButton.setEnabled(mEditPassword.getText().length() > 0 && mEditUsername.getText().length() > 0
|| mAuthType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
|| mAuthType == ParcelableCredentials.AuthType.TWIP_O_MODE);
}
void onSignInResult(final SignInResponse result) {
@ -605,7 +605,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final User user = twitter.verifyCredentials();
final int color = analyseUserProfileColor(user);
return new SignInResponse(Utils.isUserLoggedIn(context, user.getId()), auth, user,
ParcelableCredentials.AUTH_TYPE_OAUTH, color, apiUrlFormat, sameOauthSigningUrl,
ParcelableCredentials.AuthType.OAUTH, color, apiUrlFormat, sameOauthSigningUrl,
noVersionSuffix, detectAccountType(twitter, user));
} catch (final TwitterException e) {
return new SignInResponse(false, false, e);
@ -659,13 +659,13 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
protected SignInResponse doInBackground(final Object... params) {
try {
switch (authType) {
case ParcelableCredentials.AUTH_TYPE_OAUTH:
case ParcelableCredentials.AuthType.OAUTH:
return authOAuth();
case ParcelableCredentials.AUTH_TYPE_XAUTH:
case ParcelableCredentials.AuthType.XAUTH:
return authxAuth();
case ParcelableCredentials.AUTH_TYPE_BASIC:
case ParcelableCredentials.AuthType.BASIC:
return authBasic();
case ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE:
case ParcelableCredentials.AuthType.TWIP_O_MODE:
return authTwipOMode();
}
return authOAuth();
@ -690,7 +690,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final String userId = accessToken.getUserId();
if (userId == null) return new SignInResponse(false, false, null);
return getOAuthSignInResponse(activity, accessToken, userId,
ParcelableCredentials.AUTH_TYPE_OAUTH);
ParcelableCredentials.AuthType.OAUTH);
}
private SignInResponse authxAuth() throws TwitterException {
@ -704,7 +704,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final String userId = accessToken.getUserId();
if (userId == null) return new SignInResponse(false, false, null);
return getOAuthSignInResponse(activity, accessToken, userId,
ParcelableCredentials.AUTH_TYPE_XAUTH);
ParcelableCredentials.AuthType.XAUTH);
}
private SignInResponse authBasic() throws TwitterException, AuthenticationException {
@ -964,7 +964,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final String apiUrlFormat, final boolean noVersionSuffix,
final Pair<String, String> accountType) {
this(alreadyLoggedIn, true, null, basicUsername, basicPassword, null, user,
ParcelableCredentials.AUTH_TYPE_BASIC, color, apiUrlFormat, false,
ParcelableCredentials.AuthType.BASIC, color, apiUrlFormat, false,
noVersionSuffix, accountType);
}
@ -972,7 +972,7 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
final String apiUrlFormat, final boolean noVersionSuffix,
final Pair<String, String> accountType) {
this(alreadyLoggedIn, true, null, null, null, null, user,
ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE, color, apiUrlFormat, false,
ParcelableCredentials.AuthType.TWIP_O_MODE, color, apiUrlFormat, false,
noVersionSuffix, accountType);
}
@ -980,20 +980,20 @@ public class SignInActivity extends BaseActivity implements OnClickListener, Tex
if (user == null) return null;
final ContentValues values;
switch (authType) {
case ParcelableCredentials.AUTH_TYPE_BASIC: {
case ParcelableCredentials.AuthType.BASIC: {
values = new ContentValues();
values.put(Accounts.BASIC_AUTH_USERNAME, basicUsername);
values.put(Accounts.BASIC_AUTH_PASSWORD, basicPassword);
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_BASIC);
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AuthType.BASIC);
break;
}
case ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE: {
case ParcelableCredentials.AuthType.TWIP_O_MODE: {
values = new ContentValues();
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AuthType.TWIP_O_MODE);
break;
}
case ParcelableCredentials.AUTH_TYPE_OAUTH:
case ParcelableCredentials.AUTH_TYPE_XAUTH: {
case ParcelableCredentials.AuthType.OAUTH:
case ParcelableCredentials.AuthType.XAUTH: {
values = new ContentValues();
final OAuthToken accessToken = oauth.getOauthToken();
values.put(Accounts.OAUTH_TOKEN, accessToken.getOauthToken());

View File

@ -33,6 +33,7 @@ import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuInflater;
@ -43,6 +44,7 @@ import com.squareup.otto.Subscribe;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.abstask.library.TaskStarter;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration;
@ -341,6 +343,10 @@ public abstract class AbsActivitiesFragment extends AbsContentListRecyclerViewFr
public void onGapClick(GapViewHolder holder, int position) {
final ParcelableActivitiesAdapter adapter = getAdapter();
final ParcelableActivity activity = adapter.getActivity(position);
if (BuildConfig.DEBUG) {
Log.v(LOGTAG, "Load activity gap " + activity);
}
if (activity == null) return;
final UserKey[] accountIds = {activity.account_key};
final String[] maxIds = {activity.min_position};
final long[] maxSortIds = {activity.min_sort_position};

View File

@ -33,6 +33,7 @@ import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuInflater;
@ -43,6 +44,7 @@ import com.squareup.otto.Subscribe;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.abstask.library.TaskStarter;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
@ -330,6 +332,9 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
public void onGapClick(GapViewHolder holder, int position) {
final ParcelableStatusesAdapter adapter = getAdapter();
final ParcelableStatus status = adapter.getStatus(position);
if (BuildConfig.DEBUG) {
Log.v(LOGTAG, "Load activity gap " + status);
}
if (status == null) return;
final UserKey[] accountIds = {status.account_key};
final String[] maxIds = {status.id};

View File

@ -719,6 +719,10 @@ public class AccountsDashboardFragment extends BaseSupportFragment implements Lo
mAccountProfileContainer.setPadding(0, top, 0, 0);
}
public RecyclerView getAccountsSelector() {
return mAccountsSelector;
}
static class AccountProfileImageViewHolder extends ViewHolder implements OnClickListener {
private final AccountSelectorAdapter adapter;

View File

@ -189,7 +189,7 @@ public abstract class CursorActivitiesFragment extends AbsActivitiesFragment {
@Override
public void onLoadMoreContents(@IndicatorPosition int position) {
// Only supports load from end, skip START flag
if ((position & IndicatorPosition.START) != 0) return;
if ((position & IndicatorPosition.START) != 0 || isRefreshing()) return;
super.onLoadMoreContents(position);
if (position == 0) return;
getActivities(new SimpleRefreshTaskParam() {

View File

@ -149,7 +149,7 @@ public abstract class ParcelableStatusesFragment extends AbsStatusesFragment {
@Override
public void onLoadMoreContents(int position) {
// Only supports load from end, skip START flag
if ((position & IndicatorPosition.START) != 0) return;
if ((position & IndicatorPosition.START) != 0 || isRefreshing()) return;
super.onLoadMoreContents(position);
if (position == 0) return;
final ParcelableStatusesAdapter adapter = getAdapter();

View File

@ -1777,7 +1777,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
Utils.setLastSeen(context, userKey, System.currentTimeMillis());
}
Utils.updateRelationship(context, mAccountKey, userKey, relationship);
return SingleResponse.getInstance(new UserRelationship(mAccountKey, relationship, isFiltering));
return SingleResponse.getInstance(new UserRelationship(mAccountKey, userKey,
relationship, isFiltering));
} catch (final TwitterException e) {
return SingleResponse.getInstance(e);
}
@ -1793,16 +1794,16 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
boolean filtering;
boolean can_dm;
public UserRelationship(@NonNull UserKey accountKey, @NonNull Relationship relationship,
boolean filtering) {
super(accountKey, relationship.getTargetUserId(), relationship);
public UserRelationship(@NonNull UserKey accountKey, @NonNull UserKey userKey,
@NonNull Relationship relationship, boolean filtering) {
super(relationship, accountKey, userKey);
this.filtering = filtering;
this.can_dm = relationship.canSourceDMTarget();
}
public UserRelationship(@NonNull ParcelableUser user, boolean filtering) {
this.account_key = user.account_key;
this.user_id = user.key.getId();
this.user_key = user.key;
this.filtering = filtering;
if (user.extras != null) {
this.following = user.is_following;
@ -1817,8 +1818,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
if (!account_key.equals(user.account_key)) {
return false;
}
return (user.extras != null && TextUtils.equals(user_id, user.extras.unique_id))
|| TextUtils.equals(user_id, user.key.getId());
return (user.extras != null && TextUtils.equals(user_key.getId(), user.extras.unique_id))
|| TextUtils.equals(user_key.getId(), user.key.getId());
}
}

View File

@ -141,14 +141,14 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
if (mExtras != null && UserFragment.Referral.SELF_PROFILE.equals(mExtras.getString(EXTRA_REFERRAL))) {
twitterUser = twitter.verifyCredentials();
} else {
String mProfileUrl = null;
String profileUrl = null;
if (mExtras != null) {
mProfileUrl = mExtras.getString(EXTRA_PROFILE_URL);
profileUrl = mExtras.getString(EXTRA_PROFILE_URL);
}
if (TwitterAPIFactory.isStatusNetCredentials(credentials) && mUserKey != null &&
mProfileUrl != null && !TextUtils.equals(credentials.account_key.getHost(),
profileUrl != null && !TextUtils.equals(credentials.account_key.getHost(),
mUserKey.getHost())) {
twitterUser = twitter.showExternalProfile(mProfileUrl);
twitterUser = twitter.showExternalProfile(profileUrl);
} else {
final String id = mUserKey != null ? mUserKey.getId() : null;
twitterUser = TwitterWrapper.tryShowUser(twitter, id, mScreenName,

View File

@ -5,19 +5,22 @@ import android.support.annotation.NonNull;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.api.twitter.model.Relationship;
import org.mariotaku.twidere.model.util.UserKeyCursorFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataProvider;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
/**
* Created by mariotaku on 16/2/1.
*/
@CursorObject(valuesCreator = true)
@CursorObject(valuesCreator = true, tableInfo = true)
public class CachedRelationship {
@CursorField(CachedRelationships.ACCOUNT_KEY)
@CursorField(value = CachedRelationships.ACCOUNT_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey account_key;
@CursorField(CachedRelationships.USER_KEY)
public String user_id;
@CursorField(value = CachedRelationships.USER_KEY, converter = UserKeyCursorFieldConverter.class)
public UserKey user_key;
@CursorField(CachedRelationships.FOLLOWING)
public boolean following;
@ -37,13 +40,16 @@ public class CachedRelationship {
@CursorField(CachedRelationships.RETWEET_ENABLED)
public boolean retweet_enabled;
@CursorField(value = CachedRelationships._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
public long _id;
public CachedRelationship() {
}
public CachedRelationship(UserKey accountId, String userId, @NonNull Relationship relationship) {
account_key = accountId;
user_id = userId;
public CachedRelationship(@NonNull Relationship relationship, @NonNull UserKey accountKey, @NonNull UserKey userKey) {
account_key = accountKey;
user_key = userKey;
following = relationship.isSourceFollowingTarget();
followed_by = relationship.isSourceFollowedByTarget();
blocking = relationship.isSourceBlockingTarget();

View File

@ -1,24 +1,50 @@
package org.mariotaku.twidere.model;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.JsonSerializer;
import org.mariotaku.twidere.util.Utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Created by mariotaku on 16/3/12.
*/
public class CustomAPIConfig implements Constants {
@JsonObject
public final class CustomAPIConfig implements Constants {
@JsonField(name = "name")
String name;
@JsonField(name = "localized_name")
String localizedName;
@JsonField(name = "api_url_format")
String apiUrlFormat;
@ParcelableCredentials.AuthType
@JsonField(name = "auth_type", typeConverter = AuthTypeConverter.class)
int authType;
@JsonField(name = "same_oauth_url")
boolean sameOAuthUrl;
@JsonField(name = "no_version_suffix")
boolean noVersionSuffix;
@JsonField(name = "consumer_key")
String consumerKey;
@JsonField(name = "consumer_secret")
String consumerSecret;
CustomAPIConfig() {
}
public CustomAPIConfig(String name, String apiUrlFormat, int authType, boolean sameOAuthUrl,
boolean noVersionSuffix, String consumerKey, String consumerSecret) {
this.name = name;
@ -34,6 +60,16 @@ public class CustomAPIConfig implements Constants {
return name;
}
public String getLocalizedName(Context context) {
if (localizedName == null) return name;
final Resources res = context.getResources();
int id = res.getIdentifier(localizedName, "string", context.getPackageName());
if (id != 0) {
return res.getString(id);
}
return name;
}
public String getApiUrlFormat() {
return apiUrlFormat;
}
@ -60,13 +96,66 @@ public class CustomAPIConfig implements Constants {
@NonNull
public static CustomAPIConfig[] listDefault(@NonNull Context context) {
CustomAPIConfig[] list = new CustomAPIConfig[2];
list[0] = new CustomAPIConfig(context.getString(R.string.provider_default),
DEFAULT_TWITTER_API_URL_FORMAT, ParcelableCredentials.AUTH_TYPE_OAUTH, true, false,
TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET);
list[1] = new CustomAPIConfig(context.getString(R.string.provider_fanfou),
DEFAULT_FANFOU_API_URL_FORMAT, ParcelableCredentials.AUTH_TYPE_OAUTH, true, true,
FANFOU_CONSUMER_KEY, FANFOU_CONSUMER_SECRET);
return list;
final AssetManager assets = context.getAssets();
InputStream is = null;
try {
is = assets.open("data/default_api_configs.json");
List<CustomAPIConfig> configList = JsonSerializer.parseList(is, CustomAPIConfig.class);
if (configList == null) return listBuiltin(context);
return configList.toArray(new CustomAPIConfig[configList.size()]);
} catch (IOException e) {
return listBuiltin(context);
} finally {
Utils.closeSilently(is);
}
}
public static CustomAPIConfig[] listBuiltin(@NonNull Context context) {
return new CustomAPIConfig[]{new CustomAPIConfig(context.getString(R.string.provider_default),
DEFAULT_TWITTER_API_URL_FORMAT, ParcelableCredentials.AuthType.OAUTH, true, false,
TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET)};
}
static class AuthTypeConverter extends StringBasedTypeConverter<Integer> {
@Override
@ParcelableCredentials.AuthType
public Integer getFromString(String string) {
if (string == null) return ParcelableCredentials.AuthType.OAUTH;
switch (string) {
case "oauth": {
return ParcelableCredentials.AuthType.OAUTH;
}
case "xauth": {
return ParcelableCredentials.AuthType.XAUTH;
}
case "basic": {
return ParcelableCredentials.AuthType.BASIC;
}
case "twip_o_mode": {
return ParcelableCredentials.AuthType.TWIP_O_MODE;
}
}
return ParcelableCredentials.AuthType.OAUTH;
}
@Override
public String convertToString(@ParcelableCredentials.AuthType Integer object) {
if (object == null) return "oauth";
switch (object) {
case ParcelableCredentials.AuthType.OAUTH: {
return "oauth";
}
case ParcelableCredentials.AuthType.XAUTH: {
return "xauth";
}
case ParcelableCredentials.AuthType.BASIC: {
return "basic";
}
case ParcelableCredentials.AuthType.TWIP_O_MODE: {
return "twip_o_mode";
}
}
return "oauth";
}
}
}

View File

@ -47,7 +47,8 @@ public class TabArguments implements TwidereConstants {
} else if (accountId != null) {
final long id = NumberUtils.toLong(accountId, Long.MIN_VALUE);
if (id != Long.MIN_VALUE && id <= 0) {
bundle.putParcelableArray(EXTRA_ACCOUNT_KEYS, new UserKey[0]);
// account_id = -1, means no account selected
bundle.putParcelableArray(EXTRA_ACCOUNT_KEYS, null);
return;
}
bundle.putParcelableArray(EXTRA_ACCOUNT_KEYS, new UserKey[]{UserKey.valueOf(accountId)});

View File

@ -17,8 +17,8 @@ import org.mariotaku.twidere.util.DataStoreUtils;
public class ParcelableCredentialsUtils {
public static boolean isOAuth(int authType) {
switch (authType) {
case ParcelableCredentials.AUTH_TYPE_OAUTH:
case ParcelableCredentials.AUTH_TYPE_XAUTH: {
case ParcelableCredentials.AuthType.OAUTH:
case ParcelableCredentials.AuthType.XAUTH: {
return true;
}
}

View File

@ -117,12 +117,12 @@ public class DefaultAPIPreference extends DialogPreference implements Constants,
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
final int authType = APIEditorActivity.getCheckedAuthType(checkedId);
final boolean isOAuth = authType == ParcelableCredentials.AUTH_TYPE_OAUTH || authType == ParcelableCredentials.AUTH_TYPE_XAUTH;
final boolean isOAuth = authType == ParcelableCredentials.AuthType.OAUTH || authType == ParcelableCredentials.AuthType.XAUTH;
mEditSameOAuthSigningUrl.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
mEditConsumerKey.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
mEditConsumerSecret.setVisibility(isOAuth ? View.VISIBLE : View.GONE);
if (!mEditNoVersionSuffixChanged) {
mEditNoVersionSuffix.setChecked(authType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
mEditNoVersionSuffix.setChecked(authType == ParcelableCredentials.AuthType.TWIP_O_MODE);
}
}
});
@ -144,7 +144,7 @@ public class DefaultAPIPreference extends DialogPreference implements Constants,
} else {
final SharedPreferences preferences = preference.getSharedPreferences();
final String apiUrlFormat = preferences.getString(KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT);
final int authType = preferences.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_OAUTH);
final int authType = preferences.getInt(KEY_AUTH_TYPE, ParcelableCredentials.AuthType.OAUTH);
final boolean sameOAuthSigningUrl = preferences.getBoolean(KEY_SAME_OAUTH_SIGNING_URL, true);
final boolean noVersionSuffix = preferences.getBoolean(KEY_NO_VERSION_SUFFIX, false);
final String consumerKey = trim(preferences.getString(KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY));
@ -201,10 +201,10 @@ public class DefaultAPIPreference extends DialogPreference implements Constants,
mEditConsumerKey.setText(consumerKey);
mEditConsumerSecret.setText(consumerSecret);
mButtonOAuth.setChecked(authType == ParcelableCredentials.AUTH_TYPE_OAUTH);
mButtonxAuth.setChecked(authType == ParcelableCredentials.AUTH_TYPE_XAUTH);
mButtonBasic.setChecked(authType == ParcelableCredentials.AUTH_TYPE_BASIC);
mButtonTwipOMode.setChecked(authType == ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
mButtonOAuth.setChecked(authType == ParcelableCredentials.AuthType.OAUTH);
mButtonxAuth.setChecked(authType == ParcelableCredentials.AuthType.XAUTH);
mButtonBasic.setChecked(authType == ParcelableCredentials.AuthType.BASIC);
mButtonTwipOMode.setChecked(authType == ParcelableCredentials.AuthType.TWIP_O_MODE);
if (mEditAuthType.getCheckedRadioButtonId() == -1) {
mButtonOAuth.setChecked(true);
}

View File

@ -58,6 +58,7 @@ import org.mariotaku.twidere.api.fanfou.model.PhotoStatusUpdate;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.TwitterUpload;
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
import org.mariotaku.twidere.api.twitter.model.ErrorInfo;
import org.mariotaku.twidere.api.twitter.model.MediaUploadResponse;
import org.mariotaku.twidere.api.twitter.model.NewMediaMetadata;
@ -454,30 +455,42 @@ public class BackgroundOperationService extends IntentService implements Constan
final String recipientId,
final String text,
final String imageUri) {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(this, accountKey, true, true);
final TwitterUpload twitterUpload = TwitterAPIFactory.getTwitterInstance(this, accountKey, true, true, TwitterUpload.class);
final ParcelableCredentials credentials = ParcelableCredentialsUtils.getCredentials(this,
accountKey);
if (credentials == null) return SingleResponse.getInstance();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(this, credentials, true, true);
final TwitterUpload twitterUpload = TwitterAPIFactory.getTwitterInstance(this, credentials,
true, true, TwitterUpload.class);
if (twitter == null || twitterUpload == null) return SingleResponse.getInstance();
try {
final ParcelableDirectMessage directMessage;
if (imageUri != null) {
final String path = getImagePathFromUri(this, Uri.parse(imageUri));
if (path == null) throw new FileNotFoundException();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
final File file = new File(path);
BitmapUtils.downscaleImageIfNeeded(file, 100);
final ContentLengthInputStream is = new ContentLengthInputStream(file);
is.setReadListener(new MessageMediaUploadListener(this, mNotificationManager, builder, text));
// final MediaUploadResponse uploadResp = twitter.uploadMedia(file.getName(), is, o.outMimeType);
final MediaUploadResponse uploadResp = twitterUpload.uploadMedia(file);
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(twitter.sendDirectMessage(recipientId, text,
uploadResp.getId()), accountKey, true);
if (!file.delete()) {
Log.d(LOGTAG, String.format("unable to delete %s", path));
if (USER_TYPE_FANFOU_COM.equals(credentials.account_type)) {
if (imageUri != null) {
throw new TwitterException("Can't send image DM on Fanfou");
}
final DirectMessage dm = twitter.sendFanfouDirectMessage(recipientId, text, null);
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(dm, accountKey, true);
} else {
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(twitter.sendDirectMessage(recipientId, text), accountKey, true);
if (imageUri != null) {
final String path = getImagePathFromUri(this, Uri.parse(imageUri));
if (path == null) throw new FileNotFoundException();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
final File file = new File(path);
BitmapUtils.downscaleImageIfNeeded(file, 100);
final ContentLengthInputStream is = new ContentLengthInputStream(file);
is.setReadListener(new MessageMediaUploadListener(this, mNotificationManager, builder, text));
// final MediaUploadResponse uploadResp = twitter.uploadMedia(file.getName(), is, o.outMimeType);
final MediaUploadResponse uploadResp = twitterUpload.uploadMedia(file);
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(twitter.sendDirectMessage(recipientId, text,
uploadResp.getId()), accountKey, true);
if (!file.delete()) {
Log.d(LOGTAG, String.format("unable to delete %s", path));
}
} else {
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(twitter.sendDirectMessage(recipientId, text), accountKey, true);
}
}
Utils.setLastSeen(this, new UserKey(recipientId, accountKey.getHost()),
System.currentTimeMillis());

View File

@ -152,9 +152,9 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
} else {
deleteBound[1] = Math.max(deleteBound[1], parcelableActivity.max_sort_position);
}
parcelableActivity.inserted_date = System.currentTimeMillis();
final ContentValues values = ContentValuesCreator.createActivity(parcelableActivity,
credentials, userColorNameManager);
values.put(Activities.INSERTED_DATE, System.currentTimeMillis());
valuesList.add(values);
}
final Uri contentUri = UriUtils.appendQueryParameters(getContentUri(), QUERY_PARAM_NOTIFY,

View File

@ -3,7 +3,6 @@ package org.mariotaku.twidere.task.twitter;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.util.Log;
@ -12,9 +11,10 @@ import com.squareup.otto.Bus;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.abstask.library.TaskStarter;
import org.mariotaku.sqliteqb.library.Columns;
import org.mariotaku.sqliteqb.library.Expression;
import org.mariotaku.sqliteqb.library.SQLFunctions;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.api.twitter.Twitter;
@ -32,9 +32,7 @@ import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.twidere.task.CacheUsersStatusesTask;
import org.mariotaku.abstask.library.TaskStarter;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.ErrorInfoStore;
@ -44,7 +42,6 @@ import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.UriUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.content.ContentResolverUtils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
@ -189,6 +186,7 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
final ContentValues[] values = new ContentValues[statuses.size()];
final String[] statusIds = new String[statuses.size()];
int minIdx = -1;
long minPositionKey = -1;
boolean hasIntersection = false;
if (!statuses.isEmpty()) {
final long firstSortId = statuses.get(0).getSortId();
@ -203,10 +201,11 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
ParcelableStatusUtils.updateExtraInformation(status, credentials, manager);
status.position_key = getPositionKey(status.timestamp, status.sort_id, lastSortId,
sortDiff, i, j);
status.inserted_date = System.currentTimeMillis();
values[i] = ParcelableStatusValuesCreator.create(status);
values[i].put(Statuses.INSERTED_DATE, System.currentTimeMillis());
if (minIdx == -1 || item.compareTo(statuses.get(minIdx)) < 0) {
minIdx = i;
minPositionKey = status.position_key;
}
if (sinceId != null && item.getSortId() <= sinceSortId) {
hasIntersection = true;
@ -218,22 +217,16 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
final Expression accountWhere = Expression.equalsArgs(AccountSupportColumns.ACCOUNT_KEY);
final Expression statusWhere = Expression.inArgs(new Columns.Column(Statuses.STATUS_ID),
statusIds.length);
final String countWhere = Expression.and(accountWhere, statusWhere).getSQL();
final String[] whereArgs = new String[statusIds.length + 1];
System.arraycopy(statusIds, 0, whereArgs, 1, statusIds.length);
whereArgs[0] = accountKey.toString();
final String[] projection = {SQLFunctions.COUNT()};
final int rowsDeleted;
final Cursor countCur = resolver.query(uri, projection, countWhere, whereArgs, null);
try {
if (countCur != null && countCur.moveToFirst()) {
rowsDeleted = countCur.getInt(0);
} else {
rowsDeleted = 0;
}
} finally {
Utils.closeSilently(countCur);
final String deleteWhere = Expression.and(accountWhere, statusWhere).getSQL();
final String[] deleteWhereArgs = new String[statusIds.length + 1];
System.arraycopy(statusIds, 0, deleteWhereArgs, 1, statusIds.length);
deleteWhereArgs[0] = accountKey.toString();
int olderCount = -1;
if (minPositionKey > 0) {
olderCount = DataStoreUtils.getStatusesCount(context, uri, minPositionKey,
Statuses.POSITION_KEY, false, accountKey);
}
final int rowsDeleted = resolver.delete(uri, deleteWhere, deleteWhereArgs);
// BEGIN HotMobi
final RefreshEvent event = RefreshEvent.create(context, statusIds, getTimelineType());
@ -244,8 +237,8 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, maxId);
final boolean noRowsDeleted = rowsDeleted == 0;
// Why loadItemLimit / 2? because it will not acting strange in most cases
final boolean insertGap = minIdx != -1 && (noRowsDeleted || deletedOldGap) && !noItemsBefore
&& !hasIntersection && statuses.size() > loadItemLimit / 2;
final boolean insertGap = minIdx != -1 && olderCount > 0 && (noRowsDeleted || deletedOldGap)
&& !noItemsBefore && !hasIntersection && statuses.size() > loadItemLimit / 2;
if (insertGap) {
values[minIdx].put(Statuses.IS_GAP, true);
}

View File

@ -30,6 +30,8 @@ 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.CachedRelationship;
import org.mariotaku.twidere.model.CachedRelationshipValuesCreator;
import org.mariotaku.twidere.model.Draft;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableActivityValuesCreator;
@ -43,15 +45,12 @@ import org.mariotaku.twidere.model.ParcelableStatusValuesCreator;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserMention;
import org.mariotaku.twidere.model.ParcelableUserValuesCreator;
import org.mariotaku.twidere.model.SpanItem;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.draft.SendDirectMessageActionExtra;
import org.mariotaku.twidere.model.util.ParcelableActivityUtils;
import org.mariotaku.twidere.model.util.ParcelableMediaUtils;
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
@ -69,15 +68,8 @@ public final class ContentValuesCreator implements TwidereConstants {
public static ContentValues createCachedRelationship(final Relationship relationship,
final UserKey accountKey,
final UserKey userKey) {
final ContentValues values = new ContentValues();
values.put(CachedRelationships.ACCOUNT_KEY, accountKey.toString());
values.put(CachedRelationships.USER_KEY, userKey.toString());
values.put(CachedRelationships.FOLLOWING, relationship.isSourceFollowingTarget());
values.put(CachedRelationships.FOLLOWED_BY, relationship.isSourceFollowedByTarget());
values.put(CachedRelationships.BLOCKING, relationship.isSourceBlockingTarget());
values.put(CachedRelationships.BLOCKED_BY, relationship.isSourceBlockedByTarget());
values.put(CachedRelationships.MUTING, relationship.isSourceMutingTarget());
return values;
CachedRelationship cached = new CachedRelationship(relationship, accountKey, userKey);
return CachedRelationshipValuesCreator.create(cached);
}
public static ContentValues createCachedUser(final User user) {
@ -206,11 +198,26 @@ public final class ContentValuesCreator implements TwidereConstants {
ParcelableCredentials credentials, UserColorNameManager manager) {
final ContentValues values = new ContentValues();
final ParcelableStatus status = ParcelableActivityUtils.getActivityStatus(activity);
activity.account_color = credentials.color;
if (status != null) {
ParcelableStatusUtils.updateExtraInformation(status, credentials, manager);
createStatusActivity(status, values);
activity.account_color = status.account_color;
if (status.is_retweet) {
activity.status_retweeted_by_user_key = status.retweeted_by_user_key;
} else if (status.is_quote) {
activity.status_quote_spans = status.quoted_spans;
activity.status_quote_text_plain = status.quoted_text_plain;
activity.status_quote_source = status.quoted_source;
activity.status_quoted_user_key = status.quoted_user_key;
}
activity.status_user_key = status.user_key;
activity.status_user_following = status.user_is_following;
activity.status_spans = status.spans;
activity.status_text_plain = status.text_plain;
activity.status_source = status.source;
activity.status_user_color = status.user_color;
activity.status_retweet_user_color = status.retweet_user_color;
activity.status_quoted_user_color = status.quoted_user_color;
@ -219,32 +226,11 @@ public final class ContentValuesCreator implements TwidereConstants {
activity.status_in_reply_to_user_nickname = status.in_reply_to_user_nickname;
activity.status_retweet_user_nickname = status.retweet_user_nickname;
activity.status_quoted_user_nickname = status.quoted_user_nickname;
} else {
activity.account_color = credentials.color;
}
ParcelableActivityValuesCreator.writeTo(activity, values);
return values;
}
public static void createStatusActivity(@NonNull final ParcelableStatus status,
@NonNull final ContentValues values) {
if (status.is_retweet) {
values.put(Activities.STATUS_RETWEETED_BY_USER_ID, String.valueOf(status.retweeted_by_user_key));
} else if (status.is_quote) {
values.put(Activities.STATUS_QUOTE_SPANS, JsonSerializer.serialize(status.quoted_spans, SpanItem.class));
values.put(Activities.STATUS_QUOTE_TEXT_PLAIN, status.quoted_text_plain);
values.put(Activities.STATUS_QUOTE_SOURCE, status.quoted_source);
values.put(Activities.STATUS_QUOTED_USER_ID, String.valueOf(status.quoted_user_key));
}
values.put(Activities.STATUS_USER_KEY, String.valueOf(status.user_key));
values.put(Activities.STATUS_USER_FOLLOWING, status.user_is_following);
values.put(Activities.STATUS_SPANS, JsonSerializer.serialize(status.spans, SpanItem.class));
values.put(Activities.STATUS_TEXT_PLAIN, status.text_plain);
values.put(Activities.STATUS_SOURCE, status.source);
}
public static ContentValues[] createTrends(final List<Trends> trendsList) {
if (trendsList == null) return new ContentValues[0];
final List<ContentValues> resultList = new ArrayList<>();
@ -260,4 +246,5 @@ public final class ContentValuesCreator implements TwidereConstants {
return resultList.toArray(new ContentValues[resultList.size()]);
}
}

View File

@ -460,22 +460,22 @@ public class DataStoreUtils implements Constants {
}
}
public static int getStatusesCount(final Context context, final Uri uri, final long since,
String sinceColumn, UserKey... accountKeys) {
public static int getStatusesCount(final Context context, final Uri uri, final long compare,
String compareColumn, boolean greaterThan, UserKey... accountKeys) {
if (context == null) return 0;
if (accountKeys == null) {
accountKeys = getActivatedAccountKeys(context);
}
final Expression selection = Expression.and(
Expression.inArgs(new Column(Statuses.ACCOUNT_KEY), accountKeys.length),
Expression.greaterThanArgs(sinceColumn),
greaterThan ? Expression.greaterThanArgs(compareColumn) : Expression.lesserThanArgs(compareColumn),
buildStatusFilterWhereClause(getTableNameByUri(uri), null)
);
final String[] whereArgs = new String[accountKeys.length + 1];
for (int i = 0; i < accountKeys.length; i++) {
whereArgs[i] = accountKeys[i].toString();
}
whereArgs[accountKeys.length] = String.valueOf(since);
whereArgs[accountKeys.length] = String.valueOf(compare);
return queryCount(context, uri, selection.getSQL(), whereArgs);
}
@ -618,8 +618,8 @@ public class DataStoreUtils implements Constants {
.build();
final Expression filteredUsersWhere = Expression.or(
Expression.in(new Column(new Table(table), Activities.STATUS_USER_KEY), filteredUsersQuery),
Expression.in(new Column(new Table(table), Activities.STATUS_RETWEETED_BY_USER_ID), filteredUsersQuery),
Expression.in(new Column(new Table(table), Activities.STATUS_QUOTED_USER_ID), filteredUsersQuery)
Expression.in(new Column(new Table(table), Activities.STATUS_RETWEETED_BY_USER_KEY), filteredUsersQuery),
Expression.in(new Column(new Table(table), Activities.STATUS_QUOTED_USER_KEY), filteredUsersQuery)
);
final SQLSelectQuery.Builder filteredIdsQueryBuilder = SQLQueryBuilder
.select(new Column(new Table(table), Activities._ID))
@ -648,9 +648,9 @@ public class DataStoreUtils implements Constants {
.from(new Tables(table, Filters.Links.TABLE_NAME))
.where(Expression.or(
Expression.likeRaw(new Column(new Table(table), Activities.STATUS_SPANS),
"'%>%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%</a>%'"),
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'"),
Expression.likeRaw(new Column(new Table(table), Activities.STATUS_QUOTE_SPANS),
"'%>%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%</a>%'")
"'%'||" + Filters.Links.TABLE_NAME + "." + Filters.Links.VALUE + "||'%'")
));
final Expression filterExpression = Expression.or(
Expression.notIn(new Column(new Table(table), Activities._ID), filteredIdsQueryBuilder.build()),

View File

@ -26,6 +26,7 @@ import com.bluelinelabs.logansquare.JsonMapper;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
@ -116,7 +117,7 @@ public class JsonSerializer {
//noinspection TryFinallyCanBeTryWithResources
try {
is = new FileInputStream(file);
return LoganSquareMapperFinder.mapperFor(cls).parseList(is);
return parseList(is, cls);
} catch (IOException e) {
return null;
} finally {
@ -124,6 +125,14 @@ public class JsonSerializer {
}
}
public static <E> List<E> parseList(InputStream stream, Class<E> cls) {
try {
return LoganSquareMapperFinder.mapperFor(cls).parseList(stream);
} catch (IOException e) {
return null;
}
}
public static <E> List<E> parseList(String json, Class<E> cls) {
FileInputStream is = null;

View File

@ -276,7 +276,7 @@ public class TwitterAPIFactory implements TwidereConstants {
}
final String endpointUrl;
endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix);
if (credentials.auth_type == ParcelableCredentials.AUTH_TYPE_XAUTH || credentials.auth_type == ParcelableCredentials.AUTH_TYPE_OAUTH) {
if (credentials.auth_type == ParcelableCredentials.AuthType.XAUTH || credentials.auth_type == ParcelableCredentials.AuthType.OAUTH) {
final String signEndpointUrl;
if (!sameOAuthSigningUrl) {
signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix);
@ -292,8 +292,8 @@ public class TwitterAPIFactory implements TwidereConstants {
public static Authorization getAuthorization(@Nullable ParcelableCredentials credentials) {
if (credentials == null) return null;
switch (credentials.auth_type) {
case ParcelableCredentials.AUTH_TYPE_OAUTH:
case ParcelableCredentials.AUTH_TYPE_XAUTH: {
case ParcelableCredentials.AuthType.OAUTH:
case ParcelableCredentials.AuthType.XAUTH: {
final String consumerKey = TextUtils.isEmpty(credentials.consumer_key) ?
TWITTER_CONSUMER_KEY_LEGACY : credentials.consumer_key;
final String consumerSecret = TextUtils.isEmpty(credentials.consumer_secret) ?
@ -304,7 +304,7 @@ public class TwitterAPIFactory implements TwidereConstants {
return new OAuthAuthorization(consumerKey, consumerSecret, accessToken);
return new OAuthAuthorization(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET, accessToken);
}
case ParcelableCredentials.AUTH_TYPE_BASIC: {
case ParcelableCredentials.AuthType.BASIC: {
final String screenName = credentials.screen_name;
final String username = credentials.basic_auth_username;
final String loginName = username != null ? username : screenName;

View File

@ -121,9 +121,9 @@ public class UserColorNameManager implements TwidereConstants {
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_USER_COLOR,
Activities.STATUS_USER_KEY, color, cv);
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_RETWEET_USER_COLOR,
Activities.STATUS_RETWEETED_BY_USER_ID, color, cv);
Activities.STATUS_RETWEETED_BY_USER_KEY, color, cv);
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_QUOTED_USER_COLOR,
Activities.STATUS_QUOTED_USER_ID, color, cv);
Activities.STATUS_QUOTED_USER_KEY, color, cv);
}
private void updateNickname(String userKey, String nickname) {
@ -139,9 +139,9 @@ public class UserColorNameManager implements TwidereConstants {
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_USER_NICKNAME,
Activities.STATUS_USER_KEY, nickname, cv);
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_RETWEET_USER_NICKNAME,
Activities.STATUS_RETWEETED_BY_USER_ID, nickname, cv);
Activities.STATUS_RETWEETED_BY_USER_KEY, nickname, cv);
updateColumn(cr, Activities.AboutMe.CONTENT_URI, userKey, Activities.STATUS_QUOTED_USER_NICKNAME,
Activities.STATUS_QUOTED_USER_ID, nickname, cv);
Activities.STATUS_QUOTED_USER_KEY, nickname, cv);
}
private static void updateColumn(ContentResolver cr, Uri uri, String userKey, String valueColumn,

View File

@ -136,20 +136,6 @@ public final class DatabaseUpgradeHelper {
}
}
private static String getCreateSQL(final SQLiteDatabase db, final String table) {
final SQLSelectQuery.Builder qb = select(new Column("sql"));
qb.from(new Tables("sqlite_master"));
qb.where(new Expression("type = ? AND name = ?"));
final Cursor c = db.rawQuery(qb.buildSQL(), new String[]{"table", table});
if (c == null) return null;
try {
if (c.moveToFirst()) return c.getString(0);
return null;
} finally {
c.close();
}
}
private static String[] getNotNullColumns(final NewColumn[] newCols) {
if (newCols == null) return null;
final String[] notNullCols = new String[newCols.length];
@ -162,17 +148,4 @@ public final class DatabaseUpgradeHelper {
return ArrayUtils.subarray(notNullCols, 0, count);
}
private static Map<String, String> getTypeMapByCreateQuery(final String query) {
if (TextUtils.isEmpty(query)) return Collections.emptyMap();
final int start = query.indexOf("("), end = query.lastIndexOf(")");
if (start < 0 || end < 0) return Collections.emptyMap();
final HashMap<String, String> map = new HashMap<>();
for (final String segment : query.substring(start + 1, end).split(",")) {
final String trimmed = segment.trim().replaceAll(" +", " ");
final int idx = trimmed.indexOf(" ");
map.put(trimmed.substring(0, idx), trimmed.substring(idx + 1, trimmed.length()));
}
return map;
}
}

View File

@ -0,0 +1,99 @@
package org.mariotaku.twidere.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.AttributeSet;
import android.view.MotionEvent;
import com.afollestad.appthemeengine.ATE;
import com.afollestad.appthemeengine.ATEActivity;
import com.afollestad.appthemeengine.Config;
import com.afollestad.appthemeengine.inflation.ViewInterface;
/**
* @author Aidan Follestad (afollestad)
*/
public class HomeDrawerLayout extends DrawerLayout implements ViewInterface {
private ShouldDisableDecider mShouldDisableDecider;
private int state;
private int mStartLockMode, mEndLockMode;
public HomeDrawerLayout(Context context) {
super(context);
init(context, null);
}
public HomeDrawerLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, null);
}
public HomeDrawerLayout(Context context, AttributeSet attrs, @Nullable ATEActivity keyContext) {
super(context, attrs);
init(context, keyContext);
}
private void init(Context context, @Nullable ATEActivity keyContext) {
final String key = keyContext != null ? keyContext.getATEKey() : null;
if (Config.coloredStatusBar(context, key)) {
// Sets the status bar overlayed by the DrawerLayout
setStatusBarBackgroundColor(Config.statusBarColor(context, key));
if (context instanceof Activity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final Activity activity = (Activity) context;
// Sets Activity status bar to transparent, DrawerLayout overlays a color.
activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
ATE.invalidateLightStatusBar(activity, key);
}
}
}
public void setShouldDisableDecider(ShouldDisableDecider shouldDisableDecider) {
mShouldDisableDecider = shouldDisableDecider;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
mStartLockMode = getDrawerLockMode(GravityCompat.START);
mEndLockMode = getDrawerLockMode(GravityCompat.END);
if (isDrawerOpen(GravityCompat.START) || isDrawerOpen(GravityCompat.END)) {
// Opened, disable close if requested
if (mShouldDisableDecider != null && mShouldDisableDecider.shouldDisableTouch(ev)) {
setDrawerLockMode(LOCK_MODE_LOCKED_OPEN, GravityCompat.START);
setDrawerLockMode(LOCK_MODE_LOCKED_OPEN, GravityCompat.END);
}
}
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
setDrawerLockMode(mStartLockMode, GravityCompat.START);
setDrawerLockMode(mEndLockMode, GravityCompat.END);
break;
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean setsStatusBarColor() {
return true;
}
@Override
public boolean setsToolbarColor() {
return false;
}
public interface ShouldDisableDecider {
boolean shouldDisableTouch(MotionEvent e);
}
}

View File

@ -17,7 +17,7 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<android.support.v4.widget.DrawerLayout
<org.mariotaku.twidere.view.HomeDrawerLayout
android:id="@+id/home_menu"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
@ -38,4 +38,4 @@
android:layout_gravity="start"
tools:layout="@layout/fragment_accounts_dashboard"/>
</android.support.v4.widget.DrawerLayout>
</org.mariotaku.twidere.view.HomeDrawerLayout>

View File

@ -779,6 +779,9 @@
<string name="provider_default">Twidere</string>
<!-- Fanfou is a Chinese micro blogging website http://fanfou.com/ -->
<string name="provider_fanfou">Fanfou</string>
<string name="provider_quitter_se">Quitter.se</string>
<string name="provider_loadaverage_org">LoadAverage.org</string>
<string name="provider_gnusocial_net">GNU Social.net</string>
<string name="new_document_api">New Document API</string>
<string name="new_document_api_summary">Open profile and media in new task</string>
<string name="drawer_toggle">Drawer toggle</string>