From af2ff443285be675a85d595661f8d0b1ecd2f1f1 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Fri, 11 Mar 2016 22:23:09 +0800 Subject: [PATCH] improved oauth browser sign in --- .../twidere/api/twitter/TwitterOAuth.java | 4 ++ .../mariotaku/twidere/util/UriUtilsTest.java | 34 +++++++++++ .../preview/PreviewMediaExtractorTest.java | 33 ----------- .../support/BrowserSignInActivity.java | 57 ++++++++++--------- .../activity/support/SignInActivity.java | 40 ++++++++----- .../twidere/model/util/UserKeyUtils.java | 4 +- .../util/InternalTwitterContentUtils.java | 3 +- .../twidere/util/TwitterAPIFactory.java | 25 +++++++- .../org/mariotaku/twidere/util/UriUtils.java | 43 ++++++++++++++ .../media/preview/PreviewMediaExtractor.java | 28 --------- .../preview/provider/InstagramProvider.java | 8 +-- .../util/media/preview/provider/Provider.java | 0 .../provider/TwitterMediaProvider.java | 8 +-- .../ActivityTitleSummaryViewHolder.java | 5 ++ .../res/layout/card_item_activity_summary.xml | 4 +- .../card_item_activity_summary_compact.xml | 4 +- 16 files changed, 181 insertions(+), 119 deletions(-) create mode 100644 twidere/src/androidTest/java/org/mariotaku/twidere/util/UriUtilsTest.java delete mode 100644 twidere/src/androidTest/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractorTest.java rename {twidere.component.common => twidere}/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java (74%) rename {twidere.component.common => twidere}/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java (87%) rename {twidere.component.common => twidere}/src/main/java/org/mariotaku/twidere/util/media/preview/provider/Provider.java (100%) rename {twidere.component.common => twidere}/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java (85%) diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterOAuth.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterOAuth.java index cc3da8ae9..5bb19448a 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterOAuth.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/TwitterOAuth.java @@ -45,4 +45,8 @@ public interface TwitterOAuth { OAuthToken getAccessToken(@Extra({"oauth_token", "oauth_token_secret"}) OAuthToken requestToken, @Param("oauth_verifier") String oauthVerifier) throws TwitterException; + @POST("/oauth/access_token") + OAuthToken getAccessToken(@Extra({"oauth_token", "oauth_token_secret"}) OAuthToken requestToken) + throws TwitterException; + } diff --git a/twidere/src/androidTest/java/org/mariotaku/twidere/util/UriUtilsTest.java b/twidere/src/androidTest/java/org/mariotaku/twidere/util/UriUtilsTest.java new file mode 100644 index 000000000..4abddbc76 --- /dev/null +++ b/twidere/src/androidTest/java/org/mariotaku/twidere/util/UriUtilsTest.java @@ -0,0 +1,34 @@ +package org.mariotaku.twidere.util; + + +import org.junit.Test; +import org.mariotaku.twidere.util.UriUtils; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; + +/** + * Created by mariotaku on 16/2/9. + */ +public class UriUtilsTest { + + @Test + public void testGetAuthority() throws Exception { + assertEquals("www.google.com", UriUtils.getAuthority("http://www.google.com/")); + assertEquals("twitter.com", UriUtils.getAuthority("https://twitter.com")); + assertNull(UriUtils.getAuthority("www.google.com/")); + } + + @Test + public void testGetPath() throws Exception { + assertEquals("/", UriUtils.getPath("http://www.example.com/")); + assertEquals("", UriUtils.getPath("http://www.example.com")); + assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path")); + assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path?with=query")); + assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/?with=query")); + assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path?with=query#fragment")); + assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/?with=query#fragment")); + assertEquals("/test/path", UriUtils.getPath("https://example.com/test/path#fragment")); + assertEquals("/test/path/", UriUtils.getPath("https://example.com/test/path/#fragment")); + } +} \ No newline at end of file diff --git a/twidere/src/androidTest/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractorTest.java b/twidere/src/androidTest/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractorTest.java deleted file mode 100644 index 7fa79b3a4..000000000 --- a/twidere/src/androidTest/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractorTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.mariotaku.twidere.util.media.preview; - - -import org.junit.Test; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNull; - -/** - * Created by mariotaku on 16/2/9. - */ -public class PreviewMediaExtractorTest { - - @Test - public void testGetAuthority() throws Exception { - assertEquals("www.google.com", PreviewMediaExtractor.getAuthority("http://www.google.com/")); - assertEquals("twitter.com", PreviewMediaExtractor.getAuthority("https://twitter.com")); - assertNull(PreviewMediaExtractor.getAuthority("www.google.com/")); - } - - @Test - public void testGetPath() throws Exception { - assertEquals("/", PreviewMediaExtractor.getPath("http://www.example.com/")); - assertEquals("", PreviewMediaExtractor.getPath("http://www.example.com")); - assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path")); - assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path?with=query")); - assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/?with=query")); - assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path?with=query#fragment")); - assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/?with=query#fragment")); - assertEquals("/test/path", PreviewMediaExtractor.getPath("https://example.com/test/path#fragment")); - assertEquals("/test/path/", PreviewMediaExtractor.getPath("https://example.com/test/path/#fragment")); - } -} \ No newline at end of file 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 9073e95a8..26cd8cc40 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 @@ -22,7 +22,6 @@ package org.mariotaku.twidere.activity.support; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; -import android.content.SharedPreferences; import android.graphics.Bitmap; import android.net.Uri; import android.os.AsyncTask; @@ -30,7 +29,6 @@ import android.os.Bundle; import android.util.Log; import android.view.MenuItem; import android.view.View; -import android.view.Window; import android.webkit.JavascriptInterface; import android.webkit.WebSettings; import android.webkit.WebView; @@ -38,12 +36,11 @@ import android.widget.Toast; import org.attoparser.AttoParseException; import org.mariotaku.restfu.http.Authorization; +import org.mariotaku.restfu.http.Endpoint; import org.mariotaku.twidere.R; import org.mariotaku.twidere.api.twitter.TwitterOAuth; import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization; -import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint; import org.mariotaku.twidere.api.twitter.auth.OAuthToken; -import org.mariotaku.twidere.app.TwidereApplication; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.OAuthPasswordAuthenticator; @@ -52,9 +49,9 @@ import org.mariotaku.twidere.util.webkit.DefaultWebViewClient; import java.io.IOException; import java.io.StringReader; +import java.util.Set; import static android.text.TextUtils.isEmpty; -import static org.mariotaku.twidere.util.Utils.getNonEmptyString; @SuppressLint("SetJavaScriptEnabled") public class BrowserSignInActivity extends BaseAppCompatActivity { @@ -97,7 +94,6 @@ public class BrowserSignInActivity extends BaseAppCompatActivity { @SuppressLint("AddJavascriptInterface") @Override protected void onCreate(final Bundle savedInstanceState) { - requestWindowFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); setContentView(R.layout.activity_browser_sign_in); mWebView.setWebViewClient(new AuthorizationWebViewClient(this)); @@ -152,7 +148,25 @@ public class BrowserSignInActivity extends BaseAppCompatActivity { public void onPageFinished(final WebView view, final String url) { super.onPageFinished(view, url); view.loadUrl(INJECT_CONTENT); - ((BrowserSignInActivity) getActivity()).setLoadProgressShown(false); + final BrowserSignInActivity activity = (BrowserSignInActivity) getActivity(); + activity.setLoadProgressShown(false); + Uri uri = Uri.parse(url); + // Hack for fanfou + if ("fanfou.com".equals(uri.getHost())) { + final String path = uri.getPath(); + final Set paramNames = uri.getQueryParameterNames(); + if ("/oauth/authorize".equals(path) && paramNames.contains("oauth_callback")) { + // Sign in successful response. + final OAuthToken requestToken = activity.mRequestToken; + if (requestToken != null) { + final Intent intent = new Intent(); + intent.putExtra(EXTRA_REQUEST_TOKEN, requestToken.getOauthToken()); + intent.putExtra(EXTRA_REQUEST_TOKEN_SECRET, requestToken.getOauthTokenSecret()); + activity.setResult(RESULT_OK, intent); + activity.finish(); + } + } + } } @Override @@ -167,7 +181,7 @@ public class BrowserSignInActivity extends BaseAppCompatActivity { final String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); final Activity activity = getActivity(); - Toast.makeText(activity, R.string.error_occurred, Toast.LENGTH_SHORT).show(); + Toast.makeText(activity, description, Toast.LENGTH_SHORT).show(); activity.finish(); } @@ -196,36 +210,27 @@ public class BrowserSignInActivity extends BaseAppCompatActivity { static class GetRequestTokenTask extends AsyncTask { private final String mConsumerKey, mConsumerSecret; - private final TwidereApplication mApplication; - private final SharedPreferences mPreferences; private final BrowserSignInActivity mActivity; + private final String mAPIUrlFormat; public GetRequestTokenTask(final BrowserSignInActivity activity) { mActivity = activity; - mApplication = TwidereApplication.getInstance(activity); - mPreferences = activity.getSharedPreferences(SHARED_PREFERENCES_NAME, MODE_PRIVATE); final Intent intent = activity.getIntent(); mConsumerKey = intent.getStringExtra(Accounts.CONSUMER_KEY); mConsumerSecret = intent.getStringExtra(Accounts.CONSUMER_SECRET); + mAPIUrlFormat = intent.getStringExtra(Accounts.API_URL_FORMAT); } @Override protected OAuthToken doInBackground(final Object... params) { - final String defConsumerKey = getNonEmptyString(mPreferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY); - final String defConsumerSecret = getNonEmptyString(mPreferences, KEY_CONSUMER_SECRET, - TWITTER_CONSUMER_SECRET); - final String consumerKey, consumerSecret; - if (!isEmpty(mConsumerKey) && !isEmpty(mConsumerSecret)) { - consumerKey = mConsumerKey; - consumerSecret = mConsumerSecret; - } else { - consumerKey = defConsumerKey; - consumerSecret = defConsumerSecret; + if (isEmpty(mConsumerKey) || isEmpty(mConsumerSecret)) { + return null; } try { - final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null)); - final Authorization auth = new OAuthAuthorization(consumerKey, consumerSecret); - final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint, auth, TwitterOAuth.class); + final Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(mAPIUrlFormat, true); + final Authorization auth = new OAuthAuthorization(mConsumerKey, mConsumerSecret); + final TwitterOAuth twitter = TwitterAPIFactory.getInstance(mActivity, endpoint, + auth, TwitterOAuth.class); return twitter.getRequestToken(OAUTH_CALLBACK_OOB); } catch (final Exception e) { Log.w(LOGTAG, e); @@ -244,7 +249,7 @@ public class BrowserSignInActivity extends BaseAppCompatActivity { } return; } - final OAuthEndpoint endpoint = new OAuthEndpoint(TwitterAPIFactory.getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, "api", null)); + final Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(mAPIUrlFormat, true); mActivity.loadUrl(endpoint.construct("/oauth/authorize", new String[]{"oauth_token", data.getOauthToken()})); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java index 5ea3e1714..1fff7632f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/SignInActivity.java @@ -267,6 +267,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList final Intent intent = new Intent(this, BrowserSignInActivity.class); intent.putExtra(Accounts.CONSUMER_KEY, mConsumerKey); intent.putExtra(Accounts.CONSUMER_SECRET, mConsumerSecret); + intent.putExtra(Accounts.API_URL_FORMAT, mAPIUrlFormat); startActivityForResult(intent, REQUEST_BROWSER_SIGN_IN); break; } @@ -640,17 +641,20 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList public static class BrowserSignInTask extends AbstractSignInTask { - private final String oauthVerifier; - private final Context context; + @NonNull private final String apiUrlFormat; - private final boolean sameOauthSigningUrl, noVersionSuffix; + @Nullable + private final String oauthVerifier; private final OAuthToken consumerKey, requestToken; + private final boolean sameOauthSigningUrl, noVersionSuffix; - public BrowserSignInTask(final SignInActivity context, OAuthToken consumerKey, - final OAuthToken requestToken, - final String oauthVerifier, @NonNull final String apiUrlFormat, + public BrowserSignInTask(@NonNull final SignInActivity context, + @NonNull final OAuthToken consumerKey, + @NonNull final OAuthToken requestToken, + @Nullable final String oauthVerifier, + @NonNull final String apiUrlFormat, final boolean sameOauthSigningUrl, final boolean noVersionSuffix) { super(context); this.context = context; @@ -666,23 +670,26 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList protected SignInResponse doInBackground(final Object... params) { try { final String versionSuffix = noVersionSuffix ? null : "1.1"; - Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, + Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat, sameOauthSigningUrl); final TwitterOAuth oauth = TwitterAPIFactory.getInstance(context, endpoint, new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret()), TwitterOAuth.class); - final OAuthToken accessToken = oauth.getAccessToken(requestToken, oauthVerifier); - final String userId = accessToken.getUserId(); - if (userId == null) return new SignInResponse(false, false, null); + final OAuthToken accessToken; + if (oauthVerifier != null) { + accessToken = oauth.getAccessToken(requestToken, oauthVerifier); + } else { + accessToken = oauth.getAccessToken(requestToken); + } final OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret(), accessToken); endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", versionSuffix, sameOauthSigningUrl); - final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint, - auth, Twitter.class); + final Twitter twitter = TwitterAPIFactory.getInstance(context, endpoint, auth, + Twitter.class); final User user = twitter.verifyCredentials(); final int color = analyseUserProfileColor(user); - return new SignInResponse(isUserLoggedIn(context, userId), auth, user, + return new SignInResponse(isUserLoggedIn(context, user.getId()), auth, user, ParcelableCredentials.AUTH_TYPE_OAUTH, color, apiUrlFormat, sameOauthSigningUrl, noVersionSuffix, detectAccountType(twitter, user)); } catch (final TwitterException e) { @@ -759,7 +766,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authOAuth() throws AuthenticationException, TwitterException { final SignInActivity activity = activityRef.get(); if (activity == null) return new SignInResponse(false, false, null); - Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl); + Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat, + sameOAuthSigningUrl); OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret()); final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class); final OAuthPasswordAuthenticator authenticator = new OAuthPasswordAuthenticator(oauth, verificationCallback, userAgent); @@ -773,7 +781,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList private SignInResponse authxAuth() throws TwitterException { final SignInActivity activity = activityRef.get(); if (activity == null) return new SignInResponse(false, false, null); - Endpoint endpoint = TwitterAPIFactory.getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl); + Endpoint endpoint = TwitterAPIFactory.getOAuthSignInEndpoint(apiUrlFormat, + sameOAuthSigningUrl); OAuthAuthorization auth = new OAuthAuthorization(consumerKey.getOauthToken(), consumerKey.getOauthTokenSecret()); final TwitterOAuth oauth = TwitterAPIFactory.getInstance(activity, endpoint, auth, TwitterOAuth.class); final OAuthToken accessToken = oauth.getAccessToken(username, password); @@ -963,6 +972,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList final AlertDialog alertDialog = (AlertDialog) dialog; final TextView verificationHint = (TextView) alertDialog.findViewById(R.id.verification_hint); final EditText editVerification = (EditText) alertDialog.findViewById(R.id.edit_verification_code); + if (verificationHint == null || editVerification == null) return; if ("Push".equalsIgnoreCase(challengeType)) { verificationHint.setText(R.string.login_verification_push_hint); editVerification.setVisibility(View.GONE); diff --git a/twidere/src/main/java/org/mariotaku/twidere/model/util/UserKeyUtils.java b/twidere/src/main/java/org/mariotaku/twidere/model/util/UserKeyUtils.java index 45457fe8b..ec365fca5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/model/util/UserKeyUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/model/util/UserKeyUtils.java @@ -11,7 +11,7 @@ import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; import org.mariotaku.twidere.util.DataStoreUtils; -import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor; +import org.mariotaku.twidere.util.UriUtils; import java.util.ArrayList; @@ -86,7 +86,7 @@ public class UserKeyUtils { def = TwidereConstants.USER_TYPE_TWITTER_COM; } if (uri == null) return def; - final String authority = PreviewMediaExtractor.getAuthority(uri); + final String authority = UriUtils.getAuthority(uri); if (authority == null) return def; return authority.replaceAll("[^\\w\\d\\.]", "-"); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/InternalTwitterContentUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/InternalTwitterContentUtils.java index d09b69d70..d53f7f115 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/InternalTwitterContentUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/InternalTwitterContentUtils.java @@ -21,7 +21,6 @@ import org.mariotaku.twidere.api.twitter.model.User; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.provider.TwidereDataStore.Filters; -import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor; import java.util.ArrayList; import java.util.List; @@ -160,7 +159,7 @@ public class InternalTwitterContentUtils { public static String getBestBannerUrl(@Nullable final String baseUrl, final int width) { if (baseUrl == null) return null; final String type = getBestBannerType(width); - final String authority = PreviewMediaExtractor.getAuthority(baseUrl); + final String authority = UriUtils.getAuthority(baseUrl); return authority != null && authority.endsWith(".twimg.com") ? baseUrl + "/" + type : baseUrl; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java index ba3aac4d8..12604aa6a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java @@ -335,7 +335,7 @@ public class TwitterAPIFactory implements TwidereConstants { } @NonNull - public static String getApiUrl(final String pattern, final String domain, String appendPath) { + public static String getApiUrl(@NonNull final String pattern, final String domain, String appendPath) { String urlBase = getApiBaseUrl(pattern, domain); if (urlBase.endsWith("/")) { urlBase = urlBase.substring(0, urlBase.length() - 1); @@ -390,14 +390,33 @@ public class TwitterAPIFactory implements TwidereConstants { } } - public static Endpoint getOAuthRestEndpoint(String apiUrlFormat, boolean sameOAuthSigningUrl, boolean noVersionSuffix) { + public static Endpoint getOAuthRestEndpoint(@NonNull String apiUrlFormat, boolean sameOAuthSigningUrl, boolean noVersionSuffix) { return getOAuthEndpoint(apiUrlFormat, "api", noVersionSuffix ? null : "1.1", sameOAuthSigningUrl); } + public static Endpoint getOAuthSignInEndpoint(@NonNull String apiUrlFormat, boolean sameOAuthSigningUrl) { + return getOAuthEndpoint(apiUrlFormat, "api", null, sameOAuthSigningUrl, true); + } + public static Endpoint getOAuthEndpoint(String apiUrlFormat, @Nullable String domain, - @Nullable String versionSuffix, boolean sameOAuthSigningUrl) { + @Nullable String versionSuffix, + boolean sameOAuthSigningUrl) { + return getOAuthEndpoint(apiUrlFormat, domain, versionSuffix, sameOAuthSigningUrl, false); + } + + public static Endpoint getOAuthEndpoint(@NonNull String apiUrlFormat, @Nullable String domain, + @Nullable String versionSuffix, + boolean sameOAuthSigningUrl, boolean fixUrl) { String endpointUrl, signEndpointUrl; endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix); + if (fixUrl) { + int[] authorityRange = UriUtils.getAuthorityRange(endpointUrl); + if (authorityRange != null && endpointUrl.regionMatches(authorityRange[0], + "api.fanfou.com", 0, authorityRange[1] - authorityRange[0])) { + endpointUrl = endpointUrl.substring(0, authorityRange[0]) + "fanfou.com" + + endpointUrl.substring(authorityRange[1]); + } + } if (!sameOAuthSigningUrl) { signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix); } else { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/UriUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/UriUtils.java index f6f43c726..61c6cb1c9 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/UriUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/UriUtils.java @@ -20,6 +20,8 @@ package org.mariotaku.twidere.util; import android.net.Uri; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; /** * Created by mariotaku on 15/3/23. @@ -39,4 +41,45 @@ public class UriUtils { public static Uri appendQueryParameters(Uri uri, String key, boolean value) { return appendQueryParameters(uri, key, ParseUtils.parseString(value)); } + + @Nullable + public static String getAuthority(@NonNull String link) { + int start = link.indexOf("://"); + if (start < 0) return null; + int end = link.indexOf('/', start + 3); + if (end < 0) { + end = link.length(); + } + return link.substring(start + 3, end); + } + + + @Nullable + public static int[] getAuthorityRange(@NonNull String link) { + int start = link.indexOf("://"); + if (start < 0) return null; + int end = link.indexOf('/', start + 3); + if (end < 0) { + end = link.length(); + } + return new int[]{start + 3, end}; + } + + @Nullable + public static String getPath(@NonNull String link) { + int start = link.indexOf("://"); + if (start < 0) return null; + start = link.indexOf('/', start + 3); + if (start < 0) { + return ""; + } + int end = link.indexOf('?', start); + if (end < 0) { + end = link.indexOf('#', start); + if (end < 0) { + end = link.length(); + } + } + return link.substring(start, end); + } } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java similarity index 74% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java rename to twidere/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java index 45320d7d3..4d9b59084 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/PreviewMediaExtractor.java @@ -71,32 +71,4 @@ public class PreviewMediaExtractor { return links; } - @Nullable - public static String getAuthority(@NonNull String link) { - int start = link.indexOf("://"); - if (start < 0) return null; - int end = link.indexOf('/', start + 3); - if (end < 0) { - end = link.length(); - } - return link.substring(start + 3, end); - } - - @Nullable - public static String getPath(@NonNull String link) { - int start = link.indexOf("://"); - if (start < 0) return null; - start = link.indexOf('/', start + 3); - if (start < 0) { - return ""; - } - int end = link.indexOf('?', start); - if (end < 0) { - end = link.indexOf('#', start); - if (end < 0) { - end = link.length(); - } - } - return link.substring(start, end); - } } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java similarity index 87% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java rename to twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java index 49372bb1d..779205666 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/InstagramProvider.java @@ -6,7 +6,7 @@ import android.support.annotation.WorkerThread; import org.mariotaku.restfu.http.RestHttpClient; import org.mariotaku.twidere.model.ParcelableMedia; -import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor; +import org.mariotaku.twidere.util.UriUtils; import java.util.Locale; @@ -16,14 +16,14 @@ import java.util.Locale; public class InstagramProvider implements Provider { @Override public boolean supports(@NonNull String link) { - final String authority = PreviewMediaExtractor.getAuthority(link); + final String authority = UriUtils.getAuthority(link); if (authority == null) return false; switch (authority) { //noinspection SpellCheckingInspection case "instagr.am": case "instagram.com": case "www.instagram.com": { - final String path = PreviewMediaExtractor.getPath(link); + final String path = UriUtils.getPath(link); return path != null && path.startsWith("/p/"); } } @@ -33,7 +33,7 @@ public class InstagramProvider implements Provider { @Override @Nullable public ParcelableMedia from(@NonNull String link) { - final String path = PreviewMediaExtractor.getPath(link); + final String path = UriUtils.getPath(link); final String prefix = "/p/"; if (path == null || !path.startsWith(prefix)) { return null; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/Provider.java b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/Provider.java similarity index 100% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/Provider.java rename to twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/Provider.java diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java similarity index 85% rename from twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java rename to twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java index eb94e9cb5..9096eeeee 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/media/preview/provider/TwitterMediaProvider.java @@ -5,7 +5,7 @@ import android.support.annotation.Nullable; import org.mariotaku.restfu.http.RestHttpClient; import org.mariotaku.twidere.model.ParcelableMedia; -import org.mariotaku.twidere.util.media.preview.PreviewMediaExtractor; +import org.mariotaku.twidere.util.UriUtils; import java.util.Locale; @@ -21,7 +21,7 @@ public class TwitterMediaProvider implements Provider { @Nullable @Override public ParcelableMedia from(@NonNull String link) { - final String path = PreviewMediaExtractor.getPath(link); + final String path = UriUtils.getPath(link); if (path == null) return null; final ParcelableMedia media = new ParcelableMedia(); media.url = link; @@ -47,11 +47,11 @@ public class TwitterMediaProvider implements Provider { } public static boolean isSupported(@NonNull String link) { - final String authority = PreviewMediaExtractor.getAuthority(link); + final String authority = UriUtils.getAuthority(link); if (authority == null || !authority.endsWith(".twimg.com")) { return false; } - final String path = PreviewMediaExtractor.getPath(link); + final String path = UriUtils.getPath(link); if (path == null) return false; if (path.startsWith("/media/")) { return true; diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/holder/ActivityTitleSummaryViewHolder.java b/twidere/src/main/java/org/mariotaku/twidere/view/holder/ActivityTitleSummaryViewHolder.java index 9145b84de..d6a9da8b3 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/holder/ActivityTitleSummaryViewHolder.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/holder/ActivityTitleSummaryViewHolder.java @@ -107,6 +107,11 @@ public class ActivityTitleSummaryViewHolder extends ViewHolder implements View.O summaryView.setText(message.getSummary()); summaryView.setVisibility(summaryView.length() > 0 ? View.VISIBLE : View.GONE); timeView.setTime(activity.timestamp); + if (adapter.shouldShowAccountsColor()) { + itemContent.drawEnd(activity.account_color); + } else { + itemContent.drawEnd(); + } displayUserProfileImages(sources); } diff --git a/twidere/src/main/res/layout/card_item_activity_summary.xml b/twidere/src/main/res/layout/card_item_activity_summary.xml index 02d508afa..d8feec285 100644 --- a/twidere/src/main/res/layout/card_item_activity_summary.xml +++ b/twidere/src/main/res/layout/card_item_activity_summary.xml @@ -2,13 +2,15 @@ + android:paddingRight="@dimen/element_spacing_normal" + app:ignorePadding="true"> \ No newline at end of file diff --git a/twidere/src/main/res/layout/card_item_activity_summary_compact.xml b/twidere/src/main/res/layout/card_item_activity_summary_compact.xml index 94ddeb823..4f1ca8380 100644 --- a/twidere/src/main/res/layout/card_item_activity_summary_compact.xml +++ b/twidere/src/main/res/layout/card_item_activity_summary_compact.xml @@ -2,11 +2,13 @@ + android:focusableInTouchMode="false" + app:ignorePadding="true"> \ No newline at end of file