diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java index 97ba70947..7a37d511f 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/TwidereConstants.java @@ -112,6 +112,7 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst String AUTHORITY_PROFILE_EDITOR = "profile_editor"; String QUERY_PARAM_ACCOUNT_KEY = "account_key"; + String QUERY_PARAM_ACCOUNT_HOST = "account_host"; String QUERY_PARAM_ACCOUNT_NAME = "account_name"; String QUERY_PARAM_STATUS_ID = "status_id"; String QUERY_PARAM_USER_KEY = "user_key"; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java index dec6b85f2..eee5c7c2c 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/IntentConstants.java @@ -93,6 +93,7 @@ public interface IntentConstants { String EXTRA_URI_ORIG = "uri_orig"; String EXTRA_MENTIONS = "mentions"; String EXTRA_ACCOUNT_KEY = "account_key"; + String EXTRA_ACCOUNT_HOST = "account_host"; String EXTRA_ACCOUNT_KEYS = "account_keys"; String EXTRA_PAGE = "page"; String EXTRA_DATA = "data"; @@ -204,9 +205,10 @@ public interface IntentConstants { String EXTRA_NEW_DOCUMENT = "new_document"; String EXTRA_MAKE_GAP = "make_gap"; String EXTRA_QUOTE_ORIGINAL_STATUS = "quote_original_status"; - String EXTRA_KEY = "key"; String EXTRA_CARD = "card"; String EXTRA_IS_POSSIBLY_SENSITIVE = "is_possibly_sensitive"; String EXTRA_REFERRAL = "referral"; String EXTRA_LOADING_MORE = "loading_more"; + String EXTRA_START_INTENT = "start_intent"; + String EXTRA_SELECT_ONLY_ITEM = "select_only_item"; } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableCredentials.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableCredentials.java index 59f931ad2..c283b0e79 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableCredentials.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableCredentials.java @@ -136,7 +136,8 @@ public class ParcelableCredentials extends ParcelableAccount implements Parcelab ParcelableCredentialsParcelablePlease.writeToParcel(this, dest, flags); } - @IntDef({AuthType.OAUTH, AuthType.XAUTH, AuthType.BASIC, AuthType.TWIP_O_MODE}) + @IntDef({AuthType.OAUTH, AuthType.XAUTH, AuthType.BASIC, AuthType.TWIP_O_MODE, + AuthType.OAUTH2}) @Retention(RetentionPolicy.SOURCE) public @interface AuthType { @@ -144,5 +145,6 @@ public class ParcelableCredentials extends ParcelableAccount implements Parcelab int XAUTH = 1; int BASIC = 2; int TWIP_O_MODE = 3; + int OAUTH2 = 4; } } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java index 35ca8567e..4fcab544d 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/UserKey.java @@ -21,13 +21,17 @@ import java.util.List; @ParcelablePlease public class UserKey implements Comparable, Parcelable { + public static final UserKey SELF_REFERENCE = new UserKey("#self#", "#self#"); + public static final Creator CREATOR = new Creator() { + @Override public UserKey createFromParcel(Parcel source) { UserKey target = new UserKey(); UserKeyParcelablePlease.readFromParcel(target, source); return target; } + @Override public UserKey[] newArray(int size) { return new UserKey[size]; } @@ -51,6 +55,10 @@ public class UserKey implements Comparable, Parcelable { } + public boolean isSelfReference() { + return equals(SELF_REFERENCE); + } + @NonNull public String getId() { return id; diff --git a/twidere/src/main/AndroidManifest.xml b/twidere/src/main/AndroidManifest.xml index 6ba028a32..4d54f74ba 100644 --- a/twidere/src/main/AndroidManifest.xml +++ b/twidere/src/main/AndroidManifest.xml @@ -388,7 +388,7 @@ android:label="@string/import_settings" android:theme="@style/Theme.Twidere.NoDisplay"/> @@ -399,6 +399,7 @@ + diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/AccountSelectorActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/AccountSelectorActivity.java index a0d3e11ad..da524e714 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/AccountSelectorActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/AccountSelectorActivity.java @@ -28,6 +28,7 @@ import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; @@ -36,6 +37,7 @@ import android.widget.ListView; import android.widget.Toast; import org.apache.commons.lang3.ArrayUtils; +import org.mariotaku.sqliteqb.library.Columns; import org.mariotaku.sqliteqb.library.Expression; import org.mariotaku.twidere.R; import org.mariotaku.twidere.adapter.AccountsAdapter; @@ -43,6 +45,9 @@ import org.mariotaku.twidere.model.ParcelableAccount; import org.mariotaku.twidere.model.ParcelableCredentials; import org.mariotaku.twidere.provider.TwidereDataStore.Accounts; +import java.util.ArrayList; +import java.util.List; + public class AccountSelectorActivity extends BaseActivity implements LoaderCallbacks, OnClickListener, OnItemClickListener { @@ -98,16 +103,28 @@ public class AccountSelectorActivity extends BaseActivity implements @Override public Loader onCreateLoader(final int id, final Bundle args) { + final List conditions = new ArrayList<>(); + final List conditionArgs = new ArrayList<>(); + if (isOAuthOnly()) { + conditions.add(Expression.equalsArgs(Accounts.AUTH_TYPE)); + conditionArgs.add(String.valueOf(ParcelableCredentials.AuthType.OAUTH)); + } + final String accountHost = getAccountHost(); + if (!TextUtils.isEmpty(accountHost)) { + conditions.add(Expression.likeRaw(new Columns.Column(Accounts.ACCOUNT_KEY), "'%@'||?")); + conditionArgs.add(accountHost); + } final String where; final String[] whereArgs; - if (isOAuthOnly()) { - where = Expression.equalsArgs(Accounts.AUTH_TYPE).getSQL(); - whereArgs = new String[]{String.valueOf(ParcelableCredentials.AuthType.OAUTH)}; - } else { + if (conditions.isEmpty()) { where = null; whereArgs = null; + } else { + where = Expression.and(conditions.toArray(new Expression[conditions.size()])).getSQL(); + whereArgs = conditionArgs.toArray(new String[conditionArgs.size()]); } - return new CursorLoader(this, Accounts.CONTENT_URI, Accounts.COLUMNS, where, whereArgs, null); + return new CursorLoader(this, Accounts.CONTENT_URI, Accounts.COLUMNS, where, whereArgs, + Accounts.SORT_POSITION); } @Override @@ -119,6 +136,9 @@ public class AccountSelectorActivity extends BaseActivity implements mListView.setItemChecked(i, ArrayUtils.contains(activatedIds, mAdapter.getItemId(i))); } } + if (mAdapter.getCount() == 1 && isSingleSelection()) { + selectSingleAccount(0); + } } @Override @@ -128,10 +148,21 @@ public class AccountSelectorActivity extends BaseActivity implements @Override public void onItemClick(final AdapterView parent, final View view, final int position, final long id) { - final Intent data = new Intent(); + selectSingleAccount(position); + } + + public void selectSingleAccount(int position) { final ParcelableAccount account = mAdapter.getAccount(position); + final Intent data = new Intent(); data.putExtra(EXTRA_ID, account.account_key.getId()); - data.putExtra(EXTRA_KEY, account.account_key); + data.putExtra(EXTRA_ACCOUNT_KEY, account.account_key); + + final Intent startIntent = getStartIntent(); + if (startIntent != null) { + startIntent.putExtra(EXTRA_ACCOUNT_KEY, account.account_key); + startActivity(startIntent); + } + setResult(RESULT_OK, data); finish(); } @@ -185,6 +216,11 @@ public class AccountSelectorActivity extends BaseActivity implements return intent.getBooleanExtra(EXTRA_OAUTH_ONLY, false); } + private String getAccountHost() { + final Intent intent = getIntent(); + return intent.getStringExtra(EXTRA_ACCOUNT_HOST); + } + private boolean isSelectNoneAllowed() { final Intent intent = getIntent(); return intent.getBooleanExtra(EXTRA_ALLOW_SELECT_NONE, false); @@ -195,4 +231,14 @@ public class AccountSelectorActivity extends BaseActivity implements return intent.getBooleanExtra(EXTRA_SINGLE_SELECTION, false); } + private boolean shouldSelectOnlyItem() { + final Intent intent = getIntent(); + return intent.getBooleanExtra(EXTRA_SELECT_ONLY_ITEM, false); + } + + private Intent getStartIntent() { + final Intent intent = getIntent(); + return intent.getParcelableExtra(EXTRA_START_INTENT); + } + } diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java index af06ad841..32af814cd 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/BaseActivity.java @@ -198,13 +198,14 @@ public class BaseActivity extends ATEActivity implements Constants, IExtendedAct final NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this); if (adapter != null && adapter.isEnabled()) { final PendingIntent intent = PendingIntent.getActivity(this, 0, new Intent(this, - TwitterLinkHandlerActivity.class), 0); + WebLinkHandlerActivity.class), 0); final IntentFilter intentFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); intentFilter.addDataScheme("http"); intentFilter.addDataScheme("https"); intentFilter.addDataAuthority("twitter.com", null); intentFilter.addDataAuthority("www.twitter.com", null); intentFilter.addDataAuthority("mobile.twitter.com", null); + intentFilter.addDataAuthority("fanfou.com", null); try { adapter.enableForegroundDispatch(this, intent, new IntentFilter[]{intentFilter}, null); } catch (SecurityException e) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/LinkHandlerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/LinkHandlerActivity.java index 002d171c0..fe902de8f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/LinkHandlerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/LinkHandlerActivity.java @@ -167,7 +167,23 @@ public class LinkHandlerActivity extends BaseActivity implements SystemWindowsIn final Uri uri = intent.getData(); final int linkId = matchLinkId(uri); intent.setExtrasClassLoader(getClassLoader()); - final Fragment fragment = createFragmentForIntent(this, linkId, intent); + final Fragment fragment; + try { + fragment = createFragmentForIntent(this, linkId, intent); + } catch (Utils.NoAccountException e) { + super.onCreate(savedInstanceState); + Intent selectIntent = new Intent(this, AccountSelectorActivity.class); + String accountHost = intent.getStringExtra(EXTRA_ACCOUNT_HOST); + if (accountHost == null) { + accountHost = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_HOST); + } + selectIntent.putExtra(EXTRA_SINGLE_SELECTION, true); + selectIntent.putExtra(EXTRA_ACCOUNT_HOST, accountHost); + selectIntent.putExtra(EXTRA_START_INTENT, intent); + startActivity(selectIntent); + finish(); + return; + } if (fragment instanceof IToolBarSupportFragment) { if (!((IToolBarSupportFragment) fragment).setupWindow(this)) { supportRequestWindowFeature(Window.FEATURE_NO_TITLE); diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/TwitterLinkHandlerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/WebLinkHandlerActivity.java similarity index 75% rename from twidere/src/main/java/org/mariotaku/twidere/activity/TwitterLinkHandlerActivity.java rename to twidere/src/main/java/org/mariotaku/twidere/activity/WebLinkHandlerActivity.java index ae5f0d6db..0ad3ea736 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/TwitterLinkHandlerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/WebLinkHandlerActivity.java @@ -14,15 +14,14 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.math.NumberUtils; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; +import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.util.BugReporter; import org.mariotaku.twidere.util.IntentUtils; import org.mariotaku.twidere.util.Utils; import java.util.List; -import static org.mariotaku.twidere.util.Utils.getDefaultAccountKey; - -public class TwitterLinkHandlerActivity extends Activity implements Constants { +public class WebLinkHandlerActivity extends Activity implements Constants { @SuppressWarnings("SpellCheckingInspection") public static final String[] TWITTER_RESERVED_PATHS = {"about", "account", "accounts", "activity", "all", @@ -37,6 +36,11 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { "statistics", "terms", "tos", "translate", "trends", "tweetbutton", "twttr", "update_discoverability", "users", "welcome", "who_to_follow", "widgets", "zendesk_auth", "media_signup"}; + @SuppressWarnings("SpellCheckingInspection") + public static final String[] FANFOU_RESERVED_PATHS = {"home", "privatemsg", "finder", "browse", + "search", "settings", "message", "mentions", "favorites", "friends", "followers", + "sharer", "photo", "album", "paipai", "q", "userview", "dialogue"}; + private static final String AUTHORITY_TWITTER_COM = "twitter.com"; @@ -58,13 +62,28 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { super.onCreate(savedInstanceState); final PackageManager packageManager = getPackageManager(); final Intent intent = getIntent(); - final Uri data = intent.getData(); - if (data == null) { + final Uri uri = intent.getData(); + if (uri == null || uri.getHost() == null) { finish(); return; } - final Uri uri = regulateTwitterUri(data); - final Pair handled = getHandledIntent(uri); + final Pair handled; + switch (uri.getHost()) { + case "twitter.com": + case "www.twitter.com": + case "mobile.twitter.com": { + handled = handleTwitterLink(regulateTwitterUri(uri)); + break; + } + case "fanfou.com": { + handled = handleFanfouLink(uri); + break; + } + default: { + handled = Pair.create(null, false); + break; + } + } if (handled.first != null) { startActivity(handled.first); } else { @@ -95,7 +114,39 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { } @NonNull - private Pair getHandledIntent(final Uri uri) { + private Pair handleFanfouLink(final Uri uri) { + final List pathSegments = uri.getPathSegments(); + if (pathSegments.size() > 0) { + switch (pathSegments.get(0)) { + case "statuses": { + final Uri.Builder builder = new Uri.Builder(); + builder.scheme(SCHEME_TWIDERE); + builder.authority(AUTHORITY_STATUS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, USER_TYPE_FANFOU_COM); + builder.appendQueryParameter(QUERY_PARAM_STATUS_ID, pathSegments.get(1)); + return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); + } + default: { + if (!ArrayUtils.contains(FANFOU_RESERVED_PATHS, pathSegments.get(0))) { + if (pathSegments.size() == 1) { + final Uri.Builder builder = new Uri.Builder(); + builder.scheme(SCHEME_TWIDERE); + builder.authority(AUTHORITY_USER); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, USER_TYPE_FANFOU_COM); + final UserKey userKey = new UserKey(pathSegments.get(0), USER_TYPE_FANFOU_COM); + builder.appendQueryParameter(QUERY_PARAM_USER_KEY, userKey.toString()); + return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); + } + } + return Pair.create(null, false); + } + } + } + return Pair.create(null, false); + } + + @NonNull + private Pair handleTwitterLink(final Uri uri) { final List pathSegments = uri.getPathSegments(); if (pathSegments.size() > 0) { switch (pathSegments.get(0)) { @@ -103,7 +154,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { return getIUriIntent(uri, pathSegments); } case "intent": { - return getIntentUriIntent(uri, pathSegments); + return getTwitterIntentUriIntent(uri, pathSegments); } case "share": { final Intent handledIntent = new Intent(this, ComposeActivity.class); @@ -117,6 +168,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_SEARCH); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_QUERY, uri.getQueryParameter("q")); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } @@ -124,21 +176,21 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FRIENDS); - builder.appendQueryParameter(QUERY_PARAM_USER_KEY, String.valueOf(getDefaultAccountKey(this))); + builder.appendQueryParameter(QUERY_PARAM_USER_KEY, UserKey.SELF_REFERENCE.toString()); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } case "followers": { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FOLLOWERS); - builder.appendQueryParameter(QUERY_PARAM_USER_KEY, String.valueOf(getDefaultAccountKey(this))); + builder.appendQueryParameter(QUERY_PARAM_USER_KEY, UserKey.SELF_REFERENCE.toString()); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } case "favorites": { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FAVORITES); - builder.appendQueryParameter(QUERY_PARAM_USER_KEY, String.valueOf(getDefaultAccountKey(this))); + builder.appendQueryParameter(QUERY_PARAM_USER_KEY, UserKey.SELF_REFERENCE.toString()); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } default: { @@ -167,6 +219,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FRIENDS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } @@ -174,6 +227,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FOLLOWERS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } @@ -181,6 +235,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_FAVORITES); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } @@ -188,6 +243,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_LIST); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); builder.appendQueryParameter(QUERY_PARAM_LIST_NAME, pathSegments.get(1)); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); @@ -199,6 +255,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_STATUS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_STATUS_ID, pathSegments.get(2)); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); } else { @@ -207,6 +264,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_LIST_MEMBERS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); builder.appendQueryParameter(QUERY_PARAM_LIST_NAME, pathSegments.get(1)); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); @@ -215,6 +273,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { final Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_TWIDERE); builder.authority(AUTHORITY_USER_LIST_SUBSCRIBERS); + builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_HOST, "twitter.com"); builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName); builder.appendQueryParameter(QUERY_PARAM_LIST_NAME, pathSegments.get(1)); return Pair.create(new Intent(Intent.ACTION_VIEW, builder.build()), true); @@ -225,7 +284,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants { return Pair.create(null, false); } - private Pair getIntentUriIntent(Uri uri, List pathSegments) { + private Pair getTwitterIntentUriIntent(Uri uri, List pathSegments) { if (pathSegments.size() < 2) return Pair.create(null, false); switch (pathSegments.get(1)) { case "tweet": { diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java index af09e2304..b1fbb1fd0 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/StatusFragment.java @@ -342,7 +342,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac if (status == null) return; if (resultCode == Activity.RESULT_OK) { if (data == null || !data.hasExtra(EXTRA_ID)) return; - final UserKey accountKey = data.getParcelableExtra(EXTRA_KEY); + final UserKey accountKey = data.getParcelableExtra(EXTRA_ACCOUNT_KEY); IntentUtils.openStatus(activity, accountKey, status.id); } break; diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java index 8bc3f42cc..e90448e24 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java @@ -709,7 +709,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener if (user == null) return; if (resultCode == Activity.RESULT_OK) { if (data == null || !data.hasExtra(EXTRA_ID)) return; - final UserKey accountKey = data.getParcelableExtra(EXTRA_KEY); + final UserKey accountKey = data.getParcelableExtra(EXTRA_ACCOUNT_KEY); @Referral final String referral = getArguments().getString(EXTRA_REFERRAL); IntentUtils.openUserProfile(getActivity(), accountKey, user.key, @@ -1039,6 +1039,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener final Intent intent = new Intent(INTENT_ACTION_SELECT_ACCOUNT); intent.setClass(getActivity(), AccountSelectorActivity.class); intent.putExtra(EXTRA_SINGLE_SELECTION, true); + intent.putExtra(EXTRA_ACCOUNT_HOST, user.key.getHost()); startActivityForResult(intent, REQUEST_SELECT_ACCOUNT); break; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java index 4d33beaa1..0e08d8ed8 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserListFragment.java @@ -127,7 +127,7 @@ public class UserListFragment extends AbsToolbarTabPagesFragment implements OnCl if (resultCode == Activity.RESULT_OK) { if (data == null || !data.hasExtra(EXTRA_ID)) return; final ParcelableUserList userList = mUserList; - final UserKey accountKey = data.getParcelableExtra(EXTRA_KEY); + final UserKey accountKey = data.getParcelableExtra(EXTRA_ACCOUNT_KEY); IntentUtils.openUserListDetails(getActivity(), accountKey, userList.id, userList.user_key, userList.user_screen_name, userList.name); } diff --git a/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableStatusLoader.java b/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableStatusLoader.java index e1ad262c7..3b7be4c13 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableStatusLoader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableStatusLoader.java @@ -21,6 +21,7 @@ package org.mariotaku.twidere.loader; import android.content.Context; import android.os.Bundle; +import android.support.annotation.Nullable; import android.support.v4.content.AsyncTaskLoader; import org.mariotaku.twidere.api.twitter.TwitterException; @@ -48,14 +49,17 @@ public class ParcelableStatusLoader extends AsyncTaskLoader loadInBackground() { + if (mAccountId == null || mStatusId == null) return SingleResponse.getInstance(); if (!mOmitIntentExtra && mExtras != null) { final ParcelableStatus cache = mExtras.getParcelable(IntentConstants.EXTRA_STATUS); if (cache != null) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/DataStoreUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/DataStoreUtils.java index d6e9d3f3b..9bf5f54ea 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/DataStoreUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/DataStoreUtils.java @@ -914,14 +914,14 @@ public class DataStoreUtils implements Constants { if (host != null) { for (final Uri uri : STATUSES_URIS) { final String deleteWhere = Expression.and( - Expression.likeRaw(new Column(Statuses.ACCOUNT_KEY), "%@?"), + Expression.likeRaw(new Column(Statuses.ACCOUNT_KEY), "'%@'||?"), Expression.or( Expression.equalsArgs(Statuses.STATUS_ID), Expression.equalsArgs(Statuses.RETWEET_ID) )).getSQL(); cr.delete(uri, deleteWhere, new String[]{host, statusId, statusId}); final String updateWhere = Expression.and( - Expression.likeRaw(new Column(Statuses.ACCOUNT_KEY), "%@?"), + Expression.likeRaw(new Column(Statuses.ACCOUNT_KEY), "'%@'||?"), Expression.equalsArgs(Statuses.MY_RETWEET_ID) ).getSQL(); if (status != null) { diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java b/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java index ba1c6d18d..38c2bfb6b 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/MenuUtils.java @@ -47,7 +47,6 @@ import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.AccountSelectorActivity; import org.mariotaku.twidere.activity.ColorPickerDialogActivity; -import org.mariotaku.twidere.constant.IntentConstants; import org.mariotaku.twidere.constant.SharedPreferenceConstants; import org.mariotaku.twidere.fragment.AbsStatusesFragment; import org.mariotaku.twidere.fragment.AddStatusFilterDialogFragment; @@ -219,8 +218,8 @@ public class MenuUtils implements Constants { setMenuItemAvailability(menu, R.id.translate, isOfficialKey); } menu.removeGroup(Constants.MENU_GROUP_STATUS_EXTENSION); - Utils.addIntentToMenuForExtension(context, menu, Constants.MENU_GROUP_STATUS_EXTENSION, IntentConstants.INTENT_ACTION_EXTENSION_OPEN_STATUS, - IntentConstants.EXTRA_STATUS, IntentConstants.EXTRA_STATUS_JSON, status); + Utils.addIntentToMenuForExtension(context, menu, Constants.MENU_GROUP_STATUS_EXTENSION, INTENT_ACTION_EXTENSION_OPEN_STATUS, + EXTRA_STATUS, EXTRA_STATUS_JSON, status); final MenuItem shareItem = menu.findItem(R.id.share); final ActionProvider shareProvider = MenuItemCompat.getActionProvider(shareItem); if (shareProvider instanceof SupportStatusShareProvider) { @@ -267,14 +266,14 @@ public class MenuUtils implements Constants { break; } case R.id.quote: { - final Intent intent = new Intent(IntentConstants.INTENT_ACTION_QUOTE); - intent.putExtra(IntentConstants.EXTRA_STATUS, status); + final Intent intent = new Intent(INTENT_ACTION_QUOTE); + intent.putExtra(EXTRA_STATUS, status); context.startActivity(intent); break; } case R.id.reply: { - final Intent intent = new Intent(IntentConstants.INTENT_ACTION_REPLY); - intent.putExtra(IntentConstants.EXTRA_STATUS, status); + final Intent intent = new Intent(INTENT_ACTION_REPLY); + intent.putExtra(EXTRA_STATUS, status); context.startActivity(intent); break; } @@ -304,10 +303,10 @@ public class MenuUtils implements Constants { final Intent intent = new Intent(context, ColorPickerDialogActivity.class); final int color = colorNameManager.getUserColor(status.user_key); if (color != 0) { - intent.putExtra(IntentConstants.EXTRA_COLOR, color); + intent.putExtra(EXTRA_COLOR, color); } - intent.putExtra(IntentConstants.EXTRA_CLEAR_BUTTON, color != 0); - intent.putExtra(IntentConstants.EXTRA_ALPHA_SLIDER, false); + intent.putExtra(EXTRA_CLEAR_BUTTON, color != 0); + intent.putExtra(EXTRA_ALPHA_SLIDER, false); if (fragment != null) { fragment.startActivityForResult(intent, REQUEST_SET_COLOR); } else if (context instanceof Activity) { @@ -329,9 +328,10 @@ public class MenuUtils implements Constants { break; } case R.id.open_with_account: { - final Intent intent = new Intent(IntentConstants.INTENT_ACTION_SELECT_ACCOUNT); + final Intent intent = new Intent(INTENT_ACTION_SELECT_ACCOUNT); intent.setClass(context, AccountSelectorActivity.class); - intent.putExtra(IntentConstants.EXTRA_SINGLE_SELECTION, true); + intent.putExtra(EXTRA_SINGLE_SELECTION, true); + intent.putExtra(EXTRA_ACCOUNT_HOST, status.user_key.getHost()); if (fragment != null) { fragment.startActivityForResult(intent, REQUEST_SELECT_ACCOUNT); } else if (context instanceof Activity) { 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 2590ba0a3..3f3c2bff2 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/TwitterAPIFactory.java @@ -37,6 +37,7 @@ import org.mariotaku.twidere.api.twitter.Twitter; import org.mariotaku.twidere.api.twitter.TwitterCaps; import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.TwitterOAuth; +import org.mariotaku.twidere.api.twitter.TwitterOAuth2; import org.mariotaku.twidere.api.twitter.TwitterUpload; import org.mariotaku.twidere.api.twitter.TwitterUserStream; import org.mariotaku.twidere.api.twitter.auth.BasicAuthorization; @@ -264,7 +265,10 @@ public class TwitterAPIFactory implements TwidereConstants { versionSuffix = noVersionSuffix ? null : "/1.1/"; } else if (TwitterOAuth.class.isAssignableFrom(cls)) { domain = "api"; - versionSuffix = "/oauth"; + versionSuffix = null; + } else if (TwitterOAuth2.class.isAssignableFrom(cls)) { + domain = "api"; + versionSuffix = null; } else if (TwitterUserStream.class.isAssignableFrom(cls)) { domain = "userstream"; versionSuffix = noVersionSuffix ? null : "/1.1/"; 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 374beda44..2c5a5cebc 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -63,6 +63,7 @@ import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.StringRes; +import android.support.annotation.WorkerThread; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; @@ -443,12 +444,7 @@ public final class Utils implements Constants { return colors; } - public static Fragment createFragmentForIntent(final Context context, final Intent intent) { - final Uri uri = intent.getData(); - return createFragmentForIntent(context, matchLinkId(uri), intent); - } - - public static Fragment createFragmentForIntent(final Context context, final int linkId, final Intent intent) { + public static Fragment createFragmentForIntent(final Context context, final int linkId, final Intent intent) throws NoAccountException { intent.setExtrasClassLoader(context.getClassLoader()); final Bundle extras = intent.getExtras(); final Uri uri = intent.getData(); @@ -461,14 +457,17 @@ public final class Utils implements Constants { boolean isAccountIdRequired = true; switch (linkId) { case LINK_ID_ACCOUNTS: { + isAccountIdRequired = false; fragment = new AccountsManagerFragment(); break; } case LINK_ID_DRAFTS: { + isAccountIdRequired = false; fragment = new DraftsFragment(); break; } case LINK_ID_FILTERS: { + isAccountIdRequired = false; fragment = new FiltersFragment(); break; } @@ -477,6 +476,7 @@ public final class Utils implements Constants { break; } case LINK_ID_MAP: { + isAccountIdRequired = false; if (!args.containsKey(EXTRA_LATITUDE) && !args.containsKey(EXTRA_LONGITUDE)) { final double lat = NumberUtils.toDouble(uri.getQueryParameter(QUERY_PARAM_LAT), Double.NaN); final double lng = NumberUtils.toDouble(uri.getQueryParameter(QUERY_PARAM_LNG), Double.NaN); @@ -775,7 +775,10 @@ public final class Utils implements Constants { return null; } } - UserKey accountKey = UserKey.valueOf(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY)); + UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY); + if (accountKey == null) { + accountKey = UserKey.valueOf(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY)); + } if (accountKey == null) { final String accountId = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID); final String paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME); @@ -784,19 +787,21 @@ public final class Utils implements Constants { args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey); } else if (paramAccountName != null) { accountKey = DataStoreUtils.findAccountKeyByScreenName(context, paramAccountName); - } else { - accountKey = getDefaultAccountKey(context); } } if (isAccountIdRequired && accountKey == null) { - return null; + throw new NoAccountException(); } args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey); fragment.setArguments(args); return fragment; } + public static class NoAccountException extends Exception { + + } + public static String getUserKeyParam(Uri uri) { final String paramUserKey = uri.getQueryParameter(QUERY_PARAM_USER_KEY); if (paramUserKey == null) { @@ -915,10 +920,11 @@ public final class Utils implements Constants { } @NonNull - public static ParcelableStatus findStatus(final Context context, final UserKey accountKey, - final String statusId) + @WorkerThread + public static ParcelableStatus findStatus(@NonNull final Context context, + @NonNull final UserKey accountKey, + @NonNull final String statusId) throws TwitterException { - if (context == null) throw new NullPointerException(); final ParcelableStatus cached = findStatusInDatabases(context, accountKey, statusId); if (cached != null) return cached; final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, accountKey, true); @@ -934,9 +940,10 @@ public final class Utils implements Constants { } @Nullable - public static ParcelableStatus findStatusInDatabases(final Context context, final UserKey accountKey, - final String statusId) { - if (context == null) return null; + @WorkerThread + public static ParcelableStatus findStatusInDatabases(@NonNull final Context context, + @NonNull final UserKey accountKey, + @NonNull final String statusId) { final ContentResolver resolver = context.getContentResolver(); ParcelableStatus status = null; final String where = Expression.and(Expression.equalsArgs(Statuses.ACCOUNT_KEY), diff --git a/twidere/src/main/res/layout/list_item_account.xml b/twidere/src/main/res/layout/list_item_account.xml index d705e1317..b04a939b4 100644 --- a/twidere/src/main/res/layout/list_item_account.xml +++ b/twidere/src/main/res/layout/list_item_account.xml @@ -23,12 +23,7 @@ android:clipChildren="false" android:descendantFocusability="blocksDescendants" android:minHeight="?android:attr/listPreferredItemHeight" - android:paddingBottom="@dimen/element_spacing_normal" - android:paddingEnd="@dimen/element_spacing_normal" - android:paddingLeft="0dp" - android:paddingRight="@dimen/element_spacing_normal" - android:paddingStart="0dp" - android:paddingTop="@dimen/element_spacing_normal" + android:padding="@dimen/element_spacing_normal" app:ignorePadding="true"> + android:textColor="?android:textColorPrimary" + tools:text="Name"/> + android:textColor="?android:textColorSecondary" + tools:text="\@screenname"/>