diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/gnusocial/model/Attachment.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/gnusocial/model/Attachment.java index 04e916464..9cfc63653 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/gnusocial/model/Attachment.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/gnusocial/model/Attachment.java @@ -4,6 +4,8 @@ import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonObject; /** + * GNUSocial attachment model + * * Created by mariotaku on 16/1/26. */ @JsonObject diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterException.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterException.java index 2cd813d31..d1c184eb1 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterException.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterException.java @@ -108,6 +108,7 @@ public class TwitterException extends Exception implements TwitterResponse, Http /** * {@inheritDoc} */ + @AccessLevel @Override public int getAccessLevel() { return InternalParseUtil.toAccessLevel(httpResponse); diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/PageableResponseList.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/PageableResponseList.java index 49d960f57..eea6bf242 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/PageableResponseList.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/PageableResponseList.java @@ -42,6 +42,7 @@ public class PageableResponseList extends ArrayList implements TwitterResp } @Override + @AccessLevel public final int getAccessLevel() { return accessLevel; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/QueryResult.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/QueryResult.java index c756e1c2f..b50e7ac59 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/QueryResult.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/QueryResult.java @@ -45,6 +45,7 @@ public class QueryResult extends AbstractList implements TwitterResponse @JsonField(name = "statuses") ArrayList statuses; + @AccessLevel private int accessLevel; private RateLimitStatus rateLimitStatus; @@ -54,6 +55,7 @@ public class QueryResult extends AbstractList implements TwitterResponse accessLevel = InternalParseUtil.toAccessLevel(resp); } + @AccessLevel @Override public final int getAccessLevel() { return accessLevel; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/ResponseList.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/ResponseList.java index 1a9dea0a7..baf82492a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/ResponseList.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/ResponseList.java @@ -79,6 +79,7 @@ public class ResponseList extends AbstractList implements TwitterResponse accessLevel = InternalParseUtil.toAccessLevel(resp); } + @AccessLevel @Override public final int getAccessLevel() { return accessLevel; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusDeletionNotice.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusDeletionNotice.java deleted file mode 100644 index f9702e001..000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusDeletionNotice.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2015 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.mariotaku.twidere.api.twitter.model; - -import com.bluelinelabs.logansquare.annotation.JsonObject; - -/** - * Created by mariotaku on 15/5/26. - */ -@JsonObject -public class StatusDeletionNotice { - public long getStatusId() { - return 0; - } -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponse.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponse.java index 875398e4c..f6b8c72ae 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponse.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponse.java @@ -19,6 +19,8 @@ package org.mariotaku.twidere.api.twitter.model; +import android.support.annotation.IntDef; + import org.mariotaku.restfu.http.HttpResponse; /** @@ -32,16 +34,19 @@ import org.mariotaku.restfu.http.HttpResponse; */ public interface TwitterResponse { int NONE = 0; - int READ = 1; - int READ_WRITE = 2; int READ_WRITE_DIRECTMESSAGES = 3; void processResponseHeader(HttpResponse resp); + @AccessLevel int getAccessLevel(); RateLimitStatus getRateLimitStatus(); + @IntDef({NONE, READ, READ_WRITE, READ_WRITE_DIRECTMESSAGES}) + @interface AccessLevel { + + } } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponseObject.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponseObject.java index 63713168b..180017b49 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponseObject.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterResponseObject.java @@ -20,9 +20,6 @@ package org.mariotaku.twidere.api.twitter.model; import org.mariotaku.restfu.http.HttpResponse; - -import org.mariotaku.twidere.api.twitter.model.RateLimitStatus; -import org.mariotaku.twidere.api.twitter.model.TwitterResponse; import org.mariotaku.twidere.api.twitter.util.InternalParseUtil; /** @@ -30,6 +27,7 @@ import org.mariotaku.twidere.api.twitter.util.InternalParseUtil; */ public class TwitterResponseObject implements TwitterResponse { + @AccessLevel private int accessLevel; private RateLimitStatus rateLimitStatus; @@ -39,6 +37,7 @@ public class TwitterResponseObject implements TwitterResponse { accessLevel = InternalParseUtil.toAccessLevel(resp); } + @AccessLevel @Override public final int getAccessLevel() { return accessLevel; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/InternalParseUtil.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/InternalParseUtil.java index 4c902b643..225b9a970 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/InternalParseUtil.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/util/InternalParseUtil.java @@ -34,8 +34,9 @@ public final class InternalParseUtil { throw new AssertionError("This class should never be instantiated"); } + @TwitterResponse.AccessLevel public static int toAccessLevel(final HttpResponse res) { - if (null == res) return -1; + if (res == null) return TwitterResponse.NONE; final String xAccessLevel = res.getHeader("X-Access-Level"); int accessLevel; if (null == xAccessLevel) { diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableDirectMessage.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableDirectMessage.java index df78a6759..2fd1c8a5f 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableDirectMessage.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableDirectMessage.java @@ -34,7 +34,6 @@ import org.mariotaku.twidere.model.util.LoganSquareCursorFieldConverter; import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages; import java.util.Arrays; -import java.util.Comparator; @ParcelablePlease(allFields = false) @JsonObject 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 96d0e971e..ac939e550 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 @@ -14,8 +14,6 @@ import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease; import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease; import org.mariotaku.twidere.api.twitter.model.MediaEntity; -import org.mariotaku.twidere.api.twitter.model.MediaEntity.Size; -import org.mariotaku.twidere.util.TwitterContentUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java index 1cab56fdf..49372bb1d 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java @@ -19,6 +19,7 @@ public class InstagramProvider implements Provider { final String authority = PreviewMediaExtractor.getAuthority(link); if (authority == null) return false; switch (authority) { + //noinspection SpellCheckingInspection case "instagr.am": case "instagram.com": case "www.instagram.com": { diff --git a/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanDaydreamService.java b/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanDaydreamService.java index c9c9b1c1d..323a5d944 100644 --- a/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanDaydreamService.java +++ b/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanDaydreamService.java @@ -19,6 +19,7 @@ package org.mariotaku.twidere.nyan; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; @@ -28,6 +29,7 @@ import android.service.dreams.DreamService; import android.view.View; import android.view.View.OnSystemUiVisibilityChangeListener; +@SuppressLint("Registered") @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public class NyanDaydreamService extends DreamService implements NyanConstants, OnSharedPreferenceChangeListener, OnSystemUiVisibilityChangeListener { diff --git a/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanWallpaperService.java b/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanWallpaperService.java index 5a0c0775f..7607b5f3c 100644 --- a/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanWallpaperService.java +++ b/twidere.component.nyan/src/main/java/org/mariotaku/twidere/nyan/NyanWallpaperService.java @@ -19,6 +19,7 @@ package org.mariotaku.twidere.nyan; +import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -30,6 +31,7 @@ import android.os.PowerManager; import android.service.wallpaper.WallpaperService; import android.view.SurfaceHolder; +@SuppressLint("Registered") public class NyanWallpaperService extends WallpaperService implements NyanConstants { @Override diff --git a/twidere.donate.nyanwp.wear/src/main/AndroidManifest.xml b/twidere.donate.nyanwp.wear/src/main/AndroidManifest.xml index dde69e977..663bc09f4 100644 --- a/twidere.donate.nyanwp.wear/src/main/AndroidManifest.xml +++ b/twidere.donate.nyanwp.wear/src/main/AndroidManifest.xml @@ -18,16 +18,19 @@ ~ along with this program. If not, see . --> - + + android:theme="@android:style/Theme.DeviceDefault" + tools:ignore="GoogleAppIndexingWarning"> + + android:label="@string/app_name" + tools:ignore="GoogleAppIndexingWarning"> + android:process=":daydream" + tools:ignore="ExportedService"> diff --git a/twidere.extension.shortener.gist/src/main/AndroidManifest.xml b/twidere.extension.shortener.gist/src/main/AndroidManifest.xml index 84e055cd2..bd4c641a4 100644 --- a/twidere.extension.shortener.gist/src/main/AndroidManifest.xml +++ b/twidere.extension.shortener.gist/src/main/AndroidManifest.xml @@ -20,15 +20,18 @@ + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools"> + android:theme="@android:style/Theme.DeviceDefault" + tools:ignore="GoogleAppIndexingWarning"> diff --git a/twidere.extension.twitlonger/src/main/java/com/twitter/Extractor.java b/twidere.extension.twitlonger/src/main/java/com/twitter/Extractor.java deleted file mode 100644 index bbb8049ac..000000000 --- a/twidere.extension.twitlonger/src/main/java/com/twitter/Extractor.java +++ /dev/null @@ -1,567 +0,0 @@ -package com.twitter; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.regex.Matcher; - -/** - * A class to extract usernames, lists, hashtags and URLs from Tweet text. - */ -public class Extractor { - protected boolean extractURLWithoutProtocol = true; - - /** - * Fullwidth at sign: '@' - */ - private static final char FULLWIDTH_AT_SIGN = '\uff20'; - - /** - * Fullwidth number sign: '#' - */ - private static final char FULLWIDTH_NUMBER_SIGN = '\uff03'; - - /** - * Create a new extractor. - */ - public Extractor() { - } - - /** - * Extract $cashtag references from Tweet text. - * - * @param text of the tweet from which to extract cashtags - * @return List of cashtags referenced (without the leading $ sign) - */ - public List extractCashtags(final String text) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - final ArrayList extracted = new ArrayList(); - for (final Entity entity : extractCashtagsWithIndices(text)) { - extracted.add(entity.value); - } - - return extracted; - } - - /** - * Extract $cashtag references from Tweet text. - * - * @param text of the tweet from which to extract cashtags - * @return List of cashtags referenced (without the leading $ sign) - */ - public List extractCashtagsWithIndices(final String text) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - // Performance optimization. - // If text doesn't contain $, text doesn't contain - // cashtag, so we can simply return an empty list. - if (text.indexOf('$') == -1) return Collections.emptyList(); - - final ArrayList extracted = new ArrayList(); - final Matcher matcher = Regex.VALID_CASHTAG.matcher(text); - - while (matcher.find()) { - extracted.add(new Entity(matcher, Entity.Type.CASHTAG, Regex.VALID_CASHTAG_GROUP_CASHTAG_FULL)); - } - - return extracted; - } - - /** - * Extract URLs, @mentions, lists and #hashtag from a given text/tweet. - * - * @param text text of tweet - * @return list of extracted entities - */ - public List extractEntitiesWithIndices(final String text) { - final ArrayList entities = new ArrayList(); - entities.addAll(extractURLsWithIndices(text)); - entities.addAll(extractHashtagsWithIndices(text, false)); - entities.addAll(extractMentionsOrListsWithIndices(text)); - entities.addAll(extractCashtagsWithIndices(text)); - - removeOverlappingEntities(entities); - return entities; - } - - /** - * Extract #hashtag references from Tweet text. - * - * @param text of the tweet from which to extract hashtags - * @return List of hashtags referenced (without the leading # sign) - */ - public List extractHashtags(final String text) { - return extractHashtags(text, true); - } - - public List extractHashtags(final String text, final boolean exclude_duplicate) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - final ArrayList extracted = new ArrayList(); - for (final Entity entity : extractHashtagsWithIndices(text)) { - if (!exclude_duplicate || !extracted.contains(entity.value)) { - extracted.add(entity.value); - } - } - - return extracted; - } - - /** - * Extract #hashtag references from Tweet text. - * - * @param text of the tweet from which to extract hashtags - * @return List of hashtags referenced (without the leading # sign) - */ - public List extractHashtagsWithIndices(final String text) { - return extractHashtagsWithIndices(text, true); - } - - /** - * Extract @username references from Tweet text. A mention is an occurance - * of @username anywhere in a Tweet. - * - * @param text of the tweet from which to extract usernames - * @return List of usernames referenced (without the leading @ sign) - */ - public Set extractMentionedScreennames(final String text) { - return extractMentionedScreennames(text, true); - } - - public Set extractMentionedScreennames(final String text, final boolean exclude_duplicate) { - if (text == null || text.length() == 0) return Collections.emptySet(); - - final Set extracted = new HashSet(); - for (final Entity entity : extractMentionedScreennamesWithIndices(text)) { - if (!exclude_duplicate || !extracted.contains(entity.value)) { - extracted.add(entity.value); - } - } - return extracted; - } - - /** - * Extract @username references from Tweet text. A mention is an occurance - * of @username anywhere in a Tweet. - * - * @param text of the tweet from which to extract usernames - * @return List of usernames referenced (without the leading @ sign) - */ - public List extractMentionedScreennamesWithIndices(final String text) { - final ArrayList extracted = new ArrayList(); - for (final Entity entity : extractMentionsOrListsWithIndices(text)) { - if (entity.listSlug == null) { - extracted.add(entity); - } - } - return extracted; - } - - public List extractMentionsOrListsWithIndices(final String text) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - // Performance optimization. - // If text doesn't contain @ at all, the text doesn't - // contain @mention. So we can simply return an empty list. - boolean found = false; - for (final char c : text.toCharArray()) { - if (c == '@' || c == FULLWIDTH_AT_SIGN) { - found = true; - break; - } - } - if (!found) return Collections.emptyList(); - - final ArrayList extracted = new ArrayList(); - final Matcher matcher = Regex.VALID_MENTION_OR_LIST.matcher(text); - while (matcher.find()) { - final String after = text.substring(matcher.end()); - if (!Regex.INVALID_MENTION_MATCH_END.matcher(after).find()) { - if (matcher.group(Regex.VALID_MENTION_OR_LIST_GROUP_LIST) == null) { - extracted.add(new Entity(matcher, Entity.Type.MENTION, Regex.VALID_MENTION_OR_LIST_GROUP_USERNAME)); - } else { - extracted.add(new Entity(matcher.start(Regex.VALID_MENTION_OR_LIST_GROUP_USERNAME) - 1, matcher - .end(Regex.VALID_MENTION_OR_LIST_GROUP_LIST), matcher - .group(Regex.VALID_MENTION_OR_LIST_GROUP_USERNAME), matcher - .group(Regex.VALID_MENTION_OR_LIST_GROUP_LIST), Entity.Type.MENTION)); - } - } - } - return extracted; - } - - /** - * Extract a @username reference from the beginning of Tweet text. A reply - * is an occurance of @username at the beginning of a Tweet, preceded by 0 - * or more spaces. - * - * @param text of the tweet from which to extract the replied to username - * @return username referenced, if any (without the leading @ sign). Returns - * null if this is not a reply. - */ - public String extractReplyScreenname(final String text) { - if (text == null) return null; - - final Matcher matcher = Regex.VALID_REPLY.matcher(text); - if (matcher.find()) { - final String after = text.substring(matcher.end()); - if (Regex.INVALID_MENTION_MATCH_END.matcher(after).find()) - return null; - else - return matcher.group(Regex.VALID_REPLY_GROUP_USERNAME); - } else - return null; - } - - /** - * Extract URL references from Tweet text. - * - * @param text of the tweet from which to extract URLs - * @return List of URLs referenced. - */ - public List extractURLs(final String text) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - final ArrayList urls = new ArrayList(); - for (final Entity entity : extractURLsWithIndices(text)) { - urls.add(entity.value); - } - return urls; - } - - /** - * Extract URL references from Tweet text. - * - * @param text of the tweet from which to extract URLs - * @return List of URLs referenced. - */ - public List extractURLsWithIndices(final String text) { - if (text == null || text.length() == 0 - || (extractURLWithoutProtocol ? text.indexOf('.') : text.indexOf(':')) == -1) // Performance - // optimization. - // If text doesn't contain '.' or ':' at all, text doesn't contain - // URL, - // so we can simply return an empty list. - return Collections.emptyList(); - - final ArrayList urls = new ArrayList(); - - final Matcher matcher = Regex.VALID_URL.matcher(text); - while (matcher.find()) { - if (matcher.group(Regex.VALID_URL_GROUP_PROTOCOL) == null) { - // skip if protocol is not present and - // 'extractURLWithoutProtocol' is false - // or URL is preceded by invalid character. - if (!extractURLWithoutProtocol - || Regex.INVALID_URL_WITHOUT_PROTOCOL_MATCH_BEGIN.matcher( - matcher.group(Regex.VALID_URL_GROUP_BEFORE)).matches()) { - continue; - } - } - String url = matcher.group(Regex.VALID_URL_GROUP_URL); - final int start = matcher.start(Regex.VALID_URL_GROUP_URL); - int end = matcher.end(Regex.VALID_URL_GROUP_URL); - final Matcher tco_matcher = Regex.VALID_TCO_URL.matcher(url); - if (tco_matcher.find()) { - // In the case of t.co URLs, don't allow additional path - // characters. - url = tco_matcher.group(); - end = start + url.length(); - } - - urls.add(new Entity(start, end, url, Entity.Type.URL)); - } - - return urls; - } - - public boolean isExtractURLWithoutProtocol() { - return extractURLWithoutProtocol; - } - - /* - * Modify Unicode-based indices of the entities to UTF-16 based indices. - * - * In UTF-16 based indices, Unicode supplementary characters are counted as - * two characters. - * - * This method requires that the list of entities be in ascending order by - * start index. - * - * @param text original text - * - * @param entities entities with Unicode based indices - */ - public void modifyIndicesFromUnicodeToUTF16(final String text, final List entities) { - final IndexConverter convert = new IndexConverter(text); - - for (final Entity entity : entities) { - entity.start = convert.codePointsToCodeUnits(entity.start); - entity.end = convert.codePointsToCodeUnits(entity.end); - } - } - - /* - * Modify UTF-16-based indices of the entities to Unicode-based indices. - * - * In Unicode-based indices, Unicode supplementary characters are counted as - * single characters. - * - * This method requires that the list of entities be in ascending order by - * start index. - * - * @param text original text - * - * @param entities entities with UTF-16 based indices - */ - public void modifyIndicesFromUTF16ToToUnicode(final String text, final List entities) { - final IndexConverter convert = new IndexConverter(text); - - for (final Entity entity : entities) { - entity.start = convert.codeUnitsToCodePoints(entity.start); - entity.end = convert.codeUnitsToCodePoints(entity.end); - } - } - - public void setExtractURLWithoutProtocol(final boolean extractURLWithoutProtocol) { - this.extractURLWithoutProtocol = extractURLWithoutProtocol; - } - - /** - * Extract #hashtag references from Tweet text. - * - * @param text of the tweet from which to extract hashtags - * @param checkUrlOverlap if true, check if extracted hashtags overlap URLs - * and remove overlapping ones - * @return List of hashtags referenced (without the leading # sign) - */ - private List extractHashtagsWithIndices(final String text, final boolean checkUrlOverlap) { - if (text == null || text.length() == 0) return Collections.emptyList(); - - // Performance optimization. - // If text doesn't contain # at all, text doesn't contain - // hashtag, so we can simply return an empty list. - boolean found = false; - for (final char c : text.toCharArray()) { - if (c == '#' || c == FULLWIDTH_NUMBER_SIGN) { - found = true; - break; - } - } - if (!found) return Collections.emptyList(); - - final ArrayList extracted = new ArrayList(); - final Matcher matcher = Regex.VALID_HASHTAG.matcher(text); - - while (matcher.find()) { - final String after = text.substring(matcher.end()); - if (!Regex.INVALID_HASHTAG_MATCH_END.matcher(after).find()) { - extracted.add(new Entity(matcher, Entity.Type.HASHTAG, Regex.VALID_HASHTAG_GROUP_TAG)); - } - } - - if (checkUrlOverlap) { - // extract URLs - final List urls = extractURLsWithIndices(text); - if (!urls.isEmpty()) { - extracted.addAll(urls); - // remove overlap - removeOverlappingEntities(extracted); - // remove URL entities - final Iterator it = extracted.iterator(); - while (it.hasNext()) { - final Entity entity = it.next(); - if (entity.getType() != Entity.Type.HASHTAG) { - it.remove(); - } - } - } - } - - return extracted; - } - - private void removeOverlappingEntities(final List entities) { - // sort by index - Collections. sort(entities, new Comparator() { - @Override - public int compare(final Entity e1, final Entity e2) { - return e1.start - e2.start; - } - }); - - // Remove overlapping entities. - // Two entities overlap only when one is URL and the other is - // hashtag/mention - // which is a part of the URL. When it happens, we choose URL over - // hashtag/mention - // by selecting the one with smaller start index. - if (!entities.isEmpty()) { - final Iterator it = entities.iterator(); - Entity prev = it.next(); - while (it.hasNext()) { - final Entity cur = it.next(); - if (prev.getEnd() > cur.getStart()) { - it.remove(); - } else { - prev = cur; - } - } - } - } - - public static class Entity { - protected int start; - - protected int end; - protected final String value; - // listSlug is used to store the list portion of @mention/list. - protected final String listSlug; - protected final Type type; - protected String displayURL = null; - - protected String expandedURL = null; - - public Entity(final int start, final int end, final String value, final String listSlug, final Type type) { - this.start = start; - this.end = end; - this.value = value; - this.listSlug = listSlug; - this.type = type; - } - - public Entity(final int start, final int end, final String value, final Type type) { - this(start, end, value, null, type); - } - - public Entity(final Matcher matcher, final Type type, final int groupNumber) { - // Offset -1 on start index to include @, # symbols for mentions and - // hashtags - this(matcher, type, groupNumber, -1); - } - - public Entity(final Matcher matcher, final Type type, final int groupNumber, final int startOffset) { - this(matcher.start(groupNumber) + startOffset, matcher.end(groupNumber), matcher.group(groupNumber), type); - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - - if (!(obj instanceof Entity)) return false; - - final Entity other = (Entity) obj; - - if (type.equals(other.type) && start == other.start && end == other.end && value.equals(other.value)) - return true; - else - return false; - } - - public String getDisplayURL() { - return displayURL; - } - - public Integer getEnd() { - return end; - } - - public String getExpandedURL() { - return expandedURL; - } - - public String getListSlug() { - return listSlug; - } - - public Integer getStart() { - return start; - } - - public Type getType() { - return type; - } - - public String getValue() { - return value; - } - - @Override - public int hashCode() { - return type.hashCode() + value.hashCode() + start + end; - } - - public void setDisplayURL(final String displayURL) { - this.displayURL = displayURL; - } - - public void setExpandedURL(final String expandedURL) { - this.expandedURL = expandedURL; - } - - @Override - public String toString() { - return value + "(" + type + ") [" + start + "," + end + "]"; - } - - public enum Type { - URL, HASHTAG, MENTION, CASHTAG - } - } - - /** - * An efficient converter of indices between code points and code units. - */ - private static final class IndexConverter { - protected final String text; - - // Keep track of a single corresponding pair of code unit and code point - // offsets so that we can re-use counting work if the next requested - // entity is near the most recent entity. - protected int codePointIndex = 0; - protected int charIndex = 0; - - IndexConverter(final String text) { - this.text = text; - } - - /** - * @param codePointIndex Index into the string measured in code points. - * @return the code unit index that corresponds to the specified code - * point index. - */ - int codePointsToCodeUnits(final int codePointIndex) { - // Note that offsetByCodePoints accepts negative indices. - charIndex = text.offsetByCodePoints(charIndex, codePointIndex - this.codePointIndex); - this.codePointIndex = codePointIndex; - return charIndex; - } - - /** - * @param charIndex Index into the string measured in code units. - * @return The code point index that corresponds to the specified - * character index. - */ - int codeUnitsToCodePoints(final int charIndex) { - if (charIndex < this.charIndex) { - codePointIndex -= text.codePointCount(charIndex, this.charIndex); - } else { - codePointIndex += text.codePointCount(this.charIndex, charIndex); - } - this.charIndex = charIndex; - - // Make sure that charIndex never points to the second code unit of - // a - // surrogate pair. - if (charIndex > 0 && Character.isSupplementaryCodePoint(text.codePointAt(charIndex - 1))) { - this.charIndex -= 1; - } - return codePointIndex; - } - } -} diff --git a/twidere.extension.twitlonger/src/main/java/com/twitter/Regex.java b/twidere.extension.twitlonger/src/main/java/com/twitter/Regex.java deleted file mode 100644 index afdb31346..000000000 --- a/twidere.extension.twitlonger/src/main/java/com/twitter/Regex.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.twitter; - -import java.util.regex.Pattern; - -//@formatter:off -public class Regex { - private static final String UNICODE_SPACES = "[" + - "\\u0009-\\u000d" + // # White_Space # Cc [5] .. - "\\u0020" + // White_Space # Zs SPACE - "\\u0085" + // White_Space # Cc - "\\u00a0" + // White_Space # Zs NO-BREAK SPACE - "\\u1680" + // White_Space # Zs OGHAM SPACE MARK - "\\u180E" + // White_Space # Zs MONGOLIAN VOWEL SEPARATOR - "\\u2000-\\u200a" + // # White_Space # Zs [11] EN QUAD..HAIR SPACE - "\\u2028" + // White_Space # Zl LINE SEPARATOR - "\\u2029" + // White_Space # Zp PARAGRAPH SEPARATOR - "\\u202F" + // White_Space # Zs NARROW NO-BREAK SPACE - "\\u205F" + // White_Space # Zs MEDIUM MATHEMATICAL SPACE - "\\u3000" + // White_Space # Zs IDEOGRAPHIC SPACE - "]"; - - private static String LATIN_ACCENTS_CHARS = "\\u00c0-\\u00d6\\u00d8-\\u00f6\\u00f8-\\u00ff" + // Latin-1 - "\\u0100-\\u024f" + // Latin Extended A and B - "\\u0253\\u0254\\u0256\\u0257\\u0259\\u025b\\u0263\\u0268\\u026f\\u0272\\u0289\\u028b" + // IPA Extensions - "\\u02bb" + // Hawaiian - "\\u0300-\\u036f" + // Combining diacritics - "\\u1e00-\\u1eff"; // Latin Extended Additional (mostly for Vietnamese) - private static final String HASHTAG_ALPHA_CHARS = "a-z" + LATIN_ACCENTS_CHARS + - "\\u0400-\\u04ff\\u0500-\\u0527" + // Cyrillic - "\\u2de0-\\u2dff\\ua640-\\ua69f" + // Cyrillic Extended A/B - "\\u0591-\\u05bf\\u05c1-\\u05c2\\u05c4-\\u05c5\\u05c7" + - "\\u05d0-\\u05ea\\u05f0-\\u05f4" + // Hebrew - "\\ufb1d-\\ufb28\\ufb2a-\\ufb36\\ufb38-\\ufb3c\\ufb3e\\ufb40-\\ufb41" + - "\\ufb43-\\ufb44\\ufb46-\\ufb4f" + // Hebrew Pres. Forms - "\\u0610-\\u061a\\u0620-\\u065f\\u066e-\\u06d3\\u06d5-\\u06dc" + - "\\u06de-\\u06e8\\u06ea-\\u06ef\\u06fa-\\u06fc\\u06ff" + // Arabic - "\\u0750-\\u077f\\u08a0\\u08a2-\\u08ac\\u08e4-\\u08fe" + // Arabic Supplement and Extended A - "\\ufb50-\\ufbb1\\ufbd3-\\ufd3d\\ufd50-\\ufd8f\\ufd92-\\ufdc7\\ufdf0-\\ufdfb" + // Pres. Forms A - "\\ufe70-\\ufe74\\ufe76-\\ufefc" + // Pres. Forms B - "\\u200c" + // Zero-Width Non-Joiner - "\\u0e01-\\u0e3a\\u0e40-\\u0e4e" + // Thai - "\\u1100-\\u11ff\\u3130-\\u3185\\uA960-\\uA97F\\uAC00-\\uD7AF\\uD7B0-\\uD7FF" + // Hangul (Korean) - "\\p{InHiragana}\\p{InKatakana}" + // Japanese Hiragana and Katakana - "\\p{InCJKUnifiedIdeographs}" + // Japanese Kanji / Chinese Han - "\\u3003\\u3005\\u303b" + // Kanji/Han iteration marks - "\\uff21-\\uff3a\\uff41-\\uff5a" + // full width Alphabet - "\\uff66-\\uff9f" + // half width Katakana - "\\uffa1-\\uffdc"; // half width Hangul (Korean) - private static final String HASHTAG_ALPHA_NUMERIC_CHARS = "0-9\\uff10-\\uff19_" + HASHTAG_ALPHA_CHARS; - private static final String HASHTAG_ALPHA = "[" + HASHTAG_ALPHA_CHARS +"]"; - private static final String HASHTAG_ALPHA_NUMERIC = "[" + HASHTAG_ALPHA_NUMERIC_CHARS +"]"; - - /** - * Fullwidth at sign: '@' - */ - private static final char FULLWIDTH_AT_SIGN = '\uff20'; - - /** - * Fullwidth number sign: '#' - */ - private static final char FULLWIDTH_NUMBER_SIGN = '\uff03'; - - /* URL related hash regex collection */ - private static final String URL_VALID_PRECEEDING_CHARS = "(?:[^A-Z0-9@"+FULLWIDTH_AT_SIGN+"$#"+FULLWIDTH_NUMBER_SIGN+"\u202A-\u202E]|^)"; - - private static final String URL_VALID_CHARS = "[\\p{Alnum}" + LATIN_ACCENTS_CHARS + "]"; - private static final String URL_VALID_SUBDOMAIN = "(?:(?:" + URL_VALID_CHARS + "[" + URL_VALID_CHARS + "\\-_]*)?" + URL_VALID_CHARS + "\\.)"; - private static final String URL_VALID_DOMAIN_NAME = "(?:(?:" + URL_VALID_CHARS + "[" + URL_VALID_CHARS + "\\-]*)?" + URL_VALID_CHARS + "\\.)"; - /* Any non-space, non-punctuation characters. \p{Z} = any kind of whitespace or invisible separator. */ - private static final String URL_VALID_UNICODE_CHARS = "[.[^\\p{Punct}\\s\\p{Z}\\p{InGeneralPunctuation}]]"; - - private static final String URL_VALID_GTLD = - "(?:(?:aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel|xxx)(?=\\P{Alnum}|$))"; - private static final String URL_VALID_CCTLD = - "(?:(?:ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|" + - "bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|" + - "er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|" + - "hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|" + - "lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|" + - "nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|" + - "sl|sm|sn|so|sr|ss|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|" + - "va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)(?=\\P{Alnum}|$))"; - private static final String URL_PUNYCODE = "(?:xn--[0-9a-z]+)"; - - private static final String URL_VALID_DOMAIN = - "(?:" + // subdomains + domain + TLD - URL_VALID_SUBDOMAIN + "+" + URL_VALID_DOMAIN_NAME + // e.g. www.twitter.com, foo.co.jp, bar.co.uk - "(?:" + URL_VALID_GTLD + "|" + URL_VALID_CCTLD + "|" + URL_PUNYCODE + ")" + - ")" + - "|(?:" + // domain + gTLD - URL_VALID_DOMAIN_NAME + // e.g. twitter.com - "(?:" + URL_VALID_GTLD + "|" + URL_PUNYCODE + ")" + - ")" + - "|(?:" + "(?<=https?://)" + - "(?:" + - "(?:" + URL_VALID_DOMAIN_NAME + URL_VALID_CCTLD + ")" + // protocol + domain + ccTLD - "|(?:" + - URL_VALID_UNICODE_CHARS + "+\\." + // protocol + unicode domain + TLD - "(?:" + URL_VALID_GTLD + "|" + URL_VALID_CCTLD + ")" + - ")" + - ")" + - ")" + - "|(?:" + // domain + ccTLD + '/' - URL_VALID_DOMAIN_NAME + URL_VALID_CCTLD + "(?=/)" + // e.g. t.co/ - ")"; - - private static final String URL_VALID_PORT_NUMBER = "[0-9]++"; - - private static final String URL_VALID_GENERAL_PATH_CHARS = "[a-z0-9!\\*';:=\\+,.\\$/%#\\[\\]\\-_~\\|&" + LATIN_ACCENTS_CHARS + "]"; - /** Allow URL paths to contain balanced parens - * 1. Used in Wikipedia URLs like /Primer_(film) - * 2. Used in IIS sessions like /S(dfd346)/ - **/ - private static final String URL_BALANCED_PARENS = "\\(" + URL_VALID_GENERAL_PATH_CHARS + "+\\)"; - /** Valid end-of-path chracters (so /foo. does not gobble the period). - * 2. Allow =&# for empty URL parameters and other URL-join artifacts - **/ - private static final String URL_VALID_PATH_ENDING_CHARS = "[a-z0-9=_#/\\-\\+" + LATIN_ACCENTS_CHARS + "]|(?:" + URL_BALANCED_PARENS +")"; - - private static final String URL_VALID_PATH = "(?:" + - "(?:" + - URL_VALID_GENERAL_PATH_CHARS + "*" + - "(?:" + URL_BALANCED_PARENS + URL_VALID_GENERAL_PATH_CHARS + "*)*" + - URL_VALID_PATH_ENDING_CHARS + - ")|(?:@" + URL_VALID_GENERAL_PATH_CHARS + "+/)" + - ")"; - - private static final String URL_VALID_URL_QUERY_CHARS = "[a-z0-9!?\\*'\\(\\);:&=\\+\\$/%#\\[\\]\\-_\\.,~\\|]"; - private static final String URL_VALID_URL_QUERY_ENDING_CHARS = "[a-z0-9_&=#/]"; - private static final String VALID_URL_PATTERN_STRING = - "(" + // $1 total match - "(" + URL_VALID_PRECEEDING_CHARS + ")" + // $2 Preceeding chracter - "(" + // $3 URL - "(https?://)?" + // $4 Protocol (optional) - "(" + URL_VALID_DOMAIN + ")" + // $5 Domain(s) - "(?::(" + URL_VALID_PORT_NUMBER +"))?" + // $6 Port number (optional) - "(/" + - URL_VALID_PATH + "*+" + - ")?" + // $7 URL Path and anchor - "(\\?" + URL_VALID_URL_QUERY_CHARS + "*" + // $8 Query String - URL_VALID_URL_QUERY_ENDING_CHARS + ")?" + - ")" + - ")"; - - private static String AT_SIGNS_CHARS = "@\uFF20"; - - private static final String DOLLAR_SIGN_CHAR = "\\$"; - private static final String CASHTAG = "[a-z]{1,6}(?:[._][a-z]{1,2})?"; - - /* Begin public constants */ - - public static final Pattern VALID_HASHTAG = Pattern.compile("(^|[^&" + HASHTAG_ALPHA_NUMERIC_CHARS + "])((#|\uFF03)(" + HASHTAG_ALPHA_NUMERIC + "*" + HASHTAG_ALPHA + HASHTAG_ALPHA_NUMERIC + "*))", Pattern.CASE_INSENSITIVE); - public static final int VALID_HASHTAG_GROUP_BEFORE = 1; - public static final int VALID_HASHTAG_GROUP_HASHTAG_FULL = 2; - public static final int VALID_HASHTAG_GROUP_HASH = 3; - public static final int VALID_HASHTAG_GROUP_TAG = 4; - public static final Pattern INVALID_HASHTAG_MATCH_END = Pattern.compile("^(?:[#"+FULLWIDTH_NUMBER_SIGN+"]|://)"); - - public static final Pattern AT_SIGNS = Pattern.compile("[" + AT_SIGNS_CHARS + "]"); - public static final Pattern VALID_MENTION_OR_LIST = Pattern.compile("([^a-z0-9_!#$%&*" + AT_SIGNS_CHARS + "]|^|RT:?)(" + AT_SIGNS + "+)([a-z0-9_]{1,20})(\\/([a-z][a-z0-9_\\-]{0,24}))?", Pattern.CASE_INSENSITIVE); - public static final int VALID_MENTION_OR_LIST_GROUP_BEFORE = 1; - public static final int VALID_MENTION_OR_LIST_GROUP_AT = 2; - public static final int VALID_MENTION_OR_LIST_GROUP_USERNAME = 3; - public static final int VALID_MENTION_OR_LIST_GROUP_LIST_WITH_SLASH = 4; - public static final int VALID_MENTION_OR_LIST_GROUP_LIST = 5; - - public static final Pattern VALID_REPLY = Pattern.compile("^(?:" + UNICODE_SPACES + ")*" + AT_SIGNS + "([a-z0-9_]{1,20})", Pattern.CASE_INSENSITIVE); - public static final int VALID_REPLY_GROUP_USERNAME = 1; - - public static final Pattern INVALID_MENTION_MATCH_END = Pattern.compile("^(?:[" + AT_SIGNS_CHARS + LATIN_ACCENTS_CHARS + "]|://)"); - - public static final Pattern VALID_URL = Pattern.compile(VALID_URL_PATTERN_STRING, Pattern.CASE_INSENSITIVE); - public static final int VALID_URL_GROUP_ALL = 1; - public static final int VALID_URL_GROUP_BEFORE = 2; - public static final int VALID_URL_GROUP_URL = 3; - public static final int VALID_URL_GROUP_PROTOCOL = 4; - public static final int VALID_URL_GROUP_DOMAIN = 5; - public static final int VALID_URL_GROUP_PORT = 6; - public static final int VALID_URL_GROUP_PATH = 7; - public static final int VALID_URL_GROUP_QUERY_STRING = 8; - - public static final Pattern VALID_TCO_URL = Pattern.compile("^https?:\\/\\/t\\.co\\/[a-z0-9]+", Pattern.CASE_INSENSITIVE); - public static final Pattern INVALID_URL_WITHOUT_PROTOCOL_MATCH_BEGIN = Pattern.compile("[-_./]$"); - - public static final Pattern VALID_CASHTAG = Pattern.compile("((?:^|" + UNICODE_SPACES + ")((" + DOLLAR_SIGN_CHAR + ")(" + CASHTAG + "))" +"(?=$|\\s|\\p{Punct}))", Pattern.CASE_INSENSITIVE); - - public static final int VALID_CASHTAG_GROUP_CASHTAG_FULL = 2; - public static final int VALID_CASHTAG_GROUP_CASH = 3; - public static final int VALID_CASHTAG_GROUP_TAG = 4; -} diff --git a/twidere.extension.twitlonger/src/main/java/com/twitter/Validator.java b/twidere.extension.twitlonger/src/main/java/com/twitter/Validator.java deleted file mode 100644 index 098898134..000000000 --- a/twidere.extension.twitlonger/src/main/java/com/twitter/Validator.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.twitter; - -/** - * A class for validating Tweet texts. - */ -public class Validator { - public static final int MAX_TWEET_LENGTH = 140; - - protected int shortUrlLength = 22; - protected int shortUrlLengthHttps = 23; - - private final Extractor extractor = new Extractor(); - - public int getShortUrlLength() { - return shortUrlLength; - } - - public int getShortUrlLengthHttps() { - return shortUrlLengthHttps; - } - - public int getTweetLength(final String text) { - int length = text.codePointCount(0, text.length()); - - for (final Extractor.Entity urlEntity : extractor.extractURLsWithIndices(text)) { - length += urlEntity.start - urlEntity.end; - length += urlEntity.value.toLowerCase().startsWith("https://") ? shortUrlLengthHttps : shortUrlLength; - } - - return length; - } - - public boolean isValidTweet(final String text) { - if (text == null || text.length() == 0) return false; - - for (final char c : text.toCharArray()) { - if (c == '\uFFFE' || c == '\uuFEFF' || // BOM - c == '\uFFFF' || // Special - c >= '\u202A' && c <= '\u202E') return false; - } - - return getTweetLength(text) <= MAX_TWEET_LENGTH; - } - - public void setShortUrlLength(final int shortUrlLength) { - this.shortUrlLength = shortUrlLength; - } - - public void setShortUrlLengthHttps(final int shortUrlLengthHttps) { - this.shortUrlLengthHttps = shortUrlLengthHttps; - } -} diff --git a/twidere.extension.twitlonger/src/main/res/layout/main.xml b/twidere.extension.twitlonger/src/main/res/layout/main.xml index 070dd841e..1b03bd121 100644 --- a/twidere.extension.twitlonger/src/main/res/layout/main.xml +++ b/twidere.extension.twitlonger/src/main/res/layout/main.xml @@ -1,60 +1,63 @@ - + - + - + - + - + - - - + + + - + - - + + \ No newline at end of file diff --git a/twidere/build.gradle b/twidere/build.gradle index 88df4b319..a8d33b097 100644 --- a/twidere/build.gradle +++ b/twidere/build.gradle @@ -99,7 +99,6 @@ dependencies { compile 'commons-primitives:commons-primitives:1.0' compile 'com.bluelinelabs:logansquare:1.3.4' compile 'org.jraf:android-switch-backport:2.0.1' - compile 'com.github.mariotaku:jackson-jr-trees:7fe682ee09' compile 'com.makeramen:roundedimageview:2.1.1' compile 'com.soundcloud.android:android-crop:1.0.1@aar' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2' @@ -111,7 +110,7 @@ dependencies { compile 'org.attoparser:attoparser:1.4.0.RELEASE' compile 'com.github.mariotaku.MediaViewerLibrary:base:0.9.10' compile 'com.github.mariotaku.MediaViewerLibrary:subsample-image-view:0.9.10' - compile 'com.github.mariotaku.SQLiteQB:library:0.9.5-SNAPSHOT' + compile 'com.github.mariotaku.SQLiteQB:library:0.9.5' compile 'com.github.mariotaku.ObjectCursor:core:0.9.4' compile project(':twidere.component.common') compile project(':twidere.component.nyan') diff --git a/twidere/src/google/AndroidManifest.xml b/twidere/src/google/AndroidManifest.xml index 8536ee30f..b02056919 100644 --- a/twidere/src/google/AndroidManifest.xml +++ b/twidere/src/google/AndroidManifest.xml @@ -1,16 +1,19 @@ - + - + - + + android:value="@integer/google_play_services_version"/> + android:value="AIzaSyCVdCIMFFxdNqHnCPrJ9yKUzoTfs8jhYGc"/> \ No newline at end of file diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/BasePreferenceActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/BasePreferenceActivity.java index 464c3d799..28112c319 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/BasePreferenceActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/BasePreferenceActivity.java @@ -43,7 +43,6 @@ import org.mariotaku.twidere.util.ActivityTracker; import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.StrictModeUtils; import org.mariotaku.twidere.util.ThemeUtils; -import org.mariotaku.twidere.util.TwidereColorUtils; import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.dagger.GeneralComponentHelper; import org.mariotaku.twidere.util.support.ViewSupport; @@ -249,7 +248,7 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity } @Override - public void setTheme(int resid) { + public void setTheme(int resId) { super.setTheme(mCurrentThemeResource = getThemeResourceId()); if (shouldApplyWindowBackground()) { ThemeUtils.applyWindowBackground(this, getWindow(), mCurrentThemeResource, @@ -258,13 +257,13 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity } @Override - protected void onApplyThemeResource(@NonNull Resources.Theme theme, int resid, boolean first) { + protected void onApplyThemeResource(@NonNull Resources.Theme theme, int resId, boolean first) { mCurrentThemeColor = getThemeColor(); mCurrentThemeBackgroundAlpha = getThemeBackgroundAlpha(); mProfileImageStyle = Utils.getProfileImageStyle(this); mCurrentThemeBackgroundOption = getThemeBackgroundOption(); mCurrentThemeFontFamily = getThemeFontFamily(); - super.onApplyThemeResource(theme, resid, first); + super.onApplyThemeResource(theme, resId, first); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/ImageCropperActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/ImageCropperActivity.java index 53d5f9206..4e891aff1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/ImageCropperActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/ImageCropperActivity.java @@ -91,7 +91,7 @@ public class ImageCropperActivity extends CropImageActivity implements IThemedAc @Override - public void setTheme(final int resid) { + public void setTheme(final int resId) { super.setTheme(mCurrentThemeResource = getThemeResourceId()); ThemeUtils.applyWindowBackground(this, getWindow(), mCurrentThemeResource, mCurrentThemeBackgroundOption, mCurrentThemeBackgroundAlpha); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java index 44bb7b980..848ff4b21 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/MainActivity.java @@ -44,7 +44,7 @@ public class MainActivity extends Activity implements Constants { } @Override - public void setTheme(int resid) { + public void setTheme(int resId) { super.setTheme(ThemeUtils.getNoActionBarThemeResource(this)); } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java index dc31a941d..9073e95a8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/BrowserSignInActivity.java @@ -21,7 +21,6 @@ package org.mariotaku.twidere.activity.support; import android.annotation.SuppressLint; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java index 0d3e6343a..da131e1ee 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/HomeActivity.java @@ -82,7 +82,6 @@ import org.mariotaku.twidere.model.ParcelableAccount; import org.mariotaku.twidere.model.SupportTabSpec; import org.mariotaku.twidere.model.message.TaskStateChangedEvent; import org.mariotaku.twidere.model.message.UnreadCountUpdatedEvent; -import org.mariotaku.twidere.provider.TwidereDataStore; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.provider.TwidereDataStore.Activities; import org.mariotaku.twidere.provider.TwidereDataStore.Statuses; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ThemedAppCompatActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ThemedAppCompatActivity.java index f7f9accd5..a0e6cc0e7 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/ThemedAppCompatActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/ThemedAppCompatActivity.java @@ -110,12 +110,13 @@ public abstract class ThemedAppCompatActivity extends AppCompatActivity implemen } @Override - public void onSupportActionModeStarted(android.support.v7.view.ActionMode mode) { + public void onSupportActionModeStarted(@NonNull android.support.v7.view.ActionMode mode) { super.onSupportActionModeStarted(mode); ThemeUtils.applySupportActionModeColor(mode, this, getCurrentThemeResourceId(), getCurrentThemeColor(), getThemeBackgroundOption(), true); } + @NonNull @Override public ThemedAppCompatDelegateFactory.ThemedAppCompatDelegate getDelegate() { if (mDelegate != null) return mDelegate; diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java index f8fa06456..6d262d7a1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/UserStreamCallback.java @@ -19,22 +19,24 @@ package org.mariotaku.twidere.api.twitter; +import android.text.TextUtils; import android.util.Log; import com.bluelinelabs.logansquare.LoganSquare; import com.fasterxml.jackson.core.TreeNode; -import com.fasterxml.jackson.jr.tree.JacksonJrSimpleTreeCodec; import org.mariotaku.restfu.callback.RawCallback; import org.mariotaku.restfu.http.HttpResponse; +import org.mariotaku.twidere.api.twitter.model.DeletionEvent; import org.mariotaku.twidere.api.twitter.model.DirectMessage; import org.mariotaku.twidere.api.twitter.model.Status; -import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice; +import org.mariotaku.twidere.api.twitter.model.StatusFavoriteEvent; +import org.mariotaku.twidere.api.twitter.model.TwitterStreamObject; +import org.mariotaku.twidere.api.twitter.model.TwitterStreamObject.Type; import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.api.twitter.model.UserList; import org.mariotaku.twidere.api.twitter.model.Warning; import org.mariotaku.twidere.api.twitter.util.CRLFLineReader; -import org.mariotaku.twidere.api.twitter.util.JSONObjectType; import org.mariotaku.twidere.util.LoganSquareMapperFinder; import java.io.IOException; @@ -57,7 +59,6 @@ public abstract class UserStreamCallback implements RawCallback { onException(cause); return; } - final JacksonJrSimpleTreeCodec mapper = new JacksonJrSimpleTreeCodec(); final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), "UTF-8")); try { for (String line; (line = reader.readLine()) != null && !disconnected; ) { @@ -65,74 +66,78 @@ public abstract class UserStreamCallback implements RawCallback { onConnected(); connected = true; } - if (line.isEmpty()) continue; - TreeNode rootNode = mapper.readTree(LoganSquare.JSON_FACTORY.createParser(line)); - switch (JSONObjectType.determine(rootNode)) { - case SENDER: { + if (TextUtils.isEmpty(line)) continue; + final TwitterStreamObject object = LoganSquare.parse(line, TwitterStreamObject.class); + switch (object.determine()) { + case Type.SENDER: { break; } - case STATUS: { - onStatus(LoganSquareMapperFinder.mapperFor(Status.class).parse(rootNode.traverse())); + case Type.STATUS: { + onStatus(LoganSquareMapperFinder.mapperFor(Status.class).parse(line)); break; } - case DIRECT_MESSAGE: { - onDirectMessage(LoganSquareMapperFinder.mapperFor(DirectMessage.class).parse(rootNode.traverse())); + case Type.DIRECT_MESSAGE: { + onDirectMessage(object.getDirectMessage()); break; } - case DELETE: { + case Type.DELETE: { + final TwitterStreamObject.Delete delete = object.getDelete(); + if (delete.getStatus() != null) { + onStatusDeleted(delete.getStatus()); + } else if (delete.getDirectMessage() != null) { + onDirectMessageDeleted(delete.getDirectMessage()); + } break; } - case LIMIT: + case Type.LIMIT: break; - case STALL_WARNING: + case Type.STALL_WARNING: break; - case SCRUB_GEO: + case Type.SCRUB_GEO: break; - case FRIENDS: + case Type.FRIENDS: break; - case FAVORITE: { - onFavorite(parse(User.class, rootNode.get("source")), - parse(User.class, rootNode.get("target")), - parse(Status.class, rootNode.get("target_object"))); + case Type.FAVORITE: { + StatusFavoriteEvent event = LoganSquareMapperFinder.mapperFor(StatusFavoriteEvent.class).parse(line); + onFavorite(event.getSource(), event.getTarget(), event.getTargetObject()); break; } - case UNFAVORITE: { - onUnfavorite(parse(User.class, rootNode.get("source")), - parse(User.class, rootNode.get("target")), - parse(Status.class, rootNode.get("target_object"))); + case Type.UNFAVORITE: { + StatusFavoriteEvent event = LoganSquareMapperFinder.mapperFor(StatusFavoriteEvent.class).parse(line); + onUnfavorite(event.getSource(), event.getTarget(), event.getTargetObject()); break; } - case FOLLOW: + case Type.FOLLOW: break; - case UNFOLLOW: + case Type.UNFOLLOW: break; - case USER_LIST_MEMBER_ADDED: + case Type.USER_LIST_MEMBER_ADDED: break; - case USER_LIST_MEMBER_DELETED: + case Type.USER_LIST_MEMBER_DELETED: break; - case USER_LIST_SUBSCRIBED: + case Type.USER_LIST_SUBSCRIBED: break; - case USER_LIST_UNSUBSCRIBED: + case Type.USER_LIST_UNSUBSCRIBED: break; - case USER_LIST_CREATED: + case Type.USER_LIST_CREATED: break; - case USER_LIST_UPDATED: + case Type.USER_LIST_UPDATED: break; - case USER_LIST_DESTROYED: + case Type.USER_LIST_DESTROYED: break; - case USER_UPDATE: + case Type.USER_UPDATE: break; - case USER_DELETE: + case Type.USER_DELETE: break; - case USER_SUSPEND: + case Type.USER_SUSPEND: break; - case BLOCK: + case Type.BLOCK: break; - case UNBLOCK: + case Type.UNBLOCK: break; - case DISCONNECTION: + case Type.DISCONNECTION: break; - case UNKNOWN: + case Type.UNKNOWN: break; } } @@ -161,17 +166,19 @@ public abstract class UserStreamCallback implements RawCallback { public abstract void onConnected(); - public abstract void onBlock(User source, User blockedUser); - - public abstract void onDeletionNotice(long directMessageId, long userId); - - public abstract void onDeletionNotice(StatusDeletionNotice statusDeletionNotice); + public abstract void onStatus(Status status); public abstract void onDirectMessage(DirectMessage directMessage); + public abstract void onBlock(User source, User blockedUser); + + public abstract void onDirectMessageDeleted(DeletionEvent event); + + public abstract void onStatusDeleted(DeletionEvent event); + public abstract void onException(Throwable ex); - public abstract void onFavorite(User source, User target, Status favoritedStatus); + public abstract void onFavorite(User source, User target, Status targetStatus); public abstract void onFollow(User source, User followedUser); @@ -181,13 +188,11 @@ public abstract class UserStreamCallback implements RawCallback { public abstract void onStallWarning(Warning warn); - public abstract void onStatus(Status status); - public abstract void onTrackLimitationNotice(int numberOfLimitedStatuses); public abstract void onUnblock(User source, User unblockedUser); - public abstract void onUnfavorite(User source, User target, Status unfavoritedStatus); + public abstract void onUnfavorite(User source, User target, Status targetStatus); public abstract void onUserListCreation(User listOwner, UserList list); diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/DeletionEvent.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/DeletionEvent.java new file mode 100644 index 000000000..e21a67f10 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/DeletionEvent.java @@ -0,0 +1,31 @@ +package org.mariotaku.twidere.api.twitter.model; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +/** + * Created by mariotaku on 16/2/26. + */ +@JsonObject +public class DeletionEvent { + + @JsonField(name = "id") + long id; + @JsonField(name = "user_id") + long userId; + @JsonField(name = "timestamp_ms") + long timestampMs; + + public long getId() { + return id; + } + + public long getUserId() { + return userId; + } + + public long getTimestampMs() { + return timestampMs; + } + +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusFavoriteEvent.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusFavoriteEvent.java new file mode 100644 index 000000000..812a20b1d --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusFavoriteEvent.java @@ -0,0 +1,29 @@ +package org.mariotaku.twidere.api.twitter.model; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +/** + * Created by mariotaku on 16/2/26. + */ +@JsonObject +public class StatusFavoriteEvent { + @JsonField(name = "source") + User source; + @JsonField(name = "target") + User target; + @JsonField(name = "target_object") + Status targetObject; + + public User getSource() { + return source; + } + + public User getTarget() { + return target; + } + + public Status getTargetObject() { + return targetObject; + } +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUtils.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUtils.java deleted file mode 100644 index 4112ad410..000000000 --- a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/StatusUtils.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.mariotaku.twidere.api.twitter.model; - -import android.support.annotation.NonNull; - -import org.mariotaku.twidere.model.ParcelableStatus; -import org.mariotaku.twidere.util.InternalTwitterContentUtils; - -import java.util.Date; - -/** - * Created by mariotaku on 16/1/3. - */ -public class StatusUtils { - - public static Status fromParcelableStatus(@NonNull ParcelableStatus parcelable) { - Status status = new Status(); - status.id = parcelable.id; - status.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain); - status.createdAt = new Date(parcelable.timestamp); - status.inReplyToStatusId = parcelable.in_reply_to_status_id; - status.inReplyToUserId = parcelable.in_reply_to_user_id; - status.inReplyToScreenName = parcelable.in_reply_to_screen_name; - if (parcelable.is_retweet) { - Status retweet = status.retweetedStatus = new Status(); - retweet.id = parcelable.retweet_id; - retweet.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain); - retweet.createdAt = new Date(parcelable.retweet_timestamp); - User retweetUser = retweet.user = new User(); - retweetUser.id = parcelable.user_id; - retweetUser.screenName = parcelable.user_screen_name; - retweetUser.name = parcelable.user_name; - retweetUser.profileBackgroundImageUrl = parcelable.user_profile_image_url; - - User user = status.user = new User(); - user.id = parcelable.retweeted_by_user_id; - user.name = parcelable.retweeted_by_user_name; - user.screenName = parcelable.retweeted_by_user_screen_name; - user.profileImageUrl = parcelable.retweeted_by_user_profile_image; - } else if (parcelable.is_quote) { - Status quote = status.quotedStatus = new Status(); - quote.id = parcelable.quoted_id; - quote.text = InternalTwitterContentUtils.escapeTwitterStatusText(parcelable.quoted_text_plain); - quote.createdAt = new Date(parcelable.quoted_timestamp); - User quotedUser = quote.user = new User(); - quotedUser.id = parcelable.quoted_user_id; - quotedUser.name = parcelable.quoted_user_name; - quotedUser.screenName = parcelable.quoted_user_screen_name; - quotedUser.profileImageUrl = parcelable.quoted_user_profile_image; - - User user = status.user = new User(); - user.id = parcelable.user_id; - user.screenName = parcelable.user_screen_name; - user.name = parcelable.user_name; - user.profileBackgroundImageUrl = parcelable.user_profile_image_url; - } else { - User user = status.user = new User(); - user.id = parcelable.user_id; - user.screenName = parcelable.user_screen_name; - user.name = parcelable.user_name; - user.profileBackgroundImageUrl = parcelable.user_profile_image_url; - } - return status; - } - -} diff --git a/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterStreamObject.java b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterStreamObject.java new file mode 100644 index 000000000..930973001 --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/api/twitter/model/TwitterStreamObject.java @@ -0,0 +1,161 @@ +package org.mariotaku.twidere.api.twitter.model; + +import android.support.annotation.StringDef; + +import com.bluelinelabs.logansquare.annotation.JsonField; +import com.bluelinelabs.logansquare.annotation.JsonObject; + +/** + * Created by mariotaku on 16/2/26. + */ +@JsonObject +public class TwitterStreamObject { + + + @JsonField(name = "sender") + EmptyObject sender; + @JsonField(name = "event") + String event; + @JsonField(name = "text") + String text; + @JsonField(name = "direct_message") + DirectMessage directMessage; + @JsonField(name = "delete") + Delete delete; + @JsonField(name = "disconnect") + EmptyObject disconnect; + @JsonField(name = "limit") + EmptyObject limit; + @JsonField(name = "warning") + EmptyObject warning; + @JsonField(name = "scrub_geo") + EmptyObject scrubGeo; + @JsonField(name = "friends") + EmptyObject friends; + + @Type + public String determine() { + // This code originally lived in AbstractStreamImplementation. + // I've moved it in here to expose it as a public encapsulation of + // the object type determination logic. + if (sender != null) { + return Type.SENDER; + } else if (text != null) { + return Type.STATUS; + } else if (directMessage != null) { + return Type.DIRECT_MESSAGE; + } else if (delete != null) { + return Type.DELETE; + } else if (limit != null) { + return Type.LIMIT; + } else if (warning != null) { + return Type.STALL_WARNING; + } else if (scrubGeo != null) { + return Type.SCRUB_GEO; + } else if (friends != null) { + return Type.FRIENDS; + } else if (disconnect != null) { + return Type.DISCONNECTION; + } else if (event != null) { + switch (event) { + case "favorite": + return Type.FAVORITE; + case "unfavorite": + return Type.UNFAVORITE; + case "follow": + return Type.FOLLOW; + case "unfollow": + return Type.UNFOLLOW; + case "list_member_added": + return Type.USER_LIST_MEMBER_ADDED; + case "list_member_removed": + return Type.USER_LIST_MEMBER_DELETED; + case "list_user_subscribed": + return Type.USER_LIST_SUBSCRIBED; + case "list_user_unsubscribed": + return Type.USER_LIST_UNSUBSCRIBED; + case "list_created": + return Type.USER_LIST_CREATED; + case "list_updated": + return Type.USER_LIST_UPDATED; + case "list_destroyed": + return Type.USER_LIST_DESTROYED; + case "user_update": + return Type.USER_UPDATE; + case "user_delete": + return Type.USER_DELETE; + case "user_suspend": + return Type.USER_SUSPEND; + case "block": + return Type.BLOCK; + case "unblock": + return Type.UNBLOCK; + } + } + return Type.UNKNOWN; + } + + public DirectMessage getDirectMessage() { + return directMessage; + } + + public Delete getDelete() { + return delete; + } + + @StringDef({Type.SENDER, Type.STATUS, Type.DIRECT_MESSAGE, Type.DELETE, Type.LIMIT, + Type.STALL_WARNING, Type.SCRUB_GEO, Type.FRIENDS, Type.FAVORITE, Type.UNFAVORITE, + Type.FOLLOW, Type.UNFOLLOW, Type.USER_LIST_MEMBER_ADDED, Type.USER_LIST_MEMBER_DELETED, + Type.USER_LIST_SUBSCRIBED, Type.USER_LIST_UNSUBSCRIBED, Type.USER_LIST_CREATED, + Type.USER_LIST_UPDATED, Type.USER_LIST_DESTROYED, Type.USER_UPDATE, Type.USER_DELETE, + Type.USER_SUSPEND, Type.BLOCK, Type.UNBLOCK, Type.DISCONNECTION, Type.UNKNOWN}) + public @interface Type { + String SENDER = "sender"; + String STATUS = "status"; + String DIRECT_MESSAGE = "direct_message"; + String DELETE = "delete"; + String LIMIT = "limit"; + String STALL_WARNING = "stall_warning"; + String SCRUB_GEO = "scrub_geo"; + String FRIENDS = "friends"; + String FAVORITE = "favorite"; + String UNFAVORITE = "unfavorite"; + String FOLLOW = "follow"; + String UNFOLLOW = "unfollow"; + String USER_LIST_MEMBER_ADDED = "user_list_member_added"; + String USER_LIST_MEMBER_DELETED = "user_list_member_deleted"; + String USER_LIST_SUBSCRIBED = "user_list_subscribed"; + String USER_LIST_UNSUBSCRIBED = "user_list_unsubscribed"; + String USER_LIST_CREATED = "user_list_created"; + String USER_LIST_UPDATED = "user_list_updated"; + String USER_LIST_DESTROYED = "user_list_destroyed"; + String USER_UPDATE = "user_update"; + String USER_DELETE = "user_delete"; + String USER_SUSPEND = "user_suspend"; + String BLOCK = "block"; + String UNBLOCK = "unblock"; + String DISCONNECTION = "disconnection"; + String UNKNOWN = "unknown"; + } + + @JsonObject + public static class EmptyObject { + + } + + @JsonObject + public static class Delete { + @JsonField(name = "status") + DeletionEvent status; + @JsonField(name = "direct_message") + DeletionEvent directMessage; + + public DeletionEvent getStatus() { + return status; + } + + public DeletionEvent getDirectMessage() { + return directMessage; + } + } +} 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 b2225f20a..619cc4742 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 @@ -30,7 +30,6 @@ import org.mariotaku.restfu.http.HttpResponse; import org.mariotaku.restfu.http.mime.Body; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.auth.OAuthToken; -import org.mariotaku.twidere.api.twitter.model.CardDataMap; import org.mariotaku.twidere.api.twitter.model.ResponseCode; import org.mariotaku.twidere.api.twitter.model.TwitterResponse; import org.mariotaku.twidere.util.LoganSquareMapperFinder; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ActivitiesByFriendsFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ActivitiesByFriendsFragment.java deleted file mode 100644 index 8aebf6590..000000000 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/ActivitiesByFriendsFragment.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2014 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.mariotaku.twidere.fragment.support; - -import android.content.Context; -import android.net.Uri; -import android.os.Bundle; -import android.support.annotation.NonNull; - -import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter; -import org.mariotaku.twidere.provider.TwidereDataStore; -import org.mariotaku.twidere.provider.TwidereDataStore.Activities; -import org.mariotaku.twidere.util.ErrorInfoStore; - -import edu.tsinghua.hotmobi.model.TimelineType; - -public class ActivitiesByFriendsFragment extends CursorActivitiesFragment { - - @Override - public boolean getActivities(long[] accountIds, long[] maxIds, long[] sinceIds) { - mTwitterWrapper.getActivitiesByFriendsAsync(accountIds, maxIds, sinceIds); - return false; - } - - @NonNull - @Override - @TimelineType - protected String getTimelineType() { - return TimelineType.OTHER; - } - - - @NonNull - @Override - protected String getErrorInfoKey() { - return ErrorInfoStore.KEY_ACTIVITIES_BY_FRIENDS; - } - - @Override - public Uri getContentUri() { - return Activities.ByFriends.CONTENT_URI; - } - - @Override - protected int getNotificationType() { - return 0; - } - - @Override - protected boolean isFilterEnabled() { - return false; - } - - @Override - protected void updateRefreshState() { - - } - - @NonNull - @Override - protected ParcelableActivitiesAdapter onCreateAdapter(Context context, boolean compact) { - final ParcelableActivitiesAdapter adapter = new ParcelableActivitiesAdapter(context, compact, - true); - final Bundle arguments = getArguments(); - if (arguments != null) { - final Bundle extras = arguments.getBundle(EXTRA_EXTRAS); - if (extras != null) { - adapter.setFollowingOnly(extras.getBoolean(EXTRA_MY_FOLLOWING_ONLY)); - adapter.setMentionsOnly(extras.getBoolean(EXTRA_MENTIONS_ONLY)); - } - } - return adapter; - } - - - @Override - public boolean isRefreshing() { - return false; - } - -} diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/MessagesConversationFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/MessagesConversationFragment.java index f00c8366c..e300b0bd6 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/MessagesConversationFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/MessagesConversationFragment.java @@ -87,6 +87,7 @@ import org.mariotaku.twidere.model.ParcelableCredentials; import org.mariotaku.twidere.model.ParcelableDirectMessage; import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.model.ParcelableUserCursorIndices; +import org.mariotaku.twidere.model.message.TaskStateChangedEvent; import org.mariotaku.twidere.provider.TwidereDataStore; import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers; import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages; @@ -107,7 +108,6 @@ import org.mariotaku.twidere.util.ReadStateManager; import org.mariotaku.twidere.util.UserColorNameManager; import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.dagger.GeneralComponentHelper; -import org.mariotaku.twidere.model.message.TaskStateChangedEvent; import org.mariotaku.twidere.view.ComposeEditText; import java.util.ArrayList; @@ -305,8 +305,11 @@ public class MessagesConversationFragment extends BaseSupportFragment implements final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1); final long userId = args.getLong(EXTRA_RECIPIENT_ID, -1); final int accountPos = accountsSpinnerAdapter.findItemPosition(accountId); - account = accountPos < 0 ? DataStoreUtils.getCredentials(activity, accountId) - : accountsSpinnerAdapter.getItem(accountPos); + if (accountPos >= 0) { + mAccountSpinner.setSelection(accountPos); + } + account = accountPos >= 0 ? accountsSpinnerAdapter.getItem(accountPos) : + DataStoreUtils.getCredentials(activity, accountId); recipient = Utils.getUserForConversation(activity, accountId, userId); } else { account = null; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java index 9eeb083a1..123f250f4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/support/UserListFragment.java @@ -20,7 +20,6 @@ package org.mariotaku.twidere.fragment.support; import android.app.Activity; -import android.app.AlertDialog; import android.app.Dialog; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; @@ -43,6 +42,8 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.AsyncTaskLoader; import android.support.v4.content.Loader; import android.support.v4.view.ViewPager; +import android.support.v7.app.AlertDialog; +import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -432,8 +433,6 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList public static class EditUserListDialogFragment extends BaseSupportDialogFragment implements DialogInterface.OnClickListener { - private MaterialEditText mEditName, mEditDescription; - private CheckBox mPublicCheckBox; private String mName, mDescription; private long mAccountId; private long mListId; @@ -444,14 +443,18 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList if (mAccountId <= 0) return; switch (which) { case DialogInterface.BUTTON_POSITIVE: { - mName = ParseUtils.parseString(mEditName.getText()); - mDescription = ParseUtils.parseString(mEditDescription.getText()); - mIsPublic = mPublicCheckBox.isChecked(); - if (mName == null || mName.length() <= 0) return; + final AlertDialog alertDialog = (AlertDialog) dialog; + final MaterialEditText editName = (MaterialEditText) alertDialog.findViewById(R.id.name); + final MaterialEditText editDescription = (MaterialEditText) alertDialog.findViewById(R.id.description); + final CheckBox editIsPublic = (CheckBox) alertDialog.findViewById(R.id.is_public); + final String name = ParseUtils.parseString(editName.getText()); + final String description = ParseUtils.parseString(editDescription.getText()); + final boolean isPublic = editIsPublic.isChecked(); + if (TextUtils.isEmpty(name)) return; final UserListUpdate update = new UserListUpdate(); - update.setMode(mIsPublic ? UserList.Mode.PUBLIC : UserList.Mode.PRIVATE); - update.setName(mName); - update.setDescription(mDescription); + update.setMode(isPublic ? UserList.Mode.PUBLIC : UserList.Mode.PRIVATE); + update.setName(name); + update.setDescription(description); mTwitterWrapper.updateUserListDetails(mAccountId, mListId, update); break; } @@ -470,23 +473,31 @@ public class UserListFragment extends BaseSupportFragment implements OnClickList mIsPublic = bundle == null || bundle.getBoolean(EXTRA_IS_PUBLIC, true); final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity()); final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped); - final View view = LayoutInflater.from(wrapped).inflate(R.layout.dialog_user_list_detail_editor, null); - builder.setView(view); - mEditName = (MaterialEditText) view.findViewById(R.id.name); - mEditName.addValidator(new UserListNameValidator(getString(R.string.invalid_list_name))); - mEditDescription = (MaterialEditText) view.findViewById(R.id.description); - mPublicCheckBox = (CheckBox) view.findViewById(R.id.is_public); - if (mName != null) { - mEditName.setText(mName); - } - if (mDescription != null) { - mEditDescription.setText(mDescription); - } - mPublicCheckBox.setChecked(mIsPublic); + builder.setView(R.layout.dialog_user_list_detail_editor); builder.setTitle(R.string.user_list); builder.setPositiveButton(android.R.string.ok, this); builder.setNegativeButton(android.R.string.cancel, this); - return builder.create(); + final AlertDialog dialog = builder.create(); + dialog.setOnShowListener(new DialogInterface.OnShowListener() { + @Override + public void onShow(DialogInterface dialog) { + + AlertDialog alertDialog = (AlertDialog) dialog; + MaterialEditText mEditName = (MaterialEditText) alertDialog.findViewById(R.id.name); + MaterialEditText mEditDescription = (MaterialEditText) alertDialog.findViewById(R.id.description); + CheckBox mPublicCheckBox = (CheckBox) alertDialog.findViewById(R.id.is_public); + + mEditName.addValidator(new UserListNameValidator(getString(R.string.invalid_list_name))); + if (mName != null) { + mEditName.setText(mName); + } + if (mDescription != null) { + mEditDescription.setText(mDescription); + } + mPublicCheckBox.setChecked(mIsPublic); + } + }); + return dialog; } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/menu/SupportStatusShareProvider.java b/twidere/src/main/java/org/mariotaku/twidere/menu/SupportStatusShareProvider.java index 7e93fe989..448a3ccbf 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/menu/SupportStatusShareProvider.java +++ b/twidere/src/main/java/org/mariotaku/twidere/menu/SupportStatusShareProvider.java @@ -30,7 +30,6 @@ import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.util.MenuUtils; -import static org.mariotaku.twidere.util.MenuUtils.addIntentToMenu; import static org.mariotaku.twidere.util.Utils.createStatusShareIntent; /** diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/UserFollowState.java b/twidere/src/main/java/org/mariotaku/twidere/model/UserFollowState.java index ebc8da54f..3ca2cc5c2 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/UserFollowState.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/UserFollowState.java @@ -2,10 +2,6 @@ package org.mariotaku.twidere.model; import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonObject; -import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease; - -import org.mariotaku.library.objectcursor.annotation.CursorField; -import org.mariotaku.twidere.provider.TwidereDataStore; /** * Created by mariotaku on 16/2/25. diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/message/FavoriteTaskEvent.java b/twidere/src/main/java/org/mariotaku/twidere/model/message/FavoriteTaskEvent.java index 133c42b36..9e793e7ad 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/message/FavoriteTaskEvent.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/message/FavoriteTaskEvent.java @@ -61,7 +61,7 @@ public class FavoriteTaskEvent { return status; } - public void setStatus(ParcelableStatus status) { + public void setStatus(@Nullable ParcelableStatus status) { this.status = status; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundJobService.java b/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundJobService.java index fe1d9720a..fd62ef6ec 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundJobService.java +++ b/twidere/src/main/java/org/mariotaku/twidere/service/BackgroundJobService.java @@ -19,6 +19,7 @@ package org.mariotaku.twidere.service; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.job.JobParameters; import android.app.job.JobService; @@ -27,6 +28,7 @@ import android.os.Build; /** * Created by mariotaku on 14/12/12. */ +@SuppressLint("Registered") @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class BackgroundJobService extends JobService { @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java b/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java index 7daecd94d..29fba006a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java +++ b/twidere/src/main/java/org/mariotaku/twidere/service/StreamingService.java @@ -28,9 +28,9 @@ import org.mariotaku.twidere.activity.SettingsActivity; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.TwitterUserStream; import org.mariotaku.twidere.api.twitter.UserStreamCallback; +import org.mariotaku.twidere.api.twitter.model.DeletionEvent; import org.mariotaku.twidere.api.twitter.model.DirectMessage; import org.mariotaku.twidere.api.twitter.model.Status; -import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice; import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.api.twitter.model.UserList; import org.mariotaku.twidere.api.twitter.model.Warning; @@ -221,16 +221,16 @@ public class StreamingService extends Service implements Constants { } @Override - public void onDeletionNotice(final long directMessageId, final long userId) { - final String where = DirectMessages.MESSAGE_ID + " = " + directMessageId; + public void onDirectMessageDeleted(final DeletionEvent event) { + final String where = Expression.equals(DirectMessages.MESSAGE_ID, event.getId()).getSQL(); for (final Uri uri : MESSAGES_URIS) { resolver.delete(uri, where, null); } } @Override - public void onDeletionNotice(final StatusDeletionNotice statusDeletionNotice) { - final long statusId = statusDeletionNotice.getStatusId(); + public void onStatusDeleted(final DeletionEvent event) { + final long statusId = event.getId(); resolver.delete(Statuses.CONTENT_URI, Expression.equals(Statuses.STATUS_ID, statusId).getSQL(), null); resolver.delete(Activities.AboutMe.CONTENT_URI, Expression.equals(Activities.AboutMe.STATUS_ID, statusId).getSQL(), null); } @@ -298,9 +298,9 @@ public class StreamingService extends Service implements Constants { } @Override - public void onFavorite(final User source, final User target, final Status favoritedStatus) { + public void onFavorite(final User source, final User target, final Status targetStatus) { final String message = String.format("%s favorited %s's tweet: %s", source.getScreenName(), - target.getScreenName(), favoritedStatus.getText()); + target.getScreenName(), targetStatus.getText()); Log.d(LOGTAG, message); } @@ -362,9 +362,9 @@ public class StreamingService extends Service implements Constants { } @Override - public void onUnfavorite(final User source, final User target, final Status unfavoritedStatus) { + public void onUnfavorite(final User source, final User target, final Status targetStatus) { final String message = String.format("%s unfavorited %s's tweet: %s", source.getScreenName(), - target.getScreenName(), unfavoritedStatus.getText()); + target.getScreenName(), targetStatus.getText()); Log.d(LOGTAG, message); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/AbstractTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/AbstractTask.java index 2c34c3b4e..068fa46d3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/AbstractTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/AbstractTask.java @@ -4,6 +4,7 @@ import android.support.annotation.MainThread; import android.support.annotation.WorkerThread; /** + * Abstract Task class can be used with different implementations * Created by mariotaku on 16/2/24. */ public abstract class AbstractTask { diff --git a/twidere/src/main/java/org/mariotaku/twidere/task/SaveFileTask.java b/twidere/src/main/java/org/mariotaku/twidere/task/SaveFileTask.java index c1cf3e823..d051f06fc 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/task/SaveFileTask.java +++ b/twidere/src/main/java/org/mariotaku/twidere/task/SaveFileTask.java @@ -26,7 +26,6 @@ import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; -import android.webkit.MimeTypeMap; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.util.Utils; diff --git a/twidere/src/main/java/org/mariotaku/twidere/text/ParagraphSpacingSpan.java b/twidere/src/main/java/org/mariotaku/twidere/text/ParagraphSpacingSpan.java deleted file mode 100644 index 9afec2556..000000000 --- a/twidere/src/main/java/org/mariotaku/twidere/text/ParagraphSpacingSpan.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2014 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.mariotaku.twidere.text; - -import android.graphics.Paint.FontMetricsInt; -import android.text.Spanned; -import android.text.style.LineHeightSpan; - -/** - * Created by mariotaku on 14/11/22. - */ -public class ParagraphSpacingSpan implements LineHeightSpan { - - private final float spacingMultiplier; - - public ParagraphSpacingSpan(float spacingMultiplier) { - this.spacingMultiplier = spacingMultiplier; - } - - @Override - public void chooseHeight(CharSequence text, int start, int end, - int spanstartv, int v, FontMetricsInt fm) { - Spanned spanned = (Spanned) text; - int en = spanned.getSpanEnd(this); - if (end - 1 == en) { - final int extra = Math.round((fm.bottom - fm.top) * (spacingMultiplier - 1)); - fm.descent += extra; - fm.bottom += extra; - } - } -} 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 562479869..5da9fe4ca 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/CustomTabUtils.java @@ -99,11 +99,6 @@ public class CustomTabUtils implements Constants { UserListTimelineFragment.class, R.string.list_timeline, R.drawable.ic_action_list, CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_USER_LIST, 7)); -// CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.ACTIVITIES_BY_FRIENDS, new CustomTabConfiguration( -// ActivitiesByFriendsFragment.class, R.string.activities_by_friends, -// R.drawable.ic_action_accounts, CustomTabConfiguration.ACCOUNT_OPTIONAL, -// CustomTabConfiguration.FIELD_TYPE_NONE, 9)); - CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.RETWEETS_OF_ME, new CustomTabConfiguration( RetweetsOfMeFragment.class, R.string.retweets_of_me, R.drawable.ic_action_retweet, CustomTabConfiguration.ACCOUNT_REQUIRED, CustomTabConfiguration.FIELD_TYPE_NONE, 10)); diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/DatabaseQueryUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/DatabaseQueryUtils.java deleted file mode 100644 index 7720f6588..000000000 --- a/twidere/src/main/java/org/mariotaku/twidere/util/DatabaseQueryUtils.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2015 Mariotaku Lee - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.mariotaku.twidere.util; - -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; - -import org.mariotaku.sqliteqb.library.SQLFunctions; - -public class DatabaseQueryUtils { - - public static int count(final SQLiteDatabase db, final String table, final String selection, - final String[] selectionArgs, final String groupBy, final String having, final String orderBy) { - if (db == null) return -1; - final Cursor c = db.query(table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy); - try { - if (c.moveToFirst()) return c.getInt(0); - return -1; - } finally { - c.close(); - } - } - - public static int count(final SQLiteDatabase db, boolean distinct, String table, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { - if (db == null) return -1; - final Cursor c = db.query(distinct, table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy, limit); - try { - if (c.moveToFirst()) return c.getInt(0); - return -1; - } finally { - c.close(); - } - } - - public static int count(final SQLiteDatabase db, String table, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) { - if (db == null) return -1; - final Cursor c = db.query(table, new String[]{SQLFunctions.COUNT()}, selection, selectionArgs, groupBy, having, orderBy, limit); - try { - if (c.moveToFirst()) return c.getInt(0); - return -1; - } finally { - c.close(); - } - } - - -} \ No newline at end of file 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 82ed28e58..0df0a8f0b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -23,7 +23,6 @@ import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.ActionBar; import android.app.Activity; -import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -69,17 +68,13 @@ import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentManager; import android.support.v4.app.ListFragment; import android.support.v4.content.ContextCompat; import android.support.v4.net.ConnectivityManagerCompat; import android.support.v4.util.Pair; -import android.support.v4.view.ActionProvider; import android.support.v4.view.GravityCompat; -import android.support.v4.view.MenuItemCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.ShareActionProvider; import android.system.ErrnoException; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -121,8 +116,6 @@ import org.mariotaku.twidere.BuildConfig; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.CopyLinkActivity; -import org.mariotaku.twidere.activity.support.AccountSelectorActivity; -import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity; import org.mariotaku.twidere.adapter.iface.IBaseAdapter; import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter; import org.mariotaku.twidere.annotation.CustomTabType; @@ -136,10 +129,7 @@ import org.mariotaku.twidere.api.twitter.model.Relationship; import org.mariotaku.twidere.api.twitter.model.Status; import org.mariotaku.twidere.api.twitter.model.UserMentionEntity; import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback; -import org.mariotaku.twidere.fragment.support.AbsStatusesFragment.DefaultOnLikedListener; import org.mariotaku.twidere.fragment.support.AccountsManagerFragment; -import org.mariotaku.twidere.fragment.support.AddStatusFilterDialogFragment; -import org.mariotaku.twidere.fragment.support.DestroyStatusDialogFragment; import org.mariotaku.twidere.fragment.support.DirectMessagesFragment; import org.mariotaku.twidere.fragment.support.DraftsFragment; import org.mariotaku.twidere.fragment.support.FiltersFragment; @@ -151,7 +141,6 @@ import org.mariotaku.twidere.fragment.support.MutesUsersListFragment; import org.mariotaku.twidere.fragment.support.SavedSearchesListFragment; import org.mariotaku.twidere.fragment.support.ScheduledStatusesFragment; import org.mariotaku.twidere.fragment.support.SearchFragment; -import org.mariotaku.twidere.fragment.support.SetUserNicknameDialogFragment; import org.mariotaku.twidere.fragment.support.StatusFavoritersListFragment; import org.mariotaku.twidere.fragment.support.StatusFragment; import org.mariotaku.twidere.fragment.support.StatusRepliesListFragment; @@ -172,10 +161,7 @@ import org.mariotaku.twidere.fragment.support.UserMentionsFragment; import org.mariotaku.twidere.fragment.support.UserProfileEditorFragment; import org.mariotaku.twidere.fragment.support.UserTimelineFragment; import org.mariotaku.twidere.fragment.support.UsersListFragment; -import org.mariotaku.twidere.graphic.ActionIconDrawable; import org.mariotaku.twidere.graphic.PaddingDrawable; -import org.mariotaku.twidere.menu.SupportStatusShareProvider; -import org.mariotaku.twidere.menu.support.FavoriteItemProvider; import org.mariotaku.twidere.model.AccountPreferences; import org.mariotaku.twidere.model.ParcelableAccount; import org.mariotaku.twidere.model.ParcelableCredentials; @@ -201,7 +187,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Conversati import org.mariotaku.twidere.provider.TwidereDataStore.Statuses; import org.mariotaku.twidere.service.RefreshService; import org.mariotaku.twidere.util.TwidereLinkify.HighlightStyle; -import org.mariotaku.twidere.util.menu.TwidereMenuInfo; import org.mariotaku.twidere.view.CardMediaContainer.PreviewStyle; import org.mariotaku.twidere.view.ShapedImageView; import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle; @@ -466,6 +451,7 @@ public final class Utils implements Constants { if (extras != null) { args.putAll(extras); } + boolean isAccountIdRequired = true; switch (linkId) { case LINK_ID_ACCOUNTS: { fragment = new AccountsManagerFragment(); @@ -609,6 +595,7 @@ public final class Utils implements Constants { } case LINK_ID_DIRECT_MESSAGES_CONVERSATION: { fragment = new MessagesConversationFragment(); + isAccountIdRequired = false; final String paramRecipientId = uri.getQueryParameter(QUERY_PARAM_RECIPIENT_ID); final String paramScreenName = uri.getQueryParameter(QUERY_PARAM_SCREEN_NAME); final long conversationId = NumberUtils.toLong(paramRecipientId, -1); @@ -775,7 +762,7 @@ public final class Utils implements Constants { final String paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME); if (paramAccountName != null) { args.putLong(EXTRA_ACCOUNT_ID, DataStoreUtils.getAccountId(context, paramAccountName)); - } else { + } else if (isAccountIdRequired) { final long accountId = getDefaultAccountId(context); if (isMyAccount(context, accountId)) { args.putLong(EXTRA_ACCOUNT_ID, accountId); @@ -1695,9 +1682,11 @@ public final class Utils implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_DIRECT_MESSAGES_CONVERSATION); - if (accountId > 0 && recipientId > 0) { + if (accountId > 0) { builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId)); - builder.appendQueryParameter(QUERY_PARAM_RECIPIENT_ID, String.valueOf(recipientId)); + if (recipientId > 0) { + builder.appendQueryParameter(QUERY_PARAM_RECIPIENT_ID, String.valueOf(recipientId)); + } } final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build()); intent.setPackage(BuildConfig.APPLICATION_ID); diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/support/ActivitySupport.java b/twidere/src/main/java/org/mariotaku/twidere/util/support/ActivitySupport.java index a7a03be7d..a953f68a4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/support/ActivitySupport.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/support/ActivitySupport.java @@ -10,6 +10,7 @@ import android.os.Parcel; import android.os.Parcelable; /** + * Backward compatibility utilities for {@link Activity} * Created by mariotaku on 14/11/4. */ public class ActivitySupport { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/HeaderDrawerLayout.java b/twidere/src/main/java/org/mariotaku/twidere/view/HeaderDrawerLayout.java index d83930864..48043ae7e 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/HeaderDrawerLayout.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/HeaderDrawerLayout.java @@ -361,7 +361,7 @@ public class HeaderDrawerLayout extends ViewGroup { } @Override - public void onViewReleased(View releasedChild, float xvel, float yvel) { + public void onViewReleased(View releasedChild, float xVel, float yVel) { mDrawer.mDragHelper.flingCapturedView(mDrawer.getPaddingLeft(), mDrawer.getHeaderTopMinimum(), mDrawer.getPaddingLeft(), mDrawer.getHeaderTopMaximum()); diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/MediaViewPager.java b/twidere/src/main/java/org/mariotaku/twidere/view/MediaViewPager.java index b29126a01..bd339e322 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/MediaViewPager.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/MediaViewPager.java @@ -20,7 +20,6 @@ package org.mariotaku.twidere.view; import android.content.Context; -import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.View; diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/SquareActionIconButton.java b/twidere/src/main/java/org/mariotaku/twidere/view/SquareActionIconButton.java index e36e1b07b..37bcfc235 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/SquareActionIconButton.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/SquareActionIconButton.java @@ -22,7 +22,6 @@ package org.mariotaku.twidere.view; import android.content.Context; import android.util.AttributeSet; import android.view.ViewGroup; -import android.widget.ImageView; public class SquareActionIconButton extends ActionIconButton { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/AccentProgressWheel.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/AccentProgressWheel.java index ed40572f6..d72de072d 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/AccentProgressWheel.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/AccentProgressWheel.java @@ -29,6 +29,8 @@ import com.pnikosis.materialishprogress.ProgressWheel; import org.mariotaku.twidere.view.iface.IThemeAccentView; /** + * ProgressWheel view that supports theme color settings + * * Created by mariotaku on 15/4/25. */ public class AccentProgressWheel extends ProgressWheel implements IThemeAccentView { diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java index ca7faee51..b312a571b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/themed/ThemedTextView.java @@ -20,8 +20,6 @@ package org.mariotaku.twidere.view.themed; import android.content.Context; -import android.content.res.ColorStateList; -import android.support.annotation.Nullable; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; diff --git a/twidere/src/main/res/layout/header_status_common.xml b/twidere/src/main/res/layout/header_status_common.xml index 6fa71b840..4e479bf52 100644 --- a/twidere/src/main/res/layout/header_status_common.xml +++ b/twidere/src/main/res/layout/header_status_common.xml @@ -66,7 +66,8 @@ android:contentDescription="@string/profile_image" android:scaleType="centerCrop" app:sivBorder="true" - app:sivBorderWidth="1dp"/> + app:sivBorderWidth="1dp" + tools:src="@mipmap/ic_launcher"/> + tools:text="Jan 1 2015 0:00 ยท Twidere"/> @@ -376,7 +377,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/quote_original_link" - android:orientation="horizontal"> + android:orientation="horizontal" + tools:visibility="visible"> @@ -391,7 +393,8 @@ android:layout_alignTop="@+id/counts_users_height_holder" android:layout_marginLeft="@dimen/element_spacing_small" android:layout_marginRight="@dimen/element_spacing_small" - android:splitMotionEvents="false"/> + android:splitMotionEvents="false" + tools:visibility="invisible"/>