From 169f00a4862322a44e5f434cb34349480414a788 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 08:56:04 +0800 Subject: [PATCH 1/8] window background bug fixes added alt_text for media --- .../twidere/api/twitter/TwitterPrivate.java | 4 +- .../twidere/api/twitter/TwitterUpload.java | 7 ++- .../twitter/api/DirectMessagesResources.java | 8 +-- .../api/twitter/api/FavoritesResources.java | 5 +- .../api/twitter/api/ListResources.java | 12 +++-- ...ces.java => PrivateTimelineResources.java} | 6 ++- .../twitter/api/PrivateTweetResources.java | 4 +- .../api/twitter/api/TimelineResources.java | 4 +- .../api/twitter/api/TweetResources.java | 4 +- .../api/twitter/model/MediaEntity.java | 26 +++++++++ .../twitter/model/MediaUploadResponse.java | 4 +- .../api/twitter/model/NewMediaMetadata.java | 53 +++++++++++++++++++ .../api/twitter/model/StatusUpdate.java | 4 +- .../twidere/model/ParcelableMedia.java | 10 ++++ .../twidere/model/ParcelableMediaUpdate.java | 23 +++++--- .../twidere/activity/BaseActivity.java | 5 -- .../twitter/util/TwitterConverterFactory.java | 32 +++++++++-- .../graphic/WindowBackgroundDrawable.java | 38 +++++++++++++ .../model/util/ParcelableMediaUtils.java | 1 + .../service/BackgroundOperationService.java | 7 ++- .../mariotaku/twidere/util/ThemeUtils.java | 31 ++++++++--- .../twidere/util/TwitterAPIFactory.java | 1 + .../twidere/view/CardMediaContainer.java | 6 +++ 23 files changed, 248 insertions(+), 47 deletions(-) rename twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/{PrivateTimelinesResources.java => PrivateTimelineResources.java} (91%) create mode 100644 twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/NewMediaMetadata.java create mode 100644 twidere/src/main/java/org/mariotaku/twidere/graphic/WindowBackgroundDrawable.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterPrivate.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterPrivate.java index dbf2c4935..155474aff 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterPrivate.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterPrivate.java @@ -4,13 +4,13 @@ import org.mariotaku.twidere.api.twitter.api.PrivateActivityResources; import org.mariotaku.twidere.api.twitter.api.PrivateDirectMessagesResources; import org.mariotaku.twidere.api.twitter.api.PrivateFriendsFollowersResources; import org.mariotaku.twidere.api.twitter.api.PrivateScheduleResources; -import org.mariotaku.twidere.api.twitter.api.PrivateTimelinesResources; +import org.mariotaku.twidere.api.twitter.api.PrivateTimelineResources; import org.mariotaku.twidere.api.twitter.api.PrivateTweetResources; /** * Created by mariotaku on 16/3/4. */ public interface TwitterPrivate extends PrivateActivityResources, PrivateTweetResources, - PrivateTimelinesResources, PrivateFriendsFollowersResources, PrivateDirectMessagesResources, + PrivateTimelineResources, PrivateFriendsFollowersResources, PrivateDirectMessagesResources, PrivateScheduleResources { } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUpload.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUpload.java index 59d8baebc..530b6710c 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUpload.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterUpload.java @@ -23,15 +23,15 @@ import org.mariotaku.restfu.annotation.method.POST; import org.mariotaku.restfu.annotation.param.KeyValue; import org.mariotaku.restfu.annotation.param.Param; import org.mariotaku.restfu.annotation.param.Params; +import org.mariotaku.restfu.annotation.param.Raw; import org.mariotaku.restfu.http.BodyType; import org.mariotaku.restfu.http.mime.Body; -import org.mariotaku.restfu.http.mime.FileBody; import org.mariotaku.twidere.api.twitter.model.MediaUploadResponse; +import org.mariotaku.twidere.api.twitter.model.NewMediaMetadata; import org.mariotaku.twidere.api.twitter.model.ResponseCode; import java.io.File; -@SuppressWarnings("RedundantThrows") public interface TwitterUpload { @POST("/media/upload.json") @@ -57,4 +57,7 @@ public interface TwitterUpload { @POST("/media/upload.json") @Params(@KeyValue(key = "command", value = "FINALIZE")) MediaUploadResponse initUploadMedia(@Param("media_id") long mediaId) throws TwitterException; + + @POST("/media/metadata/create.json") + ResponseCode createMetadata(@Raw NewMediaMetadata metadata) throws TwitterException; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/DirectMessagesResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/DirectMessagesResources.java index df48f5f67..439bdf870 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/DirectMessagesResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/DirectMessagesResources.java @@ -56,17 +56,17 @@ public interface DirectMessagesResources { @POST("/direct_messages/new.json") @BodyType(BodyType.FORM) DirectMessage sendDirectMessage(@Param("user_id") String userId, @Param("text") String text, - @Param("media_id") long mediaId) throws TwitterException; + @Param("media_id") String mediaId) throws TwitterException; @POST("/direct_messages/new.json") @BodyType(BodyType.FORM) - DirectMessage sendDirectMessageForScreenName(@Param("screen_name") String screenName, @Param("text") String text) + DirectMessage sendDirectMessageToScreenName(@Param("screen_name") String screenName, @Param("text") String text) throws TwitterException; @POST("/direct_messages/new.json") @BodyType(BodyType.FORM) - DirectMessage sendDirectMessageForScreenName(@Param("screen_name") String screenName, @Param("text") String text, - @Param("media_id") long mediaId) throws TwitterException; + DirectMessage sendDirectMessageToScreenName(@Param("screen_name") String screenName, @Param("text") String text, + @Param("media_id") String mediaId) throws TwitterException; @GET("/direct_messages/show.json") DirectMessage showDirectMessage(@Query("id") String id) throws TwitterException; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/FavoritesResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/FavoritesResources.java index ef357d985..93096b325 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/FavoritesResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/FavoritesResources.java @@ -25,7 +25,6 @@ import org.mariotaku.restfu.annotation.param.KeyValue; import org.mariotaku.restfu.annotation.param.Param; import org.mariotaku.restfu.annotation.param.Queries; import org.mariotaku.restfu.annotation.param.Query; -import org.mariotaku.restfu.http.BodyType; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.model.Paging; import org.mariotaku.twidere.api.twitter.model.ResponseList; @@ -38,7 +37,9 @@ import org.mariotaku.twidere.api.twitter.model.Status; @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") +}) public interface FavoritesResources { @POST("/favorites/create.json") diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java index eb2e46403..e161d2fc6 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java @@ -122,7 +122,9 @@ public interface ListResources { @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") + }) ResponseList getUserListStatuses(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; @GET("/lists/statuses.json") @@ -132,7 +134,9 @@ public interface ListResources { @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") + }) ResponseList getUserListStatuses(@Query("slug") String slug, @Query("owner_id") long ownerId, @Query Paging paging) throws TwitterException; @GET("/lists/statuses.json") @@ -142,7 +146,9 @@ public interface ListResources { @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") + }) ResponseList getUserListStatuses(@Query("slug") String slug, @Query("owner_screen_name") String ownerScreenName, @Query Paging paging) throws TwitterException; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelinesResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelineResources.java similarity index 91% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelinesResources.java rename to twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelineResources.java index 9d9e637f1..5dc5c01ee 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelinesResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTimelineResources.java @@ -35,8 +35,10 @@ import org.mariotaku.twidere.api.twitter.model.Status; @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) -public interface PrivateTimelinesResources extends PrivateResources { + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") +}) +public interface PrivateTimelineResources extends PrivateResources { @GET("/statuses/media_timeline.json") ResponseList getMediaTimeline(@Query("user_id") String userId, @Query Paging paging) throws TwitterException; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTweetResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTweetResources.java index 76258bfb3..22b8b9a58 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTweetResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/PrivateTweetResources.java @@ -38,7 +38,9 @@ import org.mariotaku.twidere.api.twitter.model.TranslationResult; @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") +}) public interface PrivateTweetResources extends PrivateResources { @GET("/statuses/{id}/activity/summary.json") diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TimelineResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TimelineResources.java index a1b500472..d401b8eac 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TimelineResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TimelineResources.java @@ -36,7 +36,9 @@ import org.mariotaku.twidere.api.twitter.model.Status; @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") +}) public interface TimelineResources { @GET("/statuses/home_timeline.json") diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TweetResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TweetResources.java index 5578bbdce..01daa7ec4 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TweetResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/TweetResources.java @@ -40,7 +40,9 @@ import org.mariotaku.twidere.api.twitter.model.StatusUpdate; @KeyValue(key = "include_cards", valueKey = "include_cards"), @KeyValue(key = "cards_platform", valueKey = "cards_platform"), @KeyValue(key = "include_reply_count", valueKey = "include_reply_count"), - @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count")}) + @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), + @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") +}) public interface TweetResources { @POST("/statuses/destroy/{id}.json") Status destroyStatus(@Path("id") String statusId) throws TwitterException; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaEntity.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaEntity.java index e7e629c12..05a62e871 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaEntity.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaEntity.java @@ -19,9 +19,14 @@ package org.mariotaku.twidere.api.twitter.model; +import android.support.annotation.IntDef; +import android.support.annotation.StringDef; + import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonObject; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -61,6 +66,8 @@ public class MediaEntity extends UrlEntity { VideoInfo videoInfo; @JsonField(name = "features") HashMap features; + @JsonField(name = "ext_alt_text") + String altText; public Map getFeatures() { return features; @@ -78,14 +85,17 @@ public class MediaEntity extends UrlEntity { return mediaUrlHttps; } + @Override public String getExpandedUrl() { return expandedUrl; } + @Override public String getDisplayUrl() { return displayUrl; } + @Override public String getUrl() { return url; } @@ -99,10 +109,12 @@ public class MediaEntity extends UrlEntity { return sizes; } + @Override public int getEnd() { return indices.getEnd(); } + @Override public int getStart() { return indices.getStart(); } @@ -111,6 +123,10 @@ public class MediaEntity extends UrlEntity { return id; } + public String getAltText() { + return altText; + } + @Override public String toString() { return "MediaEntity{" + @@ -253,6 +269,16 @@ public class MediaEntity extends UrlEntity { } } + @StringDef({Size.THUMB, Size.SMALL, Size.MEDIUM, Size.LARGE}) + @Retention(RetentionPolicy.SOURCE) + public @interface SizeType { + } + + @IntDef({Size.FIT, Size.CROP}) + @Retention(RetentionPolicy.SOURCE) + public @interface ScaleType { + } + @JsonObject public static class Size { diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaUploadResponse.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaUploadResponse.java index d70d17082..578341a22 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaUploadResponse.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/MediaUploadResponse.java @@ -29,7 +29,7 @@ import com.bluelinelabs.logansquare.annotation.JsonObject; public class MediaUploadResponse extends TwitterResponseObject implements TwitterResponse { @JsonField(name = "media_id") - long mediaId; + String mediaId; @JsonField(name = "size") long size; @JsonField(name = "image") @@ -37,7 +37,7 @@ public class MediaUploadResponse extends TwitterResponseObject implements Twitte @JsonField(name = "video") Video video; - public long getId() { + public String getId() { return mediaId; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/NewMediaMetadata.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/NewMediaMetadata.java new file mode 100644 index 000000000..9de1fbfc0 --- /dev/null +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/NewMediaMetadata.java @@ -0,0 +1,53 @@ +package org.mariotaku.twidere.api.twitter.model; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +/** + * Created by mariotaku on 16/3/30. + */ +@JsonObject +public class NewMediaMetadata { + @JsonField(name = "media_id") + String mediaId; + @JsonField(name = "alt_text") + AltText altText; + + NewMediaMetadata() { + + } + + public NewMediaMetadata(String mediaId, String altText) { + this.mediaId = mediaId; + this.altText = new AltText(altText); + } + + @Override + public String toString() { + return "NewMediaMetadata{" + + "mediaId='" + mediaId + '\'' + + ", altText=" + altText + + '}'; + } + + @JsonObject + public static class AltText { + @JsonField(name = "text") + String text; + + AltText() { + + } + + public AltText(String text) { + this.text = text; + } + + @Override + public String toString() { + return "AltText{" + + "text='" + text + '\'' + + '}'; + } + } +} diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUpdate.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUpdate.java index dbb7f341a..242ebedb9 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUpdate.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUpdate.java @@ -49,7 +49,7 @@ public class StatusUpdate extends SimpleValueMap { put("long", location.getLongitude()); } - public void setMediaIds(final long... mediaIds) { + public void setMediaIds(final String... mediaIds) { remove("media_ids"); if (mediaIds == null) return; put("media_ids", RestFuUtils.toString(mediaIds, ',')); @@ -79,7 +79,7 @@ public class StatusUpdate extends SimpleValueMap { return this; } - public StatusUpdate mediaIds(final long... mediaIds) { + public StatusUpdate mediaIds(final String... mediaIds) { setMediaIds(mediaIds); return this; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMedia.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMedia.java index 902a270e7..5b981ac1c 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMedia.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMedia.java @@ -61,13 +61,19 @@ public class ParcelableMedia implements Parcelable { @ParcelableThisPlease @JsonField(name = "open_browser") public boolean open_browser; + @ParcelableThisPlease + @JsonField(name = "alt_text") + public String alt_text; + public static final Creator CREATOR = new Creator() { + @Override public ParcelableMedia createFromParcel(Parcel source) { ParcelableMedia target = new ParcelableMedia(); ParcelableMediaParcelablePlease.readFromParcel(target, source); return target; } + @Override public ParcelableMedia[] newArray(int size) { return new ParcelableMedia[size]; } @@ -185,12 +191,14 @@ public class ParcelableMedia implements Parcelable { @JsonField(name = "duration") public long duration; public static final Creator CREATOR = new Creator() { + @Override public VideoInfo createFromParcel(Parcel source) { VideoInfo target = new VideoInfo(); ParcelableMedia$VideoInfoParcelablePlease.readFromParcel(target, source); return target; } + @Override public VideoInfo[] newArray(int size) { return new VideoInfo[size]; } @@ -261,12 +269,14 @@ public class ParcelableMedia implements Parcelable { @JsonField(name = "bitrate") public long bitrate; public static final Creator CREATOR = new Creator() { + @Override public Variant createFromParcel(Parcel source) { Variant target = new Variant(); ParcelableMedia$VideoInfo$VariantParcelablePlease.readFromParcel(target, source); return target; } + @Override public Variant[] newArray(int size) { return new Variant[size]; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMediaUpdate.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMediaUpdate.java index 0b1b66a49..d7fa5b619 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMediaUpdate.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableMediaUpdate.java @@ -19,6 +19,9 @@ public class ParcelableMediaUpdate implements Parcelable { @JsonField(name = "type") public int type; + @JsonField(name = "alt_text") + public String alt_text; + public ParcelableMediaUpdate() { } @@ -27,11 +30,6 @@ public class ParcelableMediaUpdate implements Parcelable { this.type = type; } - @Override - public String toString() { - return "ParcelableMediaUpdate{uri=" + uri + ", type=" + type + "}"; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -40,7 +38,8 @@ public class ParcelableMediaUpdate implements Parcelable { ParcelableMediaUpdate that = (ParcelableMediaUpdate) o; if (type != that.type) return false; - return uri.equals(that.uri); + if (!uri.equals(that.uri)) return false; + return alt_text != null ? alt_text.equals(that.alt_text) : that.alt_text == null; } @@ -48,9 +47,19 @@ public class ParcelableMediaUpdate implements Parcelable { public int hashCode() { int result = uri.hashCode(); result = 31 * result + type; + result = 31 * result + (alt_text != null ? alt_text.hashCode() : 0); return result; } + @Override + public String toString() { + return "ParcelableMediaUpdate{" + + "uri='" + uri + '\'' + + ", type=" + type + + ", alt_text='" + alt_text + '\'' + + '}'; + } + @Override public int describeContents() { return 0; @@ -62,12 +71,14 @@ public class ParcelableMediaUpdate implements Parcelable { } public static final Creator CREATOR = new Creator() { + @Override public ParcelableMediaUpdate createFromParcel(Parcel source) { ParcelableMediaUpdate target = new ParcelableMediaUpdate(); ParcelableMediaUpdateParcelablePlease.readFromParcel(target, source); return target; } + @Override public ParcelableMediaUpdate[] newArray(int size) { return new ParcelableMediaUpdate[size]; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java index 90b3e738c..b4ad4fc03 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java @@ -277,11 +277,6 @@ public class BaseActivity extends ATEActivity implements Constants, IExtendedAct mCurrentThemeBackgroundAlpha = getThemeBackgroundAlpha(); mCurrentThemeBackgroundOption = getThemeBackgroundOption(); super.onApplyThemeResource(theme, resId, first); - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); final Window window = getWindow(); if (window != null && shouldApplyWindowBackground()) { ThemeUtils.applyWindowBackground(this, window, getThemeBackgroundOption(), diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/TwitterConverterFactory.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/TwitterConverterFactory.java index 0662a3f80..a03b1bf54 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/TwitterConverterFactory.java +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/util/TwitterConverterFactory.java @@ -26,8 +26,11 @@ import com.bluelinelabs.logansquare.JsonMapper; import com.fasterxml.jackson.core.JsonParseException; import org.mariotaku.restfu.RestConverter; +import org.mariotaku.restfu.http.ContentType; import org.mariotaku.restfu.http.HttpResponse; import org.mariotaku.restfu.http.mime.Body; +import org.mariotaku.restfu.http.mime.SimpleBody; +import org.mariotaku.restfu.http.mime.StringBody; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.auth.OAuthToken; import org.mariotaku.twidere.api.twitter.model.ResponseCode; @@ -50,7 +53,6 @@ public class TwitterConverterFactory extends RestConverter.SimpleFactory(type); + } + try { + return new JsonRequestConverter(LoganSquareMapperFinder.mapperFor(type)); + } catch (LoganSquareMapperFinder.ClassLoaderDeadLockException e) { + throw new RestConverter.ConvertException(e); + } } public static class UnsupportedTypeException extends UnsupportedOperationException { @@ -99,10 +108,10 @@ public class TwitterConverterFactory extends RestConverter.SimpleFactory { + public static class JsonResponseConverter implements RestConverter { private final JsonMapper mapper; - public JsonConverter(JsonMapper mapper) { + public JsonResponseConverter(JsonMapper mapper) { this.mapper = mapper; } @@ -116,4 +125,17 @@ public class TwitterConverterFactory extends RestConverter.SimpleFactory { + private final JsonMapper mapper; + + public JsonRequestConverter(JsonMapper mapper) { + this.mapper = mapper; + } + + @Override + public Body convert(Object request) throws IOException, ConvertException, TwitterException { + return new StringBody(mapper.serialize(request), ContentType.parse("application/json")); + } + } + } diff --git a/twidere/src/main/java/org/mariotaku/twidere/graphic/WindowBackgroundDrawable.java b/twidere/src/main/java/org/mariotaku/twidere/graphic/WindowBackgroundDrawable.java new file mode 100644 index 000000000..5b6335ddc --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/graphic/WindowBackgroundDrawable.java @@ -0,0 +1,38 @@ +package org.mariotaku.twidere.graphic; + +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; + +/** + * Created by mariotaku on 16/3/30. + */ +public class WindowBackgroundDrawable extends Drawable { + + private final int color; + + public WindowBackgroundDrawable(int color) { + this.color = color; + } + + @Override + public void draw(Canvas canvas) { + canvas.drawColor(color); + } + + @Override + public void setAlpha(int alpha) { + // No-op + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + // No-op + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableMediaUtils.java b/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableMediaUtils.java index ee0f8a583..830d87c63 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableMediaUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableMediaUtils.java @@ -71,6 +71,7 @@ public class ParcelableMediaUtils { media.start = entity.getStart(); media.end = entity.getEnd(); media.type = ParcelableMediaUtils.getTypeInt(entity.getType()); + media.alt_text = entity.getAltText(); final MediaEntity.Size size = entity.getSizes().get(MediaEntity.Size.LARGE); if (size != null) { media.width = size.getWidth(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundOperationService.java b/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundOperationService.java index 532a76dd6..31f994c85 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundOperationService.java +++ b/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundOperationService.java @@ -60,6 +60,7 @@ import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.TwitterUpload; import org.mariotaku.twidere.api.twitter.model.ErrorInfo; import org.mariotaku.twidere.api.twitter.model.MediaUploadResponse; +import org.mariotaku.twidere.api.twitter.model.NewMediaMetadata; import org.mariotaku.twidere.api.twitter.model.Status; import org.mariotaku.twidere.api.twitter.model.StatusUpdate; import org.mariotaku.twidere.app.TwidereApplication; @@ -758,7 +759,7 @@ public class BackgroundOperationService extends IntentService implements Constan if (upload == null) { throw new UpdateStatusException("Twitter instance is null"); } - final long[] mediaIds = new long[statusUpdate.media.length]; + final String[] mediaIds = new String[statusUpdate.media.length]; for (int i = 0, j = mediaIds.length; i < j; i++) { final ParcelableMediaUpdate media = statusUpdate.media[i]; @@ -767,6 +768,10 @@ public class BackgroundOperationService extends IntentService implements Constan try { body = getBodyFromMedia(resolver, builder, media, statusUpdate); uploadResp = upload.uploadMedia(body); + if (!TextUtils.isEmpty(media.alt_text)) { + upload.createMetadata(new NewMediaMetadata(uploadResp.getId(), + media.alt_text)); + } } finally { Utils.closeSilently(body); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java index f3309a0ae..ff75bc0c9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java @@ -56,6 +56,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.graphic.ActionIconDrawable; +import org.mariotaku.twidere.graphic.WindowBackgroundDrawable; import org.mariotaku.twidere.graphic.iface.DoNotWrapDrawable; import org.mariotaku.twidere.preference.ThemeBackgroundPreference; import org.mariotaku.twidere.util.menu.TwidereMenuInfo; @@ -108,7 +109,7 @@ public class ThemeUtils implements Constants { } else if (VALUE_THEME_BACKGROUND_SOLID.equals(option)) { window.setBackgroundDrawable(new ColorDrawable(isLightTheme(context) ? Color.WHITE : Color.BLACK)); } else { - window.setBackgroundDrawable(getWindowBackgroundFromTheme(context)); + window.setBackgroundDrawable(getWindowBackground(context)); } } @@ -302,7 +303,7 @@ public class ThemeUtils implements Constants { return Typeface.create(Typeface.DEFAULT, fontStyle); } - public static Drawable getWindowBackgroundFromTheme(final Context context) { + public static Drawable getWindowBackground(final Context context) { final TypedArray a = context.obtainStyledAttributes(new int[]{android.R.attr.windowBackground}); try { return a.getDrawable(0); @@ -311,13 +312,27 @@ public class ThemeUtils implements Constants { } } + public static int getColorBackground(final Context context) { + final TypedArray a = context.obtainStyledAttributes(new int[]{android.R.attr.colorBackground}); + try { + return a.getColor(0, Color.TRANSPARENT); + } finally { + a.recycle(); + } + } + public static Drawable getWindowBackgroundFromThemeApplyAlpha(final Context context, final int alpha) { - final Drawable d = getWindowBackgroundFromTheme(context); - if (d == null) return null; - d.mutate(); - d.setAlpha(TwidereMathUtils.clamp(alpha, ThemeBackgroundPreference.MIN_ALPHA, - ThemeBackgroundPreference.MAX_ALPHA)); - return d; + int backgroundColor; + final Drawable d = getWindowBackground(context); + if (d instanceof ColorDrawable) { + backgroundColor = ((ColorDrawable) d).getColor(); + } else { + backgroundColor = getColorBackground(context); + } + backgroundColor &= 0x00FFFFFF; + backgroundColor |= TwidereMathUtils.clamp(alpha, ThemeBackgroundPreference.MIN_ALPHA, + ThemeBackgroundPreference.MAX_ALPHA) << 24; + return new WindowBackgroundDrawable(backgroundColor); } public static boolean isLightTheme(final Context context) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java index 1d71ae296..b69331868 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java @@ -84,6 +84,7 @@ public class TwitterAPIFactory implements TwidereConstants { sConstantPoll.put("full_text", "true"); sConstantPoll.put("model_version", "7"); sConstantPoll.put("skip_aggregation", "false"); + sConstantPoll.put("include_ext_alt_text", "true"); } @WorkerThread diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/CardMediaContainer.java b/twidere/src/main/java/org/mariotaku/twidere/view/CardMediaContainer.java index f71426685..229789b64 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/CardMediaContainer.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/CardMediaContainer.java @@ -46,6 +46,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; /** + * Dynamic layout for media preview * Created by mariotaku on 14/12/17. */ public class CardMediaContainer extends ViewGroup implements Constants { @@ -140,6 +141,11 @@ public class CardMediaContainer extends ViewGroup implements Constants { if (imageView instanceof MediaPreviewImageView) { ((MediaPreviewImageView) imageView).setHasPlayIcon(ParcelableMediaUtils.hasPlayIcon(media.type)); } + if (TextUtils.isEmpty(media.alt_text)) { + child.setContentDescription(getContext().getString(R.string.media)); + } else { + child.setContentDescription(media.alt_text); + } child.setTag(media); child.setVisibility(VISIBLE); if (i == j - 1) { From d5c58aac1f7888da1c438b1f285a826983ec0bfd Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 09:21:07 +0800 Subject: [PATCH 2/8] updated version --- twidere/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/twidere/build.gradle b/twidere/build.gradle index c4e7088ca..8c9b4e21f 100644 --- a/twidere/build.gradle +++ b/twidere/build.gradle @@ -21,8 +21,8 @@ android { applicationId "org.mariotaku.twidere" minSdkVersion 14 targetSdkVersion 23 - versionCode 179 - versionName "3.1.1.7" + versionCode 180 + versionName "3.1.2" multiDexEnabled true generatedDensities = [] From eb437d2ba03f959c41517b948eb8025f3a6369f5 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 13:53:25 +0800 Subject: [PATCH 3/8] fixed action mode color improved theme color --- .../constant/SharedPreferenceConstants.java | 2 - .../twidere/activity/BaseActivity.java | 30 +++++++- .../activity/CustomTabEditorActivity.java | 3 +- .../twidere/app/TwidereApplication.java | 26 ++++--- .../twidere/fragment/CustomTabsFragment.java | 19 +++-- .../twidere/fragment/UserFragment.java | 8 +-- .../org/mariotaku/twidere/util/MenuUtils.java | 3 +- .../mariotaku/twidere/util/ThemeUtils.java | 31 +++++++- .../util/theme/ImageViewViewProcessor.java | 27 +++++++ ...a => SwipeRefreshLayoutViewProcessor.java} | 7 +- .../theme/TabPagerIndicatorViewProcessor.java | 4 +- .../util/theme/TextViewViewProcessor.java | 72 +++++++++++++++++++ .../twidere/view/ExtendedRecyclerView.java | 2 +- 13 files changed, 197 insertions(+), 37 deletions(-) create mode 100644 twidere/src/main/java/org/mariotaku/twidere/util/theme/ImageViewViewProcessor.java rename twidere/src/main/java/org/mariotaku/twidere/util/theme/{ExtendedSwipeRefreshLayoutViewProcessor.java => SwipeRefreshLayoutViewProcessor.java} (55%) create mode 100644 twidere/src/main/java/org/mariotaku/twidere/util/theme/TextViewViewProcessor.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java index 1e9673b10..4b199455a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java @@ -274,8 +274,6 @@ public interface SharedPreferenceConstants { @Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false) String KEY_COMPACT_CARDS = "compact_cards"; - @Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false) - String KEY_FORCE_USING_PRIVATE_APIS = "force_using_private_apis"; @Preference(type = STRING, hasDefault = true, defaultString = VALUE_COMPOSE_NOW_ACTION_COMPOSE) String KEY_COMPOSE_NOW_ACTION = "compose_now_action"; String KEY_FALLBACK_TWITTER_LINK_HANDLER = "fallback_twitter_link_handler"; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java index b4ad4fc03..fbdbc76db 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java @@ -32,6 +32,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback; import android.support.v7.view.menu.ActionMenuItemView; +import android.support.v7.widget.Toolbar; import android.support.v7.widget.TwidereActionMenuView; import android.util.AttributeSet; import android.view.KeyEvent; @@ -39,7 +40,11 @@ import android.view.MotionEvent; import android.view.View; import android.view.Window; +import com.afollestad.appthemeengine.ATE; import com.afollestad.appthemeengine.ATEActivity; +import com.afollestad.appthemeengine.Config; +import com.afollestad.appthemeengine.customizers.ATEStatusBarCustomizer; +import com.afollestad.appthemeengine.customizers.ATEToolbarCustomizer; import com.squareup.otto.Bus; import org.mariotaku.twidere.BuildConfig; @@ -73,7 +78,8 @@ import javax.inject.Inject; @SuppressLint("Registered") public class BaseActivity extends ATEActivity implements Constants, IExtendedActivity, IThemedActivity, IAppCompatActivity, IControlBarActivity, OnFitSystemWindowsListener, - SystemWindowsInsetsCallback, KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback { + SystemWindowsInsetsCallback, KeyboardShortcutCallback, OnPreferenceDisplayDialogCallback, + ATEToolbarCustomizer, ATEStatusBarCustomizer { private static final String[] sClassPrefixList = { "android.widget.", @@ -365,4 +371,26 @@ public class BaseActivity extends ATEActivity implements Constants, IExtendedAct } return false; } + + @Override + public int getStatusBarColor() { + return ATE.USE_DEFAULT; + } + + @Override + public int getToolbarColor(@Nullable Toolbar toolbar) { + return ATE.USE_DEFAULT; + } + + @Override + public int getLightStatusBarMode() { + //noinspection WrongConstant + return ThemeUtils.getLightStatusBarMode(Config.statusBarColor(this, getATEKey())); + } + + @Override + public int getLightToolbarMode(@Nullable Toolbar toolbar) { + //noinspection WrongConstant + return ThemeUtils.getLightToolbarMode(Config.toolbarColor(this, getATEKey(), toolbar)); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java index dfbfe399f..a38b5f16b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java @@ -315,8 +315,7 @@ public class CustomTabEditorActivity extends BaseActivity implements OnClickList mAccountsAdapter.add(ParcelableAccount.dummyCredentials()); } final boolean officialKeyOnly = intent.getBooleanExtra(EXTRA_OFFICIAL_KEY_ONLY, false); - final boolean forcePrivateAPIs = intent.getBooleanExtra(KEY_FORCE_USING_PRIVATE_APIS, false); - mAccountsAdapter.addAll(DataStoreUtils.getCredentialsList(this, false, !forcePrivateAPIs && officialKeyOnly)); + mAccountsAdapter.addAll(DataStoreUtils.getCredentialsList(this, false, officialKeyOnly)); mAccountsAdapter.setDummyItemText(R.string.activated_accounts); switch (conf.getSecondaryFieldType()) { case CustomTabConfiguration.FIELD_TYPE_USER: { diff --git a/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java b/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java index cc213fd98..11594c3f3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java +++ b/twidere/src/main/java/org/mariotaku/twidere/app/TwidereApplication.java @@ -39,8 +39,11 @@ import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.multidex.MultiDex; import android.support.v4.content.ContextCompat; +import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatDelegate; import android.support.v7.widget.ActionBarContextView; +import android.widget.ImageView; +import android.widget.TextView; import com.afollestad.appthemeengine.ATE; import com.afollestad.appthemeengine.Config; @@ -66,16 +69,17 @@ import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper; import org.mariotaku.twidere.util.dagger.DependencyHolder; import org.mariotaku.twidere.util.net.TwidereDns; import org.mariotaku.twidere.util.theme.ActionBarContextViewViewProcessor; -import org.mariotaku.twidere.util.theme.ExtendedSwipeRefreshLayoutViewProcessor; import org.mariotaku.twidere.util.theme.FloatingActionButtonViewProcessor; import org.mariotaku.twidere.util.theme.FontFamilyTagProcessor; import org.mariotaku.twidere.util.theme.IconActionButtonTagProcessor; +import org.mariotaku.twidere.util.theme.ImageViewViewProcessor; import org.mariotaku.twidere.util.theme.OptimalLinkColorTagProcessor; import org.mariotaku.twidere.util.theme.ProfileImageViewViewProcessor; import org.mariotaku.twidere.util.theme.ProgressWheelViewProcessor; +import org.mariotaku.twidere.util.theme.SwipeRefreshLayoutViewProcessor; import org.mariotaku.twidere.util.theme.TabPagerIndicatorViewProcessor; +import org.mariotaku.twidere.util.theme.TextViewViewProcessor; import org.mariotaku.twidere.util.theme.TimelineContentTextViewViewProcessor; -import org.mariotaku.twidere.view.ExtendedSwipeRefreshLayout; import org.mariotaku.twidere.view.ProfileImageView; import org.mariotaku.twidere.view.TabPagerIndicator; import org.mariotaku.twidere.view.ThemedMultiValueSwitch; @@ -144,8 +148,10 @@ public class TwidereApplication extends Application implements Constants, ATE.registerViewProcessor(TabPagerIndicator.class, new TabPagerIndicatorViewProcessor()); ATE.registerViewProcessor(FloatingActionButton.class, new FloatingActionButtonViewProcessor()); ATE.registerViewProcessor(ActionBarContextView.class, new ActionBarContextViewViewProcessor()); - ATE.registerViewProcessor(ExtendedSwipeRefreshLayout.class, new ExtendedSwipeRefreshLayoutViewProcessor()); + ATE.registerViewProcessor(SwipeRefreshLayout.class, new SwipeRefreshLayoutViewProcessor()); ATE.registerViewProcessor(TimelineContentTextView.class, new TimelineContentTextViewViewProcessor()); + ATE.registerViewProcessor(TextView.class, new TextViewViewProcessor()); + ATE.registerViewProcessor(ImageView.class, new ImageViewViewProcessor()); ATE.registerViewProcessor(ProgressWheel.class, new ProgressWheelViewProcessor()); ATE.registerViewProcessor(ProfileImageView.class, mProfileImageViewViewProcessor); ATE.registerTagProcessor(OptimalLinkColorTagProcessor.TAG, new OptimalLinkColorTagProcessor()); @@ -166,16 +172,17 @@ public class TwidereApplication extends Application implements Constants, final int themeColor = preferences.getInt(KEY_THEME_COLOR, ContextCompat.getColor(this, R.color.branding_color)); if (!ATE.config(this, VALUE_THEME_NAME_LIGHT).isConfigured()) { + //noinspection WrongConstant ATE.config(this, VALUE_THEME_NAME_LIGHT) .primaryColor(themeColor) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(true) .coloredStatusBar(true) .commit(); } if (!ATE.config(this, VALUE_THEME_NAME_DARK).isConfigured()) { ATE.config(this, VALUE_THEME_NAME_DARK) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(false) .coloredStatusBar(true) .statusBarColor(Color.BLACK) @@ -183,7 +190,7 @@ public class TwidereApplication extends Application implements Constants, } if (!ATE.config(this, null).isConfigured()) { ATE.config(this, null) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(false) .coloredStatusBar(false) .commit(); @@ -347,20 +354,21 @@ public class TwidereApplication extends Application implements Constants, case KEY_THEME_COLOR: { final int themeColor = preferences.getInt(key, ContextCompat.getColor(this, R.color.branding_color)); + //noinspection WrongConstant ATE.config(this, VALUE_THEME_NAME_LIGHT) .primaryColor(themeColor) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(true) .coloredStatusBar(true) .commit(); ATE.config(this, VALUE_THEME_NAME_DARK) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(false) .coloredStatusBar(true) .statusBarColor(Color.BLACK) .commit(); ATE.config(this, null) - .accentColor(themeColor) + .accentColor(ThemeUtils.getOptimalAccentColor(themeColor)) .coloredActionBar(false) .coloredStatusBar(false) .commit(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/CustomTabsFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/CustomTabsFragment.java index d5a86c564..a42dadca5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/CustomTabsFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/CustomTabsFragment.java @@ -30,6 +30,7 @@ import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; @@ -51,6 +52,8 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; +import com.afollestad.appthemeengine.ATEActivity; +import com.afollestad.appthemeengine.Config; import com.mobeta.android.dslv.DragSortListView; import com.mobeta.android.dslv.DragSortListView.DropListener; import com.mobeta.android.dslv.SimpleDragSortCursorAdapter; @@ -59,15 +62,14 @@ import org.mariotaku.sqliteqb.library.Columns.Column; import org.mariotaku.sqliteqb.library.Expression; import org.mariotaku.sqliteqb.library.RawItemArray; import org.mariotaku.twidere.R; -import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.activity.CustomTabEditorActivity; +import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.model.CustomTabConfiguration; import org.mariotaku.twidere.model.CustomTabConfiguration.CustomTabConfigurationComparator; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.provider.TwidereDataStore.Tabs; import org.mariotaku.twidere.util.DataStoreUtils; import org.mariotaku.twidere.util.ThemeUtils; -import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder; import java.util.ArrayList; @@ -220,9 +222,8 @@ public class CustomTabsFragment extends BaseSupportFragment implements LoaderCal public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { inflater.inflate(R.menu.menu_custom_tabs, menu); final Resources res = getResources(); - final boolean hasOfficialKeyAccounts = Utils.hasAccountSignedWithOfficialKeys(getActivity()); - final boolean forcePrivateAPI = mPreferences.getBoolean(KEY_FORCE_USING_PRIVATE_APIS, false); - final UserKey[] accountIds = DataStoreUtils.getAccountKeys(getActivity()); + final FragmentActivity activity = getActivity(); + final UserKey[] accountIds = DataStoreUtils.getAccountKeys(activity); final MenuItem itemAdd = menu.findItem(R.id.add_submenu); if (itemAdd != null && itemAdd.hasSubMenu()) { final SubMenu subMenu = itemAdd.getSubMenu(); @@ -238,16 +239,20 @@ public class CustomTabsFragment extends BaseSupportFragment implements LoaderCal final boolean accountIdRequired = conf.getAccountRequirement() == CustomTabConfiguration.ACCOUNT_REQUIRED; final Intent intent = new Intent(INTENT_ACTION_ADD_TAB); - intent.setClass(getActivity(), CustomTabEditorActivity.class); + intent.setClass(activity, CustomTabEditorActivity.class); intent.putExtra(EXTRA_TYPE, type); final MenuItem subItem = subMenu.add(conf.getDefaultTitle()); final boolean disabledByNoAccount = accountIdRequired && accountIds.length == 0; - final boolean disabledByDuplicateTab = conf.isSingleTab() && isTabAdded(getActivity(), type); + final boolean disabledByDuplicateTab = conf.isSingleTab() && isTabAdded(activity, type); final boolean shouldDisable = disabledByDuplicateTab || disabledByNoAccount; subItem.setVisible(!shouldDisable); subItem.setEnabled(!shouldDisable); final Drawable icon = ResourcesCompat.getDrawable(res, conf.getDefaultIcon(), null); + if (icon != null && activity instanceof ATEActivity) { + icon.mutate().setColorFilter(Config.textColorPrimary(activity, + ((ATEActivity) activity).getATEKey()), Mode.SRC_ATOP); + } subItem.setIcon(icon); subItem.setIntent(intent); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java index 4c4ef0d2d..719ab815a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java @@ -1556,7 +1556,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener ATEUtil.darkenColor(mPrimaryColorDark)); final Window window = activity.getWindow(); mTintedStatusFrameLayout.setStatusBarColor(statusBarColor); - ThemeUtils.setLightStatusBar(window, ATEUtil.isColorLight(statusBarColor)); + ThemeUtils.setLightStatusBar(window, ThemeUtils.isLightColor(statusBarColor)); int stackedTabColor = mPrimaryColor; @@ -1583,7 +1583,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener final Drawable tabBackground = mPagerIndicator.getBackground(); ((ColorDrawable) tabBackground).setColor(currentTabColor); - final boolean tabItemIsDark = ATEUtil.isColorLight(currentTabColor); + final boolean tabItemIsDark = ThemeUtils.isLightColor(currentTabColor); if (mPreviousTabItemIsDark == 0 || (tabItemIsDark ? 1 : -1) != mPreviousTabItemIsDark) { final int tabContrastColor = ThemeUtils.getColorDependent(currentTabColor); @@ -1597,11 +1597,11 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener } mPagerIndicator.updateAppearance(); } - mPreviousTabItemIsDark = (tabItemIsDark ? 1 : -1); + mPreviousTabItemIsDark = tabItemIsDark ? 1 : -1; final int currentActionBarColor = (Integer) sArgbEvaluator.evaluate(factor, mActionBarShadowColor, stackedTabColor); - final boolean actionItemIsDark = ATEUtil.isColorLight(currentActionBarColor); + final boolean actionItemIsDark = ThemeUtils.isLightColor(currentActionBarColor); if (mPreviousActionBarItemIsDark == 0 || (actionItemIsDark ? 1 : -1) != mPreviousActionBarItemIsDark) { ThemeUtils.applyToolbarItemColor(activity, mToolbar, currentActionBarColor); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java index 52b9418a2..42c392a95 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java @@ -219,8 +219,7 @@ public class MenuUtils implements Constants { if (translate != null) { final boolean isOfficialKey = Utils.isOfficialCredentials(context, account); final SharedPreferencesWrapper prefs = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); - final boolean forcePrivateApis = prefs.getBoolean(SharedPreferenceConstants.KEY_FORCE_USING_PRIVATE_APIS, false); - setMenuItemAvailability(menu, R.id.translate, forcePrivateApis || isOfficialKey); + setMenuItemAvailability(menu, R.id.translate, isOfficialKey); } menu.removeGroup(Constants.MENU_GROUP_STATUS_EXTENSION); Utils.addIntentToMenuForExtension(context, menu, Constants.MENU_GROUP_STATUS_EXTENSION, IntentConstants.INTENT_ACTION_EXTENSION_OPEN_STATUS, diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java index ff75bc0c9..60d87e0a4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/ThemeUtils.java @@ -34,6 +34,7 @@ import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; +import android.support.v4.graphics.ColorUtils; import android.support.v7.app.AppCompatDelegate; import android.support.v7.view.menu.ActionMenuItemView; import android.support.v7.widget.ActionMenuView; @@ -50,7 +51,7 @@ import android.view.Window; import android.view.WindowManager; import android.widget.FrameLayout; -import com.afollestad.appthemeengine.util.ATEUtil; +import com.afollestad.appthemeengine.Config; import org.apache.commons.lang3.ArrayUtils; import org.mariotaku.twidere.Constants; @@ -436,7 +437,7 @@ public class ThemeUtils implements Constants { public static int getActionIconColor(Context context, int backgroundColor) { final int colorDark = ContextCompat.getColor(context, R.color.action_icon_dark); final int colorLight = ContextCompat.getColor(context, R.color.action_icon_light); - return ATEUtil.isColorLight(backgroundColor) ? colorDark : colorLight; + return isLightColor(backgroundColor) ? colorDark : colorLight; } public static void setLightStatusBar(@NonNull Window window, boolean lightStatusBar) { @@ -596,9 +597,33 @@ public class ThemeUtils implements Constants { } public static int getColorDependent(int color) { - final boolean isDark = !ATEUtil.isColorLight(color); + final boolean isDark = !isLightColor(color); return isDark ? Color.WHITE : Color.BLACK; } + @Config.LightStatusBarMode + public static int getLightStatusBarMode(int statusBarColor) { + if (isLightColor(statusBarColor)) { + return Config.LIGHT_STATUS_BAR_ON; + } + return Config.LIGHT_STATUS_BAR_OFF; + } + + @Config.LightToolbarMode + public static int getLightToolbarMode(int themeColor) { + if (isLightColor(themeColor)) { + return Config.LIGHT_TOOLBAR_ON; + } + return Config.LIGHT_TOOLBAR_OFF; + } + + public static boolean isLightColor(int color) { + return ColorUtils.calculateLuminance(color) * 0xFF > ACCENT_COLOR_THRESHOLD; + } + + public static int getOptimalAccentColor(int themeColor) { + return getOptimalAccentColor(themeColor, getContrastColor(themeColor, Color.BLACK, + Color.WHITE)); + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/theme/ImageViewViewProcessor.java b/twidere/src/main/java/org/mariotaku/twidere/util/theme/ImageViewViewProcessor.java new file mode 100644 index 000000000..ad607a263 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/util/theme/ImageViewViewProcessor.java @@ -0,0 +1,27 @@ +package org.mariotaku.twidere.util.theme; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.widget.ImageView; + +import com.afollestad.appthemeengine.Config; +import com.afollestad.appthemeengine.viewprocessors.ViewProcessor; + +import org.mariotaku.twidere.util.ThemeUtils; + +/** + * Created by mariotaku on 16/3/30. + */ +public class ImageViewViewProcessor implements ViewProcessor { + @Override + public void process(@NonNull Context context, @Nullable String key, @Nullable ImageView target, @Nullable Void extra) { + if (target == null) return; + switch (target.getId()) { + case android.support.v7.appcompat.R.id.action_mode_close_button: { + target.setColorFilter(ThemeUtils.getColorDependent(Config.toolbarColor(context, key, null))); + break; + } + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/theme/ExtendedSwipeRefreshLayoutViewProcessor.java b/twidere/src/main/java/org/mariotaku/twidere/util/theme/SwipeRefreshLayoutViewProcessor.java similarity index 55% rename from twidere/src/main/java/org/mariotaku/twidere/util/theme/ExtendedSwipeRefreshLayoutViewProcessor.java rename to twidere/src/main/java/org/mariotaku/twidere/util/theme/SwipeRefreshLayoutViewProcessor.java index 524b84b04..7f7e1a756 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/theme/ExtendedSwipeRefreshLayoutViewProcessor.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/theme/SwipeRefreshLayoutViewProcessor.java @@ -2,18 +2,17 @@ package org.mariotaku.twidere.util.theme; import android.content.Context; import android.support.annotation.NonNull; +import android.support.v4.widget.SwipeRefreshLayout; import com.afollestad.appthemeengine.Config; import com.afollestad.appthemeengine.viewprocessors.ViewProcessor; -import org.mariotaku.twidere.view.ExtendedSwipeRefreshLayout; - /** * Created by mariotaku on 16/3/18. */ -public class ExtendedSwipeRefreshLayoutViewProcessor implements ViewProcessor { +public class SwipeRefreshLayoutViewProcessor implements ViewProcessor { @Override - public void process(@NonNull Context context, String key, ExtendedSwipeRefreshLayout target, Object extra) { + public void process(@NonNull Context context, String key, SwipeRefreshLayout target, Object extra) { target.setColorSchemeColors(Config.accentColor(context, key)); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/theme/TabPagerIndicatorViewProcessor.java b/twidere/src/main/java/org/mariotaku/twidere/util/theme/TabPagerIndicatorViewProcessor.java index 58f107874..413ccbaf2 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/theme/TabPagerIndicatorViewProcessor.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/theme/TabPagerIndicatorViewProcessor.java @@ -5,9 +5,9 @@ import android.graphics.Color; import android.support.annotation.NonNull; import com.afollestad.appthemeengine.Config; -import com.afollestad.appthemeengine.util.ATEUtil; import com.afollestad.appthemeengine.viewprocessors.ViewProcessor; +import org.mariotaku.twidere.util.ThemeUtils; import org.mariotaku.twidere.view.TabPagerIndicator; /** @@ -17,7 +17,7 @@ public class TabPagerIndicatorViewProcessor implements ViewProcessor, Constants { + @Override + public void process(@NonNull final Context context, @Nullable final String key, + @Nullable final TextView target, @Nullable Void extra) { + if (target == null) return; + switch (target.getId()) { + case android.support.v7.appcompat.R.id.action_bar_title: { + if (VALUE_THEME_NAME_DARK.equals(key)) return; + target.addTextChangedListener(new SimpleTextWatcher() { + @Override + public void afterTextChanged(Editable s) { + if (Config.isLightToolbar(context, null, key, Config.toolbarColor(context, key, null))) { + target.setTextColor(Config.textColorPrimary(context, key)); + } else { + target.setTextColor(Config.textColorPrimaryInverse(context, key)); + } + } + }); + break; + } + case android.support.v7.appcompat.R.id.action_bar_subtitle: { + if (VALUE_THEME_NAME_DARK.equals(key)) return; + target.addTextChangedListener(new SimpleTextWatcher() { + @Override + public void afterTextChanged(Editable s) { + if (Config.isLightToolbar(context, null, key, Config.toolbarColor(context, key, null))) { + target.setTextColor(Config.textColorSecondary(context, key)); + } else { + target.setTextColor(Config.textColorSecondaryInverse(context, key)); + } + } + }); + break; + } + } + } + + abstract static class SimpleTextWatcher implements TextWatcher { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + + } + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedRecyclerView.java b/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedRecyclerView.java index 78db04f7d..e511a0dad 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedRecyclerView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/ExtendedRecyclerView.java @@ -91,7 +91,7 @@ public class ExtendedRecyclerView extends RecyclerView { } else { hScroll = 0f; } - if ((vScroll != 0 || hScroll != 0)) { + if (vScroll != 0 || hScroll != 0) { final float scrollFactor = getScrollFactorBackport(); float horizontalDirection = mMouseScrollDirectionDecider.getHorizontalDirection(); float verticalDirection = mMouseScrollDirectionDecider.getVerticalDirection(); From f5830845c73ca2d09b33d3c690747f1cd8585b27 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 13:58:46 +0800 Subject: [PATCH 4/8] fixed crashes --- .../java/org/mariotaku/twidere/activity/SettingsActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java index b9f4c241f..992b85c44 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsActivity.java @@ -55,7 +55,6 @@ import org.mariotaku.twidere.fragment.CustomTabsFragment; import org.mariotaku.twidere.fragment.ExtensionsListFragment; import org.mariotaku.twidere.fragment.SettingsDetailsFragment; import org.mariotaku.twidere.fragment.SupportBrowserFragment; -import org.mariotaku.twidere.preference.iface.IDialogPreference; import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.ThemeUtils; @@ -239,6 +238,7 @@ public class SettingsActivity extends BaseActivity implements OnItemClickListene } protected void openDetails(int position) { + if (isFinishing()) return; final Entry entry = mEntriesAdapter.getItem(position); if (!(entry instanceof PreferenceEntry)) return; final PreferenceEntry pe = (PreferenceEntry) entry; From b1d15ff14f7c397c5e28642289b1d64e5977f73f Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 14:44:03 +0800 Subject: [PATCH 5/8] fixed user timeline --- .../activity/CustomTabEditorActivity.java | 6 ++- .../model/tab/argument/UserArguments.java | 2 +- .../tab/extra/InteractionsTabExtras.java | 12 +++++ .../twidere/model/tab/extra/TabExtras.java | 6 +++ .../twidere/util/CustomTabUtils.java | 4 +- .../twidere/util/InternalParseUtils.java | 53 ------------------- .../res/layout/activity_quick_search_bar.xml | 3 +- .../layout/activity_user_list_selector.xml | 6 ++- 8 files changed, 32 insertions(+), 60 deletions(-) diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java index a38b5f16b..8bfb3982e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/CustomTabEditorActivity.java @@ -61,6 +61,7 @@ import org.mariotaku.twidere.model.tab.argument.TabArguments; import org.mariotaku.twidere.model.tab.argument.TextQueryArguments; import org.mariotaku.twidere.model.tab.argument.UserArguments; import org.mariotaku.twidere.model.tab.argument.UserListArguments; +import org.mariotaku.twidere.model.tab.extra.TabExtras; import org.mariotaku.twidere.util.CustomTabUtils; import org.mariotaku.twidere.util.DataStoreUtils; import org.mariotaku.twidere.util.InternalParseUtils; @@ -349,7 +350,10 @@ public class CustomTabEditorActivity extends BaseActivity implements OnClickList iconKey = intent.getStringExtra(EXTRA_ICON); mEditTabName.setText(intent.getStringExtra(EXTRA_NAME)); if (savedInstanceState == null && intent.hasExtra(EXTRA_EXTRAS)) { - mExtrasBundle.putAll(InternalParseUtils.jsonToBundle(intent.getStringExtra(EXTRA_EXTRAS))); + TabExtras extras = CustomTabUtils.parseTabExtras(type, intent.getStringExtra(EXTRA_EXTRAS)); + if (extras != null) { + extras.copyToBundle(mExtrasBundle); + } } } final int selection = mTabIconsAdapter.getIconPosition(iconKey); diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserArguments.java b/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserArguments.java index b526f9996..f802a9579 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserArguments.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserArguments.java @@ -26,7 +26,7 @@ public class UserArguments extends TabArguments { public void copyToBundle(@NonNull Bundle bundle) { super.copyToBundle(bundle); if (userKey == null) { - bundle.putParcelable(EXTRA_USER_ID, UserKey.valueOf(userId)); + bundle.putParcelable(EXTRA_USER_KEY, UserKey.valueOf(userId)); } else { bundle.putParcelable(EXTRA_USER_KEY, userKey); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/InteractionsTabExtras.java b/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/InteractionsTabExtras.java index 87ddd7014..81f35d11b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/InteractionsTabExtras.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/InteractionsTabExtras.java @@ -1,5 +1,6 @@ package org.mariotaku.twidere.model.tab.extra; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -8,6 +9,8 @@ import com.bluelinelabs.logansquare.annotation.JsonObject; import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease; import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease; +import org.mariotaku.twidere.constant.IntentConstants; + /** * Created by mariotaku on 16/3/6. */ @@ -39,6 +42,13 @@ public class InteractionsTabExtras extends TabExtras implements Parcelable { this.mentionsOnly = mentionsOnly; } + @Override + public void copyToBundle(Bundle bundle) { + super.copyToBundle(bundle); + bundle.putBoolean(IntentConstants.EXTRA_MY_FOLLOWING_ONLY, myFollowingOnly); + bundle.putBoolean(IntentConstants.EXTRA_MENTIONS_ONLY, mentionsOnly); + } + @Override public int describeContents() { return 0; @@ -50,12 +60,14 @@ public class InteractionsTabExtras extends TabExtras implements Parcelable { } public static final Creator CREATOR = new Creator() { + @Override public InteractionsTabExtras createFromParcel(Parcel source) { InteractionsTabExtras target = new InteractionsTabExtras(); InteractionsTabExtrasParcelablePlease.readFromParcel(target, source); return target; } + @Override public InteractionsTabExtras[] newArray(int size) { return new InteractionsTabExtras[size]; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/TabExtras.java b/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/TabExtras.java index 9f04d1533..119fb142d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/TabExtras.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/tab/extra/TabExtras.java @@ -1,6 +1,8 @@ package org.mariotaku.twidere.model.tab.extra; +import android.os.Bundle; import android.os.Parcelable; +import android.support.annotation.CallSuper; import com.bluelinelabs.logansquare.annotation.JsonObject; @@ -9,4 +11,8 @@ import com.bluelinelabs.logansquare.annotation.JsonObject; */ @JsonObject public abstract class TabExtras implements Parcelable { + @CallSuper + public void copyToBundle(Bundle bundle) { + + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java index 4526630c1..221f173c8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java @@ -88,11 +88,11 @@ public class CustomTabUtils implements Constants { if (BuildConfig.DEBUG) { CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.DIRECT_MESSAGES, new CustomTabConfiguration( - DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message, + MessagesEntriesFragment.class, R.string.direct_messages, R.drawable.ic_action_message, CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false)); } else { CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.DIRECT_MESSAGES, new CustomTabConfiguration( - MessagesEntriesFragment.class, R.string.direct_messages, R.drawable.ic_action_message, + DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message, CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false)); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/InternalParseUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/InternalParseUtils.java index 70b179894..cc7c1d95f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/InternalParseUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/InternalParseUtils.java @@ -4,16 +4,11 @@ import android.os.Bundle; import android.util.JsonWriter; import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; import org.mariotaku.restfu.RestFuUtils; import org.mariotaku.twidere.TwidereConstants; -import org.mariotaku.twidere.constant.CompatibilityConstants; -import org.mariotaku.twidere.constant.IntentConstants; import java.io.IOException; import java.io.StringWriter; -import java.util.Iterator; import java.util.Locale; import java.util.Set; @@ -61,54 +56,6 @@ public class InternalParseUtils { } } - public static Bundle jsonToBundle(final String string) { - final Bundle bundle = new Bundle(); - if (string == null) return bundle; - try { - final JSONObject json = new JSONObject(string); - final Iterator it = json.keys(); - while (it.hasNext()) { - final Object key_obj = it.next(); - if (key_obj == null) { - continue; - } - final String key = key_obj.toString(); - final Object value = json.get(key); - if (shouldUseString(key)) { - bundle.putString(key, json.optString(key)); - } else if (shouldPutLong(key)) { - bundle.putLong(key, json.optLong(key)); - } else if (value instanceof Boolean) { - bundle.putBoolean(key, json.optBoolean(key)); - } else if (value instanceof Integer) { - bundle.putInt(key, json.optInt(key)); - } else if (value instanceof Long) { - bundle.putLong(key, json.optLong(key)); - } else if (value instanceof String) { - bundle.putString(key, json.optString(key)); - } else { - Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key); - } - } - } catch (final JSONException | ClassCastException e) { - e.printStackTrace(); - } - return bundle; - } - - private static boolean shouldUseString(final String key) { - switch (key) { - case CompatibilityConstants.EXTRA_ACCOUNT_ID: - case CompatibilityConstants.EXTRA_USER_ID: - return true; - } - return IntentConstants.EXTRA_LIST_ID.equals(key); - } - - private static boolean shouldPutLong(final String key) { - return IntentConstants.EXTRA_LIST_ID.equals(key); - } - public static String parsePrettyDecimal(double num, int decimalDigits) { String result = String.format(Locale.US, "%." + decimalDigits + "f", num); int dotIdx = result.lastIndexOf('.'); diff --git a/twidere/src/main/res/layout/activity_quick_search_bar.xml b/twidere/src/main/res/layout/activity_quick_search_bar.xml index c3355b32f..04f43c4e9 100644 --- a/twidere/src/main/res/layout/activity_quick_search_bar.xml +++ b/twidere/src/main/res/layout/activity_quick_search_bar.xml @@ -76,7 +76,8 @@ android:layout_weight="0" android:background="?actionBarItemBackground" android:color="?menuIconColor" - android:src="@drawable/ic_action_search"/> + android:src="@drawable/ic_action_search" + tools:tint="?menuIconColor"/> diff --git a/twidere/src/main/res/layout/activity_user_list_selector.xml b/twidere/src/main/res/layout/activity_user_list_selector.xml index 39ec50640..300b24853 100644 --- a/twidere/src/main/res/layout/activity_user_list_selector.xml +++ b/twidere/src/main/res/layout/activity_user_list_selector.xml @@ -94,15 +94,17 @@ android:ems="10" android:singleLine="true"/> - + android:src="@drawable/ic_action_search" + tools:tint="?menuIconColor"/> From 1a2a7cad0dcadef1ef1ee18a16247faa3ec66bd6 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 15:07:22 +0800 Subject: [PATCH 6/8] fixed status action item click --- .../twidere/fragment/AbsStatusesFragment.java | 76 ++++++++++-------- .../twidere/fragment/ItemsListFragment.java | 77 +++++++++++++++++++ .../twidere/fragment/StatusFragment.java | 30 +------- .../fragment/UserMediaTimelineFragment.java | 14 ++-- 4 files changed, 129 insertions(+), 68 deletions(-) diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java index a29478a0f..3b9ad0f96 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java @@ -26,7 +26,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; +import android.support.v4.app.FragmentManager; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; import android.support.v7.widget.LinearLayoutManager; @@ -47,6 +47,7 @@ import org.mariotaku.twidere.R; import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter; import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition; import org.mariotaku.twidere.annotation.ReadPositionTag; +import org.mariotaku.twidere.constant.IntentConstants; import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable; import org.mariotaku.twidere.loader.iface.IExtendedLoader; import org.mariotaku.twidere.model.BaseRefreshTaskParam; @@ -349,6 +350,47 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag // END HotMobi } + @Override + public void onItemActionClick(RecyclerView.ViewHolder holder, int id, int position) { + final Context context = getContext(); + if (context == null) return; + final ParcelableStatusesAdapter adapter = getAdapter(); + final ParcelableStatus status = adapter.getStatus(position); + if (status == null) return; + handleStatusActionClick(context, getFragmentManager(), mTwitterWrapper, + (StatusViewHolder) holder, status, id); + } + + public static void handleStatusActionClick(Context context, FragmentManager fm, + AsyncTwitterWrapper twitter, StatusViewHolder holder, + ParcelableStatus status, int id) { + + if (status == null) return; + switch (id) { + case R.id.reply: { + final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY); + intent.setPackage(context.getPackageName()); + intent.putExtra(IntentConstants.EXTRA_STATUS, status); + context.startActivity(intent); + break; + } + case R.id.retweet: { + RetweetQuoteDialogFragment.show(fm, status); + break; + } + case R.id.favorite: { + if (twitter == null) return; + if (status.is_favorite) { + twitter.destroyFavoriteAsync(status.account_key, status.id); + } else { + holder.playLikeAnimation(new DefaultOnLikedListener(twitter, + status)); + } + break; + } + } + } + protected void saveReadPosition() { final LinearLayoutManager layoutManager = getLayoutManager(); if (layoutManager != null) { @@ -363,38 +405,6 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag @TimelineType protected abstract String getTimelineType(); - @Override - public void onItemActionClick(RecyclerView.ViewHolder holder, int id, int position) { - final ParcelableStatusesAdapter adapter = getAdapter(); - final ParcelableStatus status = adapter.getStatus(position); - if (status == null) return; - final FragmentActivity activity = getActivity(); - switch (id) { - case R.id.reply: { - final Intent intent = new Intent(INTENT_ACTION_REPLY); - intent.setPackage(activity.getPackageName()); - intent.putExtra(EXTRA_STATUS, status); - activity.startActivity(intent); - break; - } - case R.id.retweet: { - RetweetQuoteDialogFragment.show(getFragmentManager(), status); - break; - } - case R.id.favorite: { - final AsyncTwitterWrapper twitter = mTwitterWrapper; - if (twitter == null) return; - if (status.is_favorite) { - twitter.destroyFavoriteAsync(status.account_key, status.id); - } else { - ((StatusViewHolder) holder).playLikeAnimation(new DefaultOnLikedListener(twitter, - status)); - } - break; - } - } - } - @Override public void onStatusClick(IStatusViewHolder holder, int position) { final ParcelableStatusesAdapter adapter = getAdapter(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/ItemsListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/ItemsListFragment.java index 5d571eec0..6ea13ebbb 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/ItemsListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/ItemsListFragment.java @@ -1,6 +1,7 @@ package org.mariotaku.twidere.fragment; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.NonNull; @@ -9,7 +10,12 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.Loader; import android.support.v7.widget.RecyclerView; +import android.view.ContextMenu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import org.mariotaku.twidere.R; import org.mariotaku.twidere.adapter.DummyItemAdapter; import org.mariotaku.twidere.adapter.VariousItemsAdapter; import org.mariotaku.twidere.adapter.decorator.DividerItemDecoration; @@ -17,6 +23,11 @@ import org.mariotaku.twidere.adapter.iface.IUsersAdapter; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.util.IntentUtils; +import org.mariotaku.twidere.util.LinkCreator; +import org.mariotaku.twidere.util.MenuUtils; +import org.mariotaku.twidere.util.Utils; +import org.mariotaku.twidere.view.ExtendedRecyclerView; +import org.mariotaku.twidere.view.holder.StatusViewHolder; import org.mariotaku.twidere.view.holder.UserViewHolder; import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder; @@ -30,6 +41,7 @@ public class ItemsListFragment extends AbsContentListRecyclerViewFragment> { private final Bundle mArguments; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java index d4bf121f5..af09e2304 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java @@ -98,8 +98,6 @@ import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.model.Paging; import org.mariotaku.twidere.api.twitter.model.Status; import org.mariotaku.twidere.api.twitter.model.TranslationResult; -import org.mariotaku.twidere.constant.IntentConstants; -import org.mariotaku.twidere.fragment.AbsStatusesFragment.DefaultOnLikedListener; import org.mariotaku.twidere.loader.ConversationLoader; import org.mariotaku.twidere.loader.ParcelableStatusLoader; import org.mariotaku.twidere.menu.support.FavoriteItemProvider; @@ -429,32 +427,8 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac @Override public void onItemActionClick(ViewHolder holder, int id, int position) { final ParcelableStatus status = mStatusAdapter.getStatus(position); - if (status == null) return; - switch (id) { - case R.id.reply: { - final Context context = getActivity(); - final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY); - intent.setPackage(context.getPackageName()); - intent.putExtra(IntentConstants.EXTRA_STATUS, status); - context.startActivity(intent); - break; - } - case R.id.retweet: { - RetweetQuoteDialogFragment.show(getFragmentManager(), status); - break; - } - case R.id.favorite: { - final AsyncTwitterWrapper twitter = mTwitterWrapper; - if (twitter == null) return; - if (status.is_favorite) { - twitter.destroyFavoriteAsync(status.account_key, status.id); - } else { - ((StatusViewHolder) holder).playLikeAnimation(new DefaultOnLikedListener(twitter, - status)); - } - break; - } - } + AbsStatusesFragment.handleStatusActionClick(getContext(), getFragmentManager(), mTwitterWrapper, + (StatusViewHolder) holder, status, id); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserMediaTimelineFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserMediaTimelineFragment.java index f37631f7f..eee00ced0 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserMediaTimelineFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserMediaTimelineFragment.java @@ -167,11 +167,6 @@ public class UserMediaTimelineFragment extends AbsContentRecyclerViewFragment Date: Wed, 30 Mar 2016 16:54:14 +0800 Subject: [PATCH 7/8] supports remove from user list --- .../api/twitter/api/ListResources.java | 40 ++--- .../twidere/api/twitter/model/UserList.java | 9 +- .../twidere/constant/IntentConstants.java | 1 - .../twidere/model/ParcelableUserList.java | 24 +-- .../twidere/adapter/DummyItemAdapter.java | 4 +- .../adapter/ParcelableUserListsAdapter.java | 6 +- .../adapter/ParcelableUsersAdapter.java | 2 - .../SimpleParcelableUserListsAdapter.java | 9 +- .../adapter/iface/IUserListsAdapter.java | 2 +- .../twidere/fragment/AbsStatusesFragment.java | 4 +- .../CursorSupportUsersListFragment.java | 2 + .../DeleteUserListMembersDialogFragment.java | 4 +- .../twidere/fragment/UserListFragment.java | 26 ++-- .../fragment/UserListMembersFragment.java | 138 ++++++++++++++---- .../fragment/UserListSubscribersFragment.java | 2 +- .../fragment/UserListTimelineFragment.java | 10 +- .../twidere/fragment/UserListsFragment.java | 2 +- .../twidere/loader/UserListMembersLoader.java | 6 +- .../loader/UserListSubscribersLoader.java | 6 +- .../loader/UserListTimelineLoader.java | 6 +- .../message/UserListMembersChangedEvent.java | 49 +++++++ .../model/tab/argument/UserListArguments.java | 8 +- .../model/util/ParcelableUserListUtils.java | 18 +++ .../twidere/util/AsyncTwitterWrapper.java | 82 +++++------ .../mariotaku/twidere/util/IntentUtils.java | 11 +- .../twidere/util/OnLinkClickHandler.java | 2 +- .../org/mariotaku/twidere/util/Utils.java | 8 +- .../card_item_activity_summary_common.xml | 19 ++- .../main/res/menu/action_user_list_member.xml | 2 +- 29 files changed, 326 insertions(+), 176 deletions(-) create mode 100644 twidere/src/main/java/org/mariotaku/twidere/model/message/UserListMembersChangedEvent.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java index e161d2fc6..d1b34b42d 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/api/ListResources.java @@ -36,43 +36,43 @@ import org.mariotaku.twidere.api.twitter.model.UserListUpdate; public interface ListResources { @POST("/lists/members/create.json") - UserList addUserListMember(@Query("list_id") long listId, @Query("user_id") long userId) throws TwitterException; + UserList addUserListMember(@Query("list_id") String listId, @Query("user_id") String userId) throws TwitterException; @POST("/lists/members/create.json") - UserList addUserListMember(@Query("list_id") long listId, @Query("screen_name") String userScreenName) throws TwitterException; + UserList addUserListMemberByScreenName(@Query("list_id") String listId, @Query("screen_name") String userScreenName) throws TwitterException; @POST("/lists/members/create_all.json") - UserList addUserListMembers(@Param("list_id") long listId, @Param(value = "user_id", arrayDelimiter = ',') long[] userIds) throws TwitterException; + UserList addUserListMembers(@Param("list_id") String listId, @Param(value = "user_id", arrayDelimiter = ',') String[] userIds) throws TwitterException; @POST("/lists/members/create_all.json") - UserList addUserListMembers(@Param("list_id") long listId, @Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException; + UserList addUserListMembersByScreenName(@Param("list_id") String listId, @Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException; @POST("/lists/create.json") UserList createUserList(@Param UserListUpdate update) throws TwitterException; @POST("/lists/subscribers/create.json") - UserList createUserListSubscription(@Param("list_id") long listId) throws TwitterException; + UserList createUserListSubscription(@Param("list_id") String listId) throws TwitterException; @POST("/lists/members/destroy.json") - UserList deleteUserListMember(@Query("list_id") long listId, @Query("user_id") long userId) throws TwitterException; + UserList deleteUserListMember(@Query("list_id") String listId, @Query("user_id") String userId) throws TwitterException; @POST("/lists/members/destroy.json") - UserList deleteUserListMember(@Query("list_id") long listId, @Param("screen_name") String screenName) throws TwitterException; + UserList deleteUserListMemberByScreenName(@Query("list_id") String listId, @Param("screen_name") String screenName) throws TwitterException; @POST("/lists/members/destroy_all.json") - UserList deleteUserListMembers(@Param("list_id") long listId, @Param(value = "user_id", arrayDelimiter = ',') long[] userIds) throws TwitterException; + UserList deleteUserListMembers(@Param("list_id") String listId, @Param(value = "user_id", arrayDelimiter = ',') String[] userIds) throws TwitterException; @POST("/lists/members/destroy_all.json") - UserList deleteUserListMembers(@Query("list_id") long listId, @Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException; + UserList deleteUserListMembersByScreenName(@Query("list_id") String listId, @Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException; @POST("/lists/destroy.json") - UserList destroyUserList(@Param("list_id") long listId) throws TwitterException; + UserList destroyUserList(@Param("list_id") String listId) throws TwitterException; @POST("/lists/subscribers/destroy.json") - UserList destroyUserListSubscription(@Param("list_id") long listId) throws TwitterException; + UserList destroyUserListSubscription(@Param("list_id") String listId) throws TwitterException; @GET("/lists/members.json") - PageableResponseList getUserListMembers(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; + PageableResponseList getUserListMembers(@Query("list_id") String listId, @Query Paging paging) throws TwitterException; @GET("/lists/members.json") PageableResponseList getUserListMembers(@Query("slug") String slug, @@ -103,10 +103,10 @@ public interface ListResources { PageableResponseList getUserListOwnerships(@Query Paging paging) throws TwitterException; @GET("/lists/ownerships.json") - PageableResponseList getUserListOwnerships(@Query("user_id") long listMemberId, @Query Paging paging) throws TwitterException; + PageableResponseList getUserListOwnerships(@Query("user_id") String listMemberId, @Query Paging paging) throws TwitterException; @GET("/lists/ownerships.json") - PageableResponseList getUserListOwnerships(@Query("screen_name") String listMemberScreenName, @Query Paging paging) + PageableResponseList getUserListOwnershipsByScreenName(@Query("screen_name") String listMemberScreenName, @Query Paging paging) throws TwitterException; @GET("/lists/list.json") @@ -125,7 +125,7 @@ public interface ListResources { @KeyValue(key = "include_descendent_reply_count", valueKey = "include_descendent_reply_count"), @KeyValue(key = "include_ext_alt_text", valueKey = "include_ext_alt_text") }) - ResponseList getUserListStatuses(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; + ResponseList getUserListStatuses(@Query("list_id") String listId, @Query Paging paging) throws TwitterException; @GET("/lists/statuses.json") @Queries({@KeyValue(key = "include_my_retweet", valueKey = "include_my_retweet"), @@ -153,7 +153,7 @@ public interface ListResources { throws TwitterException; @GET("/lists/subscribers.json") - PageableResponseList getUserListSubscribers(@Query("list_id") long listId, @Query Paging paging) throws TwitterException; + PageableResponseList getUserListSubscribers(@Query("list_id") String listId, @Query Paging paging) throws TwitterException; @GET("/lists/subscribers.json") PageableResponseList getUserListSubscribers(@Query("list_id") String slug, @Query("owner_id") String ownerId, @Query Paging paging) @@ -165,15 +165,15 @@ public interface ListResources { @GET("/lists/subscriptions.json") - PageableResponseList getUserListSubscriptions(@Query("screen_name") String listOwnerScreenName, long cursor) + PageableResponseList getUserListSubscriptionsByScreenName(@Query("screen_name") String listOwnerScreenName, long cursor) throws TwitterException; @GET("/lists/subscriptions.json") - PageableResponseList getUserListSubscriptions(@Query("user_id") long userId, long cursor) + PageableResponseList getUserListSubscriptions(@Query("user_id") String userId, long cursor) throws TwitterException; @GET("/lists/show.json") - UserList showUserList(@Query("list_id") long listId) throws TwitterException; + UserList showUserList(@Query("list_id") String listId) throws TwitterException; @GET("/lists/show.json") UserList showUserList(@Query("slug") String slug, @Query("owner_id") String ownerId) throws TwitterException; @@ -182,5 +182,5 @@ public interface ListResources { UserList showUserListByScrenName(@Query("slug") String slug, @Query("owner_screen_name") String ownerScreenName) throws TwitterException; @POST("/lists/update.json") - UserList updateUserList(@Param("list_id") long listId, @Param UserListUpdate update) throws TwitterException; + UserList updateUserList(@Param("list_id") String listId, @Param UserListUpdate update) throws TwitterException; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/UserList.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/UserList.java index 2be4e244d..1a91b1141 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/UserList.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/UserList.java @@ -37,7 +37,7 @@ import java.util.Date; @JsonObject public class UserList extends TwitterResponseObject implements Comparable, TwitterResponse { @JsonField(name = "id") - long id; + String id; @JsonField(name = "name") String name; @@ -73,7 +73,7 @@ public class UserList extends TwitterResponseObject implements Comparable Integer.MAX_VALUE) return Integer.MAX_VALUE; - if (diff < Integer.MIN_VALUE) return Integer.MIN_VALUE; - return (int) diff; + return id.compareTo(another.id); } @Override diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java index c9f4408eb..ac6bd3f2a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java @@ -75,7 +75,6 @@ public interface IntentConstants { String BROADCAST_NOTIFICATION_DELETED = INTENT_PACKAGE_PREFIX + "NOTIFICATION_DELETED"; String BROADCAST_USER_LIST_MEMBERS_DELETED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_DELETED"; - String BROADCAST_USER_LIST_MEMBERS_ADDED = INTENT_PACKAGE_PREFIX + "USER_LIST_MEMBER_ADDED"; String BROADCAST_REFRESH_HOME_TIMELINE = INTENT_PACKAGE_PREFIX + "REFRESH_HOME_TIMELINE"; String BROADCAST_REFRESH_NOTIFICATIONS = INTENT_PACKAGE_PREFIX + "REFRESH_NOTIFICATIONS"; String BROADCAST_REFRESH_DIRECT_MESSAGES = INTENT_PACKAGE_PREFIX + "REFRESH_DIRECT_MESSAGES"; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserList.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserList.java index 190a34279..19326ad2a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserList.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableUserList.java @@ -39,7 +39,7 @@ public class ParcelableUserList implements Parcelable, Comparable>> 32)); + result = 31 * result + id.hashCode(); return result; } @Override public String toString() { return "ParcelableUserList{" + - "members_count=" + members_count + - ", subscribers_count=" + subscribers_count + - ", account_key=" + account_key + - ", id=" + id + - ", user_id=" + user_key + - ", position=" + position + + "account_key=" + account_key + + ", id='" + id + '\'' + ", is_public=" + is_public + ", is_following=" + is_following + ", description='" + description + '\'' + ", name='" + name + '\'' + + ", position=" + position + + ", members_count=" + members_count + + ", subscribers_count=" + subscribers_count + + ", user_key=" + user_key + ", user_screen_name='" + user_screen_name + '\'' + ", user_name='" + user_name + '\'' + ", user_profile_image_url='" + user_profile_image_url + '\'' + @@ -137,12 +137,14 @@ public class ParcelableUserList implements Parcelable, Comparable CREATOR = new Creator() { + @Override public ParcelableUserList createFromParcel(Parcel source) { ParcelableUserList target = new ParcelableUserList(); ParcelableUserListParcelablePlease.readFromParcel(target, source); return target; } + @Override public ParcelableUserList[] newArray(int size) { return new ParcelableUserList[size]; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/DummyItemAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/DummyItemAdapter.java index bfa1e4502..90cada123 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/DummyItemAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/DummyItemAdapter.java @@ -310,8 +310,8 @@ public final class DummyItemAdapter implements IStatusesAdapter, } @Override - public long getUserListId(int position) { - return 0; + public String getUserListId(int position) { + return null; } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java index 36c62b415..2bd5ab4ed 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/ParcelableUserListsAdapter.java @@ -101,8 +101,8 @@ public class ParcelableUserListsAdapter extends LoadMoreSupportAdapter data, final boolean clear_old) { - if (clear_old) { + public void setData(final List data, final boolean clearOld) { + if (clearOld) { clear(); } if (data == null) return; for (final ParcelableUserList user : data) { - if (clear_old || findItemPosition(user.id) < 0) { + //TODO improve compare + if (clearOld || findItemPosition(user.hashCode()) < 0) { add(user); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IUserListsAdapter.java b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IUserListsAdapter.java index c91187344..0ed97b0c3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IUserListsAdapter.java +++ b/twidere/src/main/java/org/mariotaku/twidere/adapter/iface/IUserListsAdapter.java @@ -33,7 +33,7 @@ public interface IUserListsAdapter extends IContentCardAdapter { ParcelableUserList getUserList(int position); - long getUserListId(int position); + String getUserListId(int position); int getUserListsCount(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java index 3b9ad0f96..d5dc8c471 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java @@ -605,8 +605,8 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag startActivity(chooser); return true; } - return MenuUtils.handleStatusClick(getActivity(), AbsStatusesFragment.this, - getFragmentManager(), mUserColorNameManager, mTwitterWrapper, status, item); + return MenuUtils.handleStatusClick(getActivity(), this, getFragmentManager(), + mUserColorNameManager, mTwitterWrapper, status, item); } private String getCurrentReadPositionTag() { diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorSupportUsersListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorSupportUsersListFragment.java index 74ad0735e..0c5920e11 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorSupportUsersListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/CursorSupportUsersListFragment.java @@ -27,6 +27,7 @@ import android.support.v4.content.Loader; import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition; import org.mariotaku.twidere.loader.CursorSupportUsersLoader; import org.mariotaku.twidere.model.ParcelableUser; +import org.mariotaku.twidere.view.holder.UserViewHolder; import java.util.List; @@ -99,4 +100,5 @@ public abstract class CursorSupportUsersListFragment extends ParcelableUsersFrag @Override protected abstract CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser); + } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/DeleteUserListMembersDialogFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/DeleteUserListMembersDialogFragment.java index e44939ac2..6a2e0cf13 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/DeleteUserListMembersDialogFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/DeleteUserListMembersDialogFragment.java @@ -20,7 +20,6 @@ package org.mariotaku.twidere.fragment; import android.app.Dialog; -import android.content.Context; import android.content.DialogInterface; import android.content.res.Resources; import android.os.Bundle; @@ -59,8 +58,7 @@ public class DeleteUserListMembersDialogFragment extends BaseSupportDialogFragme @Override public Dialog onCreateDialog(final Bundle savedInstanceState) { final FragmentActivity activity = getActivity(); - final Context context = activity; - final AlertDialog.Builder builder = new AlertDialog.Builder(context); + final AlertDialog.Builder builder = new AlertDialog.Builder(activity); final ParcelableUser[] users = getUsers(); final ParcelableUserList userList = getUserList(); if (users == null || userList == null) throw new NullPointerException(); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java index e1fbcb650..4d33beaa1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java @@ -167,13 +167,13 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl tabArgs.putParcelable(EXTRA_ACCOUNT_KEY, userList.account_key); tabArgs.putParcelable(EXTRA_USER_KEY, userList.user_key); tabArgs.putString(EXTRA_SCREEN_NAME, userList.user_screen_name); - tabArgs.putLong(EXTRA_LIST_ID, userList.id); + tabArgs.putString(EXTRA_LIST_ID, userList.id); tabArgs.putString(EXTRA_LIST_NAME, userList.name); } else { tabArgs.putParcelable(EXTRA_ACCOUNT_KEY, args.getParcelable(EXTRA_ACCOUNT_KEY)); tabArgs.putParcelable(EXTRA_USER_KEY, args.getParcelable(EXTRA_USER_KEY)); tabArgs.putString(EXTRA_SCREEN_NAME, args.getString(EXTRA_SCREEN_NAME)); - tabArgs.putLong(EXTRA_LIST_ID, args.getLong(EXTRA_LIST_ID, -1)); + tabArgs.putString(EXTRA_LIST_ID, args.getString(EXTRA_LIST_ID)); tabArgs.putString(EXTRA_LIST_NAME, args.getString(EXTRA_LIST_NAME)); } adapter.addTab(UserListTimelineFragment.class, tabArgs, getString(R.string.statuses), null, 0, null); @@ -181,7 +181,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl adapter.addTab(UserListSubscribersFragment.class, tabArgs, getString(R.string.subscribers), null, 2, null); } - private ParcelableUserList getUserList() { + public ParcelableUserList getUserList() { return mUserList; } @@ -266,7 +266,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl args.putString(EXTRA_LIST_NAME, userList.name); args.putString(EXTRA_DESCRIPTION, userList.description); args.putBoolean(EXTRA_IS_PUBLIC, userList.is_public); - args.putLong(EXTRA_LIST_ID, userList.id); + args.putString(EXTRA_LIST_ID, userList.id); final DialogFragment f = new EditUserListDialogFragment(); f.setArguments(args); f.show(getFragmentManager(), "edit_user_list_details"); @@ -325,7 +325,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl public Loader> onCreateLoader(final int id, final Bundle args) { final UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY); final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); - final long listId = args.getLong(EXTRA_LIST_ID, -1); + final String listId = args.getString(EXTRA_LIST_ID); 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); @@ -353,7 +353,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl @Subscribe public void onUserListUpdated(UserListUpdatedEvent event) { if (mUserList == null) return; - if (event.getUserList().id == mUserList.id) { + if (TextUtils.equals(event.getUserList().id, mUserList.id)) { getUserListInfo(true); } } @@ -361,7 +361,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl @Subscribe public void onUserListSubscriptionChanged(UserListSubscriptionEvent event) { if (mUserList == null) return; - if (event.getUserList().id == mUserList.id) { + if (TextUtils.equals(event.getUserList().id, mUserList.id)) { getUserListInfo(true); } } @@ -371,7 +371,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl private String mName, mDescription; private UserKey mAccountKey; - private long mListId; + private String mListId; private boolean mIsPublic; @Override @@ -403,7 +403,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl public Dialog onCreateDialog(final Bundle savedInstanceState) { final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState; mAccountKey = bundle != null ? bundle.getParcelable(EXTRA_ACCOUNT_KEY) : null; - mListId = bundle != null ? bundle.getLong(EXTRA_LIST_ID, -1) : -1; + mListId = bundle != null ? bundle.getString(EXTRA_LIST_ID) : null; mName = bundle != null ? bundle.getString(EXTRA_LIST_NAME) : null; mDescription = bundle != null ? bundle.getString(EXTRA_DESCRIPTION) : null; mIsPublic = bundle == null || bundle.getBoolean(EXTRA_IS_PUBLIC, true); @@ -439,7 +439,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl @Override public void onSaveInstanceState(final Bundle outState) { outState.putParcelable(EXTRA_ACCOUNT_KEY, mAccountKey); - outState.putLong(EXTRA_LIST_ID, mListId); + outState.putString(EXTRA_LIST_ID, mListId); outState.putString(EXTRA_LIST_NAME, mName); outState.putString(EXTRA_DESCRIPTION, mDescription); outState.putBoolean(EXTRA_IS_PUBLIC, mIsPublic); @@ -454,12 +454,12 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl private final Bundle mExtras; private final UserKey mAccountKey; private final UserKey mUserKey; - private final long mListId; + private final String mListId; private final String mScreenName, mListName; private ParcelableUserListLoader(final Context context, final boolean omitIntentExtra, final Bundle extras, final UserKey accountKey, - final long listId, final String listName, + final String listId, final String listName, final UserKey userKey, final String screenName) { super(context); mOmitIntentExtra = omitIntentExtra; @@ -482,7 +482,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl if (twitter == null) return SingleResponse.getInstance(); try { final UserList list; - if (mListId > 0) { + if (mListId != null) { list = twitter.showUserList(mListId); } else if (mUserKey != null) { list = twitter.showUserList(mListName, mUserKey.getId()); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListMembersFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListMembersFragment.java index 89725142f..58feb9803 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListMembersFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListMembersFragment.java @@ -19,42 +19,41 @@ package org.mariotaku.twidere.fragment; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; +import android.view.ContextMenu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import com.squareup.otto.Subscribe; + +import org.mariotaku.twidere.R; +import org.mariotaku.twidere.adapter.ParcelableUsersAdapter; import org.mariotaku.twidere.loader.CursorSupportUsersLoader; import org.mariotaku.twidere.loader.UserListMembersLoader; +import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.model.ParcelableUserList; import org.mariotaku.twidere.model.UserKey; +import org.mariotaku.twidere.model.message.UserListMembersChangedEvent; +import org.mariotaku.twidere.model.util.ParcelableUserListUtils; +import org.mariotaku.twidere.view.ExtendedRecyclerView; +import org.mariotaku.twidere.view.holder.UserViewHolder; + +import java.util.Arrays; +import java.util.List; public class UserListMembersFragment extends CursorSupportUsersListFragment { private ParcelableUserList mUserList; - private final BroadcastReceiver mStatusReceiver = new BroadcastReceiver() { - - @Override - public void onReceive(final Context context, final Intent intent) { - if (getActivity() == null || !isAdded() || isDetached()) return; - final String action = intent.getAction(); - if (BROADCAST_USER_LIST_MEMBERS_DELETED.equals(action)) { - final ParcelableUserList list = intent.getParcelableExtra(EXTRA_USER_LIST); - if (mUserList != null && list != null && list.id == mUserList.id) { - removeUsers(intent.getStringExtra(EXTRA_USER_IDS)); - } - } - } - }; - @Override public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) { - final long listId = args.getLong(EXTRA_LIST_ID, -1); final UserKey accountId = args.getParcelable(EXTRA_ACCOUNT_KEY); + final String listId = args.getString(EXTRA_LIST_ID); final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); final String screenName = args.getString(EXTRA_SCREEN_NAME); final String listName = args.getString(EXTRA_LIST_NAME); @@ -67,32 +66,113 @@ public class UserListMembersFragment extends CursorSupportUsersListFragment { @Override public void onActivityCreated(final Bundle savedInstanceState) { - final Bundle args = getArguments(); - if (savedInstanceState != null) { - mUserList = savedInstanceState.getParcelable(EXTRA_USER_LIST); - } else if (args != null) { - mUserList = args.getParcelable(EXTRA_USER_LIST); - } super.onActivityCreated(savedInstanceState); + registerForContextMenu(getRecyclerView()); } @Override public void onSaveInstanceState(final Bundle outState) { - outState.putParcelable(EXTRA_USER_LIST, mUserList); + outState.putParcelable(EXTRA_USER_LIST, getUserList()); super.onSaveInstanceState(outState); } @Override public void onStart() { super.onStart(); - final IntentFilter filter = new IntentFilter(BROADCAST_USER_LIST_MEMBERS_DELETED); - registerReceiver(mStatusReceiver, filter); + mBus.register(this); } @Override public void onStop() { - unregisterReceiver(mStatusReceiver); + mBus.unregister(this); super.onStop(); } + @Override + public boolean onUserLongClick(UserViewHolder holder, int position) { + return getRecyclerView().showContextMenuForChild(holder.itemView); + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + if (!getUserVisibleHint() || menuInfo == null) return; + final ParcelableUserList userList = getUserList(); + if (userList == null) return; + final Bundle args = getArguments(); + final UserKey accountId = args.getParcelable(EXTRA_ACCOUNT_KEY); + final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); + if (accountId == null || !accountId.equals(userKey)) return; + final ParcelableUsersAdapter adapter = getAdapter(); + final MenuInflater inflater = new MenuInflater(getContext()); + final ExtendedRecyclerView.ContextMenuInfo contextMenuInfo = + (ExtendedRecyclerView.ContextMenuInfo) menuInfo; + inflater.inflate(R.menu.action_user_list_member, menu); + final ParcelableUser user = adapter.getUser(contextMenuInfo.getPosition()); + menu.setHeaderTitle(mUserColorNameManager.getDisplayName(user, mPreferences.getBoolean(KEY_NAME_FIRST))); + } + + @Override + public boolean onContextItemSelected(MenuItem item) { + if (!getUserVisibleHint()) return false; + final ParcelableUserList userList = getUserList(); + if (userList == null) return false; + final ExtendedRecyclerView.ContextMenuInfo contextMenuInfo = + (ExtendedRecyclerView.ContextMenuInfo) item.getMenuInfo(); + final ParcelableUser user = getAdapter().getUser(contextMenuInfo.getPosition()); + if (user == null) return false; + switch (item.getItemId()) { + case R.id.delete_from_list: { + DeleteUserListMembersDialogFragment.show(getFragmentManager(), getUserList(), user); + return true; + } + } + return false; + } + + public ParcelableUserList getUserList() { + Fragment parent = getParentFragment(); + if (parent instanceof UserListFragment) { + return ((UserListFragment) parent).getUserList(); + } + return null; + } + + @Subscribe + public void onUserListMembersChanged(UserListMembersChangedEvent event) { + ParcelableUserList userList = event.getUserList(); + final Bundle args = getArguments(); + final UserKey accountId = args.getParcelable(EXTRA_ACCOUNT_KEY); + final String listId = args.getString(EXTRA_LIST_ID); + final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); + final String screenName = args.getString(EXTRA_SCREEN_NAME); + final String listName = args.getString(EXTRA_LIST_NAME); + if (!ParcelableUserListUtils.check(userList, accountId, listId, userKey, screenName, listName)) { + return; + } + switch (event.getAction()) { + case UserListMembersChangedEvent.Action.ADDED: { + final ParcelableUsersAdapter adapter = getAdapter(); + final List newUsers = Arrays.asList(event.getUsers()); + final List users = adapter.getData(); + users.removeAll(newUsers); + users.addAll(0, newUsers); + for (int i = 0, j = users.size(); i < j; i++) { + users.get(i).position = i; + } + adapter.notifyDataSetChanged(); + break; + } + case UserListMembersChangedEvent.Action.REMOVED: { + final ParcelableUsersAdapter adapter = getAdapter(); + final List removedUsers = Arrays.asList(event.getUsers()); + final List users = adapter.getData(); + users.removeAll(removedUsers); + for (int i = 0, j = users.size(); i < j; i++) { + users.get(i).position = i; + } + adapter.notifyDataSetChanged(); + break; + } + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListSubscribersFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListSubscribersFragment.java index 17d33f43d..07e4a18c1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListSubscribersFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListSubscribersFragment.java @@ -31,7 +31,7 @@ public class UserListSubscribersFragment extends CursorSupportUsersListFragment @Override public CursorSupportUsersLoader onCreateUsersLoader(final Context context, @NonNull final Bundle args, boolean fromUser) { - final long listId = args.getLong(EXTRA_LIST_ID, -1); + final String listId = args.getString(EXTRA_LIST_ID); final UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY); final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); final String screenName = args.getString(EXTRA_SCREEN_NAME); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListTimelineFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListTimelineFragment.java index ea04d6b8e..12b97285b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListTimelineFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListTimelineFragment.java @@ -52,7 +52,7 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment { final boolean fromUser) { setRefreshing(true); if (args == null) return null; - final long listId = args.getLong(EXTRA_LIST_ID, -1); + final String listId = args.getString(EXTRA_LIST_ID); final UserKey accountKey = Utils.getAccountKey(context, args); final String maxId = args.getString(EXTRA_MAX_ID); final String sinceId = args.getString(EXTRA_SINCE_ID); @@ -71,14 +71,14 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment { final Bundle args = getArguments(); assert args != null; final UserKey accountKey = Utils.getAccountKey(getContext(), args); - final long listId = args.getLong(EXTRA_LIST_ID, -1); + final String listId = args.getString(EXTRA_LIST_ID); final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); final String screenName = args.getString(EXTRA_SCREEN_NAME); final String listName = args.getString(EXTRA_LIST_NAME); final List result = new ArrayList<>(); result.add(AUTHORITY_USER_LIST_TIMELINE); result.add("account=" + accountKey); - if (listId > 0) { + if (listId != null) { result.add("list_id=" + listId); } else if (listName != null) { if (userKey != null) { @@ -100,9 +100,9 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment { final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1); StringBuilder sb = new StringBuilder("user_list_"); if (tabPosition < 0) return null; - final long listId = args.getLong(EXTRA_LIST_ID, -1); + final String listId = args.getString(EXTRA_LIST_ID); final String listName = args.getString(EXTRA_LIST_NAME); - if (listId > 0) { + if (listId != null) { sb.append(listId); } else if (listName != null) { final UserKey userKey = args.getParcelable(EXTRA_USER_KEY); diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListsFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListsFragment.java index f4a82e326..8dccfa771 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListsFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListsFragment.java @@ -114,7 +114,7 @@ public class UserListsFragment extends ParcelableUserListsFragment { removeUserList(event.userList.id); } - private void removeUserList(final long id) { + private void removeUserList(final String id) { final ParcelableUserListsAdapter adapter = getAdapter(); // final int listsIdx = adapter.findItemPosition(id); // if (listsIdx >= 0) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListMembersLoader.java b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListMembersLoader.java index 3015d17db..fd7008c78 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListMembersLoader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListMembersLoader.java @@ -35,11 +35,11 @@ import java.util.List; public class UserListMembersLoader extends CursorSupportUsersLoader { - private final long mListId; + private final String mListId; private final UserKey mUserKey; private final String mScreenName, mListName; - public UserListMembersLoader(final Context context, final UserKey accountKey, final long listId, + public UserListMembersLoader(final Context context, final UserKey accountKey, final String listId, final UserKey userKey, final String screenName, final String listName, final List data, boolean fromUser) { super(context, accountKey, data, fromUser); @@ -53,7 +53,7 @@ public class UserListMembersLoader extends CursorSupportUsersLoader { @Override public PageableResponseList getCursoredUsers(@NonNull final Twitter twitter, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws TwitterException { - if (mListId > 0) + if (mListId != null) return twitter.getUserListMembers(mListId, paging); else if (mUserKey != null) return twitter.getUserListMembers(mListName.replace(' ', '-'), mUserKey.getId(), paging); diff --git a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListSubscribersLoader.java b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListSubscribersLoader.java index b0283ab44..675e67dd9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListSubscribersLoader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListSubscribersLoader.java @@ -35,11 +35,11 @@ import java.util.List; public class UserListSubscribersLoader extends CursorSupportUsersLoader { - private final long mListId; + private final String mListId; private final UserKey mUserKey; private final String mScreenName, mListName; - public UserListSubscribersLoader(final Context context, final UserKey accountKey, final long listId, + public UserListSubscribersLoader(final Context context, final UserKey accountKey, final String listId, final UserKey userKey, final String screenName, final String listName, final List data, boolean fromUser) { super(context, accountKey, data, fromUser); @@ -53,7 +53,7 @@ public class UserListSubscribersLoader extends CursorSupportUsersLoader { @Override public PageableResponseList getCursoredUsers(@NonNull final Twitter twitter, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws TwitterException { - if (mListId > 0) + if (mListId != null) return twitter.getUserListSubscribers(mListId, paging); else if (mUserKey != null) return twitter.getUserListSubscribers(mListName.replace(' ', '-'), mUserKey.getId(), paging); diff --git a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListTimelineLoader.java b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListTimelineLoader.java index 21cca5ebe..f0fb288ea 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/loader/UserListTimelineLoader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/loader/UserListTimelineLoader.java @@ -40,9 +40,9 @@ public class UserListTimelineLoader extends TwitterAPIStatusesLoader { private final UserKey mUserKey; private final String mScreenName, mListName; - private final long mListId; + private final String mListId; - public UserListTimelineLoader(final Context context, final UserKey accountKey, final long listId, + public UserListTimelineLoader(final Context context, final UserKey accountKey, final String listId, final UserKey userKey, final String screenName, final String listName, final String sinceId, final String maxId, final List data, final String[] savedStatusesArgs, final int tabPosition, boolean fromUser, boolean loadingMore) { @@ -56,7 +56,7 @@ public class UserListTimelineLoader extends TwitterAPIStatusesLoader { @NonNull @Override protected ResponseList getStatuses(@NonNull final Twitter twitter, @NonNull ParcelableCredentials credentials, @NonNull final Paging paging) throws TwitterException { - if (mListId > 0) + if (mListId != null) return twitter.getUserListStatuses(mListId, paging); else if (mListName == null) throw new TwitterException("No list name or id given"); diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/message/UserListMembersChangedEvent.java b/twidere/src/main/java/org/mariotaku/twidere/model/message/UserListMembersChangedEvent.java new file mode 100644 index 000000000..b9b6906e1 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/model/message/UserListMembersChangedEvent.java @@ -0,0 +1,49 @@ +package org.mariotaku.twidere.model.message; + +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; + +import org.mariotaku.twidere.model.ParcelableUser; +import org.mariotaku.twidere.model.ParcelableUserList; + +/** + * Created by mariotaku on 16/3/30. + */ +public class UserListMembersChangedEvent { + + @Action + private final int action; + @NonNull + private final ParcelableUserList userList; + @NonNull + private final ParcelableUser[] users; + + public UserListMembersChangedEvent(@Action int action, @NonNull ParcelableUserList userList, + @NonNull ParcelableUser[] users) { + this.action = action; + this.userList = userList; + this.users = users; + } + + @Action + public int getAction() { + return action; + } + + @NonNull + public ParcelableUserList getUserList() { + return userList; + } + + @NonNull + public ParcelableUser[] getUsers() { + return users; + } + + @IntDef({Action.ADDED, Action.REMOVED}) + public @interface Action { + int ADDED = 1; + int REMOVED = 2; + } + +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserListArguments.java b/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserListArguments.java index 8472792dd..59a681b43 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserListArguments.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/tab/argument/UserListArguments.java @@ -12,20 +12,20 @@ import com.bluelinelabs.logansquare.annotation.JsonObject; @JsonObject public class UserListArguments extends TabArguments { @JsonField(name = "list_id") - long listId; + String listId; - public long getListId() { + public String getListId() { return listId; } - public void setListId(long listId) { + public void setListId(String listId) { this.listId = listId; } @Override public void copyToBundle(@NonNull Bundle bundle) { super.copyToBundle(bundle); - bundle.putLong(EXTRA_LIST_ID, listId); + bundle.putString(EXTRA_LIST_ID, listId); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableUserListUtils.java b/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableUserListUtils.java index d0348da10..5ff3fbc86 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableUserListUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/util/ParcelableUserListUtils.java @@ -1,5 +1,7 @@ package org.mariotaku.twidere.model.util; +import android.text.TextUtils; + import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.api.twitter.model.UserList; import org.mariotaku.twidere.model.ParcelableUserList; @@ -42,4 +44,20 @@ public class ParcelableUserListUtils { } return result; } + + public static boolean check(ParcelableUserList userList, UserKey accountKey, String listId, + UserKey userKey, String screenName, String listName) { + if (!userList.account_key.equals(accountKey)) return false; + if (listId != null) { + return TextUtils.equals(listId, userList.id); + } else if (listName != null) { + if (!TextUtils.equals(listName, userList.name)) return false; + if (userKey != null) { + return userKey.equals(userList.user_key); + } else if (screenName != null) { + return TextUtils.equals(screenName, userList.user_screen_name); + } + } + return false; + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java index 9bd3acb9a..7e907194a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/AsyncTwitterWrapper.java @@ -75,6 +75,7 @@ import org.mariotaku.twidere.model.message.StatusListChangedEvent; import org.mariotaku.twidere.model.message.StatusRetweetedEvent; import org.mariotaku.twidere.model.message.UserListCreatedEvent; import org.mariotaku.twidere.model.message.UserListDestroyedEvent; +import org.mariotaku.twidere.model.message.UserListMembersChangedEvent; import org.mariotaku.twidere.model.message.UserListSubscriptionEvent; import org.mariotaku.twidere.model.message.UserListUpdatedEvent; import org.mariotaku.twidere.model.message.UsersBlockedEvent; @@ -158,7 +159,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper { } } - public int addUserListMembersAsync(final UserKey accountKey, final long listId, final ParcelableUser... users) { + public int addUserListMembersAsync(final UserKey accountKey, final String listId, @NonNull final ParcelableUser... users) { final AddUserListMembersTask task = new AddUserListMembersTask(accountKey, listId, users); return mAsyncTaskManager.add(task, true); } @@ -225,12 +226,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper { return mAsyncTaskManager.add(task, true); } - public int createUserListSubscriptionAsync(final UserKey accountKey, final long listId) { + public int createUserListSubscriptionAsync(final UserKey accountKey, final String listId) { final CreateUserListSubscriptionTask task = new CreateUserListSubscriptionTask(accountKey, listId); return mAsyncTaskManager.add(task, true); } - public int deleteUserListMembersAsync(final UserKey accountKey, final long listId, final ParcelableUser... users) { + public int deleteUserListMembersAsync(final UserKey accountKey, final String listId, final ParcelableUser... users) { final DeleteUserListMembersTask task = new DeleteUserListMembersTask(accountKey, listId, users); return mAsyncTaskManager.add(task, true); } @@ -284,12 +285,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper { return mAsyncTaskManager.add(task, true); } - public int destroyUserListAsync(final UserKey accountKey, final long listId) { + public int destroyUserListAsync(final UserKey accountKey, final String listId) { final DestroyUserListTask task = new DestroyUserListTask(mContext, accountKey, listId); return mAsyncTaskManager.add(task, true); } - public int destroyUserListSubscriptionAsync(final UserKey accountKey, final long listId) { + public int destroyUserListSubscriptionAsync(final UserKey accountKey, final String listId) { final DestroyUserListSubscriptionTask task = new DestroyUserListSubscriptionTask(accountKey, listId); return mAsyncTaskManager.add(task, true); } @@ -470,7 +471,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper { return 0; } - public int updateUserListDetails(final UserKey accountKey, final long listId, + public int updateUserListDetails(final UserKey accountKey, final String listId, final UserListUpdate update) { final UpdateUserListDetailsTask task = new UpdateUserListDetailsTask(mContext, accountKey, listId, update); @@ -602,26 +603,29 @@ public class AsyncTwitterWrapper extends TwitterWrapper { class AddUserListMembersTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long listId; - private final ParcelableUser[] users; + private final String mListId; + @NonNull + private final ParcelableUser[] mUsers; - public AddUserListMembersTask(final UserKey accountKey, final long listId, final ParcelableUser[] users) { + public AddUserListMembersTask(@NonNull final UserKey accountKey, + final String listId, + @NonNull final ParcelableUser[] users) { super(mContext); this.mAccountKey = accountKey; - this.listId = listId; - this.users = users; + this.mListId = listId; + this.mUsers = users; } @Override protected SingleResponse doInBackground(final Object... params) { final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey, false); - if (twitter == null || users == null) return SingleResponse.getInstance(); + if (twitter == null) return SingleResponse.getInstance(); try { - final UserKey[] userIds = new UserKey[users.length]; - for (int i = 0, j = users.length; i < j; i++) { - userIds[i] = users[i].key; + final UserKey[] userIds = new UserKey[mUsers.length]; + for (int i = 0, j = mUsers.length; i < j; i++) { + userIds[i] = mUsers[i].key; } - final UserList result = twitter.addUserListMembers(listId, UserKey.getIds(userIds)); + final UserList result = twitter.addUserListMembers(mListId, UserKey.getIds(userIds)); final ParcelableUserList list = ParcelableUserListUtils.from(result, mAccountKey); return SingleResponse.getInstance(list, null); } catch (final TwitterException e) { @@ -631,28 +635,26 @@ public class AsyncTwitterWrapper extends TwitterWrapper { @Override protected void onPostExecute(final SingleResponse result) { - final boolean succeed = result.hasData() && result.getData().id > 0; + final boolean succeed = result.hasData(); if (succeed) { final String message; - if (users.length == 1) { - final ParcelableUser user = users[0]; + if (mUsers.length == 1) { + final ParcelableUser user = mUsers[0]; final boolean nameFirst = mPreferences.getBoolean(KEY_NAME_FIRST); final String displayName = mUserColorNameManager.getDisplayName(user.key, user.name, user.screen_name, nameFirst); message = mContext.getString(R.string.added_user_to_list, displayName, result.getData().name); } else { final Resources res = mContext.getResources(); - message = res.getQuantityString(R.plurals.added_N_users_to_list, users.length, users.length, + message = res.getQuantityString(R.plurals.added_N_users_to_list, mUsers.length, mUsers.length, result.getData().name); } Utils.showOkMessage(mContext, message, false); } else { Utils.showErrorMessage(mContext, R.string.action_adding_member, result.getException(), true); } - final Intent intent = new Intent(BROADCAST_USER_LIST_MEMBERS_ADDED); - intent.putExtra(EXTRA_USER_LIST, result.getData()); - intent.putExtra(EXTRA_USERS, users); - mContext.sendBroadcast(intent); + bus.post(new UserListMembersChangedEvent(UserListMembersChangedEvent.Action.ADDED, + result.getData(), mUsers)); super.onPostExecute(result); } @@ -887,12 +889,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper { class CreateUserListSubscriptionTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long listId; + private final String mListId; - public CreateUserListSubscriptionTask(final UserKey accountKey, final long listId) { + public CreateUserListSubscriptionTask(final UserKey accountKey, final String listId) { super(mContext); this.mAccountKey = accountKey; - this.listId = listId; + this.mListId = listId; } @Override @@ -900,7 +902,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper { final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey, false); if (twitter == null) return SingleResponse.getInstance(); try { - final UserList userList = twitter.createUserListSubscription(listId); + final UserList userList = twitter.createUserListSubscription(mListId); final ParcelableUserList list = ParcelableUserListUtils.from(userList, mAccountKey); return SingleResponse.getInstance(list); } catch (final TwitterException e) { @@ -975,10 +977,10 @@ public class AsyncTwitterWrapper extends TwitterWrapper { class DeleteUserListMembersTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long mUserListId; + private final String mUserListId; private final ParcelableUser[] users; - public DeleteUserListMembersTask(final UserKey accountKey, final long userListId, final ParcelableUser[] users) { + public DeleteUserListMembersTask(final UserKey accountKey, final String userListId, final ParcelableUser[] users) { super(mContext); mAccountKey = accountKey; mUserListId = userListId; @@ -1004,7 +1006,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper { @Override protected void onPostExecute(final SingleResponse result) { - final boolean succeed = result.hasData() && result.getData().id > 0; + final boolean succeed = result.hasData(); final String message; if (succeed) { if (users.length == 1) { @@ -1019,11 +1021,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper { message = res.getQuantityString(R.plurals.deleted_N_users_from_list, users.length, users.length, result.getData().name); } + bus.post(new UserListMembersChangedEvent(UserListMembersChangedEvent.Action.REMOVED, + result.getData(), users)); Utils.showInfoMessage(mContext, message, false); - final Intent intent = new Intent(BROADCAST_USER_LIST_MEMBERS_DELETED); - intent.putExtra(EXTRA_USER_LIST, result.getData()); - intent.putExtra(EXTRA_USERS, users); - mContext.sendBroadcast(intent); } else { Utils.showErrorMessage(mContext, R.string.action_deleting, result.getException(), true); } @@ -1342,9 +1342,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper { class DestroyUserListSubscriptionTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long mListId; + private final String mListId; - public DestroyUserListSubscriptionTask(@NonNull final UserKey accountKey, final long listId) { + public DestroyUserListSubscriptionTask(@NonNull final UserKey accountKey, final String listId) { super(mContext); mAccountKey = accountKey; mListId = listId; @@ -1383,9 +1383,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper { static class DestroyUserListTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long mListId; + private final String mListId; - public DestroyUserListTask(Context context, final UserKey accountKey, final long listId) { + public DestroyUserListTask(Context context, final UserKey accountKey, final String listId) { super(context); mAccountKey = accountKey; mListId = listId; @@ -1570,12 +1570,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper { static class UpdateUserListDetailsTask extends ManagedAsyncTask> { private final UserKey mAccountKey; - private final long listId; + private final String listId; private final UserListUpdate update; private Context mContext; public UpdateUserListDetailsTask(Context context, final UserKey accountKey, - final long listId, UserListUpdate update) { + final String listId, UserListUpdate update) { super(context); this.mAccountKey = accountKey; this.listId = listId; diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/IntentUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/IntentUtils.java index 744737561..2acf5e185 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/IntentUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/IntentUtils.java @@ -480,7 +480,8 @@ public class IntentUtils implements Constants { } public static void openUserListDetails(@NonNull final Context context, - @Nullable final UserKey accountKey, final long listId, + @Nullable final UserKey accountKey, + @Nullable final String listId, @Nullable final UserKey userId, @Nullable final String screenName, final String listName) { final Uri.Builder builder = new Uri.Builder(); @@ -489,8 +490,8 @@ public class IntentUtils implements Constants { if (accountKey != null) { builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, accountKey.toString()); } - if (listId > 0) { - builder.appendQueryParameter(QUERY_PARAM_LIST_ID, String.valueOf(listId)); + if (listId != null) { + builder.appendQueryParameter(QUERY_PARAM_LIST_ID, listId); } if (userId != null) { builder.appendQueryParameter(QUERY_PARAM_USER_KEY, userId.toString()); @@ -508,7 +509,7 @@ public class IntentUtils implements Constants { public static void openUserListDetails(@NonNull final Context context, @NonNull final ParcelableUserList userList) { final UserKey userKey = userList.user_key; - final long listId = userList.id; + final String listId = userList.id; final Bundle extras = new Bundle(); extras.putParcelable(EXTRA_USER_LIST, userList); final Uri.Builder builder = new Uri.Builder(); @@ -516,7 +517,7 @@ public class IntentUtils implements Constants { builder.authority(AUTHORITY_USER_LIST); builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, userList.account_key.toString()); builder.appendQueryParameter(QUERY_PARAM_USER_KEY, userKey.toString()); - builder.appendQueryParameter(QUERY_PARAM_LIST_ID, String.valueOf(listId)); + builder.appendQueryParameter(QUERY_PARAM_LIST_ID, listId); final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build()); intent.setExtrasClassLoader(context.getClassLoader()); intent.putExtras(extras); diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java b/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java index a0c9369a7..96597c73b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/OnLinkClickHandler.java @@ -122,7 +122,7 @@ public class OnLinkClickHandler implements OnLinkClickListener, Constants { if (mentionList.length != 2) { break; } - IntentUtils.openUserListDetails(context, accountKey, -1, null, mentionList[0], + IntentUtils.openUserListDetails(context, accountKey, null, null, mentionList[0], mentionList[1]); break; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java index abfda1d2d..987b5edb9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -640,7 +640,7 @@ public final class Utils implements Constants { && isEmpty(paramListId)) { return null; } - args.putLong(EXTRA_LIST_ID, NumberUtils.toLong(paramListId, -1)); + args.putString(EXTRA_LIST_ID, paramListId); args.putParcelable(EXTRA_USER_KEY, paramUserKey); args.putString(EXTRA_SCREEN_NAME, paramScreenName); args.putString(EXTRA_LIST_NAME, paramListName); @@ -691,7 +691,7 @@ public final class Utils implements Constants { && isEmpty(paramListId)) { return null; } - args.putLong(EXTRA_LIST_ID, NumberUtils.toLong(paramListId, -1)); + args.putString(EXTRA_LIST_ID, paramListId); args.putParcelable(EXTRA_USER_KEY, paramUserKey); args.putString(EXTRA_SCREEN_NAME, paramScreenName); args.putString(EXTRA_LIST_NAME, paramListName); @@ -706,7 +706,7 @@ public final class Utils implements Constants { if ((isEmpty(paramListName) || isEmpty(paramScreenName) && paramUserKey == null) && isEmpty(paramListId)) return null; - args.putLong(EXTRA_LIST_ID, NumberUtils.toLong(paramListId, -1)); + args.putString(EXTRA_LIST_ID, paramListId); args.putParcelable(EXTRA_USER_KEY, paramUserKey); args.putString(EXTRA_SCREEN_NAME, paramScreenName); args.putString(EXTRA_LIST_NAME, paramListName); @@ -721,7 +721,7 @@ public final class Utils implements Constants { if (isEmpty(paramListId) && (isEmpty(paramListName) || isEmpty(paramScreenName) && paramUserKey == null)) return null; - args.putLong(EXTRA_LIST_ID, NumberUtils.toLong(paramListId, -1)); + args.putString(EXTRA_LIST_ID, paramListId); args.putParcelable(EXTRA_USER_KEY, paramUserKey); args.putString(EXTRA_SCREEN_NAME, paramScreenName); args.putString(EXTRA_LIST_NAME, paramListName); diff --git a/twidere/src/main/res/layout/card_item_activity_summary_common.xml b/twidere/src/main/res/layout/card_item_activity_summary_common.xml index 44fea33c6..25771de71 100644 --- a/twidere/src/main/res/layout/card_item_activity_summary_common.xml +++ b/twidere/src/main/res/layout/card_item_activity_summary_common.xml @@ -33,7 +33,8 @@ android:layout_alignTop="@+id/profile_images_container" android:padding="@dimen/element_spacing_small" android:scaleType="centerInside" - tools:src="@drawable/ic_indicator_retweet"/> + tools:src="@drawable/ic_indicator_retweet" + tools:tint="@color/highlight_retweet"/> + android:contentDescription="@string/profile_image" + tools:src="@mipmap/ic_launcher"/> + android:contentDescription="@string/profile_image" + tools:src="@mipmap/ic_launcher_hondajojo"/> + android:contentDescription="@string/profile_image" + tools:src="@mipmap/ic_launcher"/> + android:contentDescription="@string/profile_image" + tools:src="@mipmap/ic_launcher_hondajojo"/> + android:contentDescription="@string/profile_image" + tools:src="@mipmap/ic_launcher"/> diff --git a/twidere/src/main/res/menu/action_user_list_member.xml b/twidere/src/main/res/menu/action_user_list_member.xml index 60d28980b..a6311f60a 100644 --- a/twidere/src/main/res/menu/action_user_list_member.xml +++ b/twidere/src/main/res/menu/action_user_list_member.xml @@ -3,7 +3,7 @@ \ No newline at end of file From 8406a55f0160912b92f55fc3b1000444ec404000 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Wed, 30 Mar 2016 21:31:12 +0800 Subject: [PATCH 8/8] improved trends location dialog --- .../twidere/api/twitter/model/Location.java | 38 ++- .../preference/TrendsLocationPreference.java | 279 +++++++++++++----- .../dialog_trends_location_selector.xml | 12 + twidere/src/main/res/values/strings.xml | 1 + 4 files changed, 255 insertions(+), 75 deletions(-) create mode 100644 twidere/src/main/res/layout/dialog_trends_location_selector.xml diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/Location.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/Location.java index 16abb390c..633a212cf 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/Location.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/Location.java @@ -30,12 +30,14 @@ public class Location { @JsonField(name = "woeid") int woeid; + @JsonField(name = "parentid") + int parentId; @JsonField(name = "country") String countryName; @JsonField(name = "countryCode") String countryCode; @JsonField(name = "placeType") - PlaceTypeImpl placeType; + PlaceType placeType; @JsonField(name = "name") String name; @JsonField(name = "url") @@ -45,6 +47,10 @@ public class Location { return woeid; } + public long getParentId() { + return parentId; + } + public String getCountryName() { return countryName; } @@ -53,7 +59,7 @@ public class Location { return countryCode; } - public PlaceTypeImpl getPlaceType() { + public PlaceType getPlaceType() { return placeType; } @@ -65,11 +71,27 @@ public class Location { return url; } - @JsonObject - public static class PlaceTypeImpl { + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Location location = (Location) o; + + return woeid == location.woeid; + + } + + @Override + public int hashCode() { + return woeid; + } + + @JsonObject + public static class PlaceType { @JsonField(name = "name") String name; + @JsonField(name = "code") int code; @@ -80,5 +102,13 @@ public class Location { public String getName() { return name; } + + @Override + public String toString() { + return "PlaceType{" + + "name='" + name + '\'' + + ", code=" + code + + '}'; + } } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/preference/TrendsLocationPreference.java b/twidere/src/main/java/org/mariotaku/twidere/preference/TrendsLocationPreference.java index 0865a8d0d..40b9ced5e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/preference/TrendsLocationPreference.java +++ b/twidere/src/main/java/org/mariotaku/twidere/preference/TrendsLocationPreference.java @@ -19,42 +19,47 @@ package org.mariotaku.twidere.preference; -import android.app.AlertDialog; +import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; import android.os.AsyncTask; +import android.support.annotation.Nullable; +import android.support.v4.util.LongSparseArray; +import android.support.v4.util.SimpleArrayMap; +import android.support.v7.app.AlertDialog; import android.support.v7.preference.Preference; import android.util.AttributeSet; import android.util.Log; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListView; +import android.widget.BaseExpandableListAdapter; +import android.widget.ExpandableListView; import android.widget.TextView; +import org.mariotaku.twidere.BuildConfig; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.api.twitter.Twitter; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.model.Location; -import org.mariotaku.twidere.api.twitter.model.ResponseList; import org.mariotaku.twidere.util.TwitterAPIFactory; import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Locale; -public class TrendsLocationPreference extends Preference implements Constants, OnClickListener { - - private int mCheckedWoeId = 1; +public class TrendsLocationPreference extends Preference implements Constants { + private static final long EMPTY = 0; + private static final long WORLDWIDE = 1; + private final ExpandableTrendLocationsListAdapter mAdapter; private GetAvailableTrendsTask mGetAvailableTrendsTask; - - private final AvailableTrendsAdapter mAdapter; - private AlertDialog mDialog; public TrendsLocationPreference(final Context context) { @@ -67,23 +72,11 @@ public class TrendsLocationPreference extends Preference implements Constants, O public TrendsLocationPreference(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); - mAdapter = new AvailableTrendsAdapter(context); - } - - @Override - public void onClick(final DialogInterface dialog, final int which) { - final Location item = mAdapter.getItem(which); - if (item != null) { - persistInt(item.getWoeid()); - } - if (mDialog != null && mDialog.isShowing()) { - mDialog.dismiss(); - } + mAdapter = new ExpandableTrendLocationsListAdapter(context); } @Override protected void onClick() { - mCheckedWoeId = getPersistedInt(1); if (mGetAvailableTrendsTask != null) { mGetAvailableTrendsTask.cancel(false); } @@ -91,64 +84,178 @@ public class TrendsLocationPreference extends Preference implements Constants, O mGetAvailableTrendsTask.execute(); } - private static class AvailableTrendsAdapter extends ArrayAdapter { + static class ExpandableTrendLocationsListAdapter extends BaseExpandableListAdapter { - private final Context mContext; + private final LayoutInflater mInflater; + @Nullable + SimpleArrayMap> mData; - public AvailableTrendsAdapter(final Context context) { - super(context, android.R.layout.simple_list_item_single_choice); - mContext = context; - } - - public int findItemPosition(final int woeid) { - final int count = getCount(); - for (int i = 0; i < count; i++) { - final Location item = getItem(i); - if (item.getWoeid() == woeid) return i; - } - return -1; + public ExpandableTrendLocationsListAdapter(Context context) { + mInflater = LayoutInflater.from(context); } @Override - public View getView(final int position, final View convertView, final ViewGroup parent) { - final View view = super.getView(position, convertView, parent); - final TextView text = (TextView) (view instanceof TextView ? view : view.findViewById(android.R.id.text1)); - final Location item = getItem(position); - if (item != null && text != null) { - text.setSingleLine(); - text.setText(item.getName()); + public int getGroupCount() { + if (mData == null) return 0; + return mData.size(); + } + + @Override + public int getChildrenCount(int groupPosition) { + if (mData == null) return 0; + return mData.valueAt(groupPosition).size(); + } + + @Override + public Location getGroup(int groupPosition) { + assert mData != null; + return mData.keyAt(groupPosition); + } + + @Override + public Location getChild(int groupPosition, int childPosition) { + assert mData != null; + return mData.valueAt(groupPosition).get(childPosition); + } + + @Override + public long getGroupId(int groupPosition) { + return getGroup(groupPosition).getWoeid(); + } + + @Override + public long getChildId(int groupPosition, int childPosition) { + return getChild(groupPosition, childPosition).getWoeid(); + } + + @Override + public boolean hasStableIds() { + return true; + } + + @Override + public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { + View view; + if (convertView != null) { + view = convertView; + } else { + view = mInflater.inflate(android.R.layout.simple_expandable_list_item_1, parent, false); + } + ((TextView) view.findViewById(android.R.id.text1)).setText(getGroup(groupPosition).getName()); + return view; + } + + @Override + public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { + View view; + if (convertView != null) { + view = convertView; + } else { + view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false); + } + final Location location = getChild(groupPosition, childPosition); + final TextView text1 = (TextView) view.findViewById(android.R.id.text1); + if (location.getParentId() == 1) { + text1.setText(R.string.location_countrywide); + } else { + text1.setText(location.getName()); } return view; } - public void setData(final List data) { - clear(); - if (data != null) { - addAll(data); - } - sort(new LocationComparator(mContext)); + @Override + public boolean isChildSelectable(int groupPosition, int childPosition) { + return true; } + public void setData(@Nullable SimpleArrayMap> data) { + mData = data; + notifyDataSetChanged(); + } + } + + static class LocationsMap { + + final LongSparseArray> map = new LongSparseArray<>(); + final LongSparseArray parents = new LongSparseArray<>(); + private final LocationComparator comparator; + + LocationsMap(Locale locale) { + comparator = new LocationComparator(Collator.getInstance(locale)); + } + + void put(Location location) { + final long parentId = location.getParentId(); + if (parentId == EMPTY || parentId == WORLDWIDE) { + putParent(location); + } else { + putChild(parentId, location); + } + } + + void putParent(Location location) { + final long woeid = location.getWoeid(); + parents.put(woeid, location); + final List list = getList(woeid); + // Don't add child for 'worldwide' + if (woeid != WORLDWIDE) { + addToList(list, location); + } + } + + void putChild(long parentId, Location location) { + addToList(getList(parentId), location); + } + + List getList(long parentId) { + List list = map.get(parentId); + if (list == null) { + list = new ArrayList<>(); + map.put(parentId, list); + } + return list; + } + + void addToList(List list, Location location) { + int loc = Collections.binarySearch(list, location, comparator); + if (loc < 0) { + list.add(-(loc + 1), location); + } + } + + SimpleArrayMap> pack() { + SimpleArrayMap> result = new SimpleArrayMap<>(map.size()); + for (int i = 0, j = map.size(); i < j; i++) { + Location parent = parents.get(map.keyAt(i)); + if (parent == null) continue; + result.put(parent, map.valueAt(i)); + } + return result; + } } private static class LocationComparator implements Comparator { - private final Collator mCollator; + private final Collator collator; - LocationComparator(final Context context) { - mCollator = Collator.getInstance(context.getResources().getConfiguration().locale); + public LocationComparator(Collator collator) { + this.collator = collator; + } + + private boolean isCountryOrWorldwide(Location location) { + final long parentId = location.getParentId(); + return parentId == 0 || parentId == 1; } @Override - public int compare(final Location object1, final Location object2) { - if (object1.getWoeid() == 1) return Integer.MIN_VALUE; - if (object2.getWoeid() == 1) return Integer.MAX_VALUE; - return mCollator.compare(object1.getName(), object2.getName()); + public int compare(Location lhs, Location rhs) { + if (isCountryOrWorldwide(lhs)) return Integer.MIN_VALUE; + if (isCountryOrWorldwide(rhs)) return Integer.MAX_VALUE; + return collator.compare(lhs.getName(), rhs.getName()); } - } - class GetAvailableTrendsTask extends AsyncTask> implements OnCancelListener { - + class GetAvailableTrendsTask extends AsyncTask>> implements OnCancelListener { private final ProgressDialog mProgress; public GetAvailableTrendsTask(final Context context) { @@ -161,19 +268,25 @@ public class TrendsLocationPreference extends Preference implements Constants, O } @Override - protected ResponseList doInBackground(final Object... args) { + protected SimpleArrayMap> doInBackground(final Object... args) { final Twitter twitter = TwitterAPIFactory.getDefaultTwitterInstance(getContext(), false); if (twitter == null) return null; try { - return twitter.getAvailableTrends(); + LocationsMap map = new LocationsMap(Locale.getDefault()); + for (Location location : twitter.getAvailableTrends()) { + map.put(location); + } + return map.pack(); } catch (final TwitterException e) { - Log.w(LOGTAG, e); + if (BuildConfig.DEBUG) { + Log.w(LOGTAG, e); + } } return null; } @Override - protected void onPostExecute(final ResponseList result) { + protected void onPostExecute(final SimpleArrayMap> result) { if (mProgress.isShowing()) { mProgress.dismiss(); } @@ -181,14 +294,38 @@ public class TrendsLocationPreference extends Preference implements Constants, O if (result == null) return; final AlertDialog.Builder selectorBuilder = new AlertDialog.Builder(getContext()); selectorBuilder.setTitle(getTitle()); - selectorBuilder.setSingleChoiceItems(mAdapter, mAdapter.findItemPosition(mCheckedWoeId), - TrendsLocationPreference.this); + selectorBuilder.setView(R.layout.dialog_trends_location_selector); selectorBuilder.setNegativeButton(android.R.string.cancel, null); mDialog = selectorBuilder.create(); - final ListView lv = mDialog.getListView(); - if (lv != null) { - lv.setFastScrollEnabled(true); - } + mDialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialogInterface) { + final Dialog dialog = (Dialog) dialogInterface; + final ExpandableListView listView = (ExpandableListView) dialog.findViewById(R.id.expandable_list); + listView.setAdapter(mAdapter); + listView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { + @Override + public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { + final Location group = mAdapter.getGroup(groupPosition); + if (group.getWoeid() == WORLDWIDE) { + persistInt(group.getWoeid()); + dialog.dismiss(); + return true; + } + return false; + } + }); + listView.setOnChildClickListener(new ExpandableListView.OnChildClickListener() { + @Override + public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { + final Location child = mAdapter.getChild(groupPosition, childPosition); + persistInt(child.getWoeid()); + dialog.dismiss(); + return true; + } + }); + } + }); mDialog.show(); } diff --git a/twidere/src/main/res/layout/dialog_trends_location_selector.xml b/twidere/src/main/res/layout/dialog_trends_location_selector.xml new file mode 100644 index 000000000..7d4a8939f --- /dev/null +++ b/twidere/src/main/res/layout/dialog_trends_location_selector.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index f93613039..4afefd39f 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -785,4 +785,5 @@ Group Your coarse location + Countrywide \ No newline at end of file