diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/statusnet/StatusNet.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/statusnet/StatusNet.java index 68b729ba6..9ddd21e72 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/statusnet/StatusNet.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/statusnet/StatusNet.java @@ -1,12 +1,20 @@ package org.mariotaku.twidere.api.statusnet; +import org.mariotaku.restfu.annotation.method.GET; +import org.mariotaku.restfu.annotation.param.Query; import org.mariotaku.twidere.api.statusnet.api.GroupResources; import org.mariotaku.twidere.api.statusnet.api.SearchResources; import org.mariotaku.twidere.api.statusnet.api.StatusNetResources; import org.mariotaku.twidere.api.statusnet.api.UserResources; +import org.mariotaku.twidere.api.twitter.TwitterException; +import org.mariotaku.twidere.api.twitter.model.User; /** * Created by mariotaku on 16/3/4. */ public interface StatusNet extends StatusNetResources, GroupResources, SearchResources, UserResources { + + @GET("/externalprofile/show.json") + User showExternalProfile(@Query("profileurl") String profileUrl) throws TwitterException; + } diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/User.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/User.java index b800ed762..dd828d36f 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/User.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/api/twitter/model/User.java @@ -215,13 +215,25 @@ public class User extends TwitterResponseObject implements Comparable { @JsonField(name = "statusnet_profile_url") String statusnetProfileUrl; + @JsonField(name = "ostatus_uri") String ostatusUri; + @JsonField(name = "profile_image_url_original") String profileImageUrlOriginal; + @JsonField(name = "profile_image_url_profile_size") String profileImageUrlProfileSize; + @JsonField(name = "follows_you") + boolean followsYou; + + @JsonField(name = "blocks_you") + boolean blocksYou; + + @JsonField(name = "statusnet_blocking") + boolean statusnetBlocking; + public boolean canMediaTag() { return canMediaTag; } @@ -500,10 +512,23 @@ public class User extends TwitterResponseObject implements Comparable { return uniqueId; } + public boolean isStatusnetBlocking() { + return statusnetBlocking; + } + + public boolean isBlocksYou() { + return blocksYou; + } + + public boolean isFollowsYou() { + return followsYou; + } + @Override public String toString() { return "User{" + - "id=" + id + + "id='" + id + '\'' + + ", uniqueId='" + uniqueId + '\'' + ", name='" + name + '\'' + ", screenName='" + screenName + '\'' + ", location='" + location + '\'' + @@ -515,6 +540,7 @@ public class User extends TwitterResponseObject implements Comparable { ", followersCount=" + followersCount + ", friendsCount=" + friendsCount + ", listedCount=" + listedCount + + ", groupsCount=" + groupsCount + ", createdAt=" + createdAt + ", favouritesCount=" + favouritesCount + ", utcOffset=" + utcOffset + @@ -523,6 +549,7 @@ public class User extends TwitterResponseObject implements Comparable { ", isVerified=" + isVerified + ", statusesCount=" + statusesCount + ", mediaCount=" + mediaCount + + ", photoCount=" + photoCount + ", lang='" + lang + '\'' + ", status=" + status + ", contributorsEnabled=" + contributorsEnabled + @@ -535,6 +562,7 @@ public class User extends TwitterResponseObject implements Comparable { ", profileBackgroundTile=" + profileBackgroundTile + ", profileImageUrl='" + profileImageUrl + '\'' + ", profileImageUrlHttps='" + profileImageUrlHttps + '\'' + + ", profileImageUrlLarge='" + profileImageUrlLarge + '\'' + ", profileBannerUrl='" + profileBannerUrl + '\'' + ", coverPhoto='" + coverPhoto + '\'' + ", profileLinkColor='" + profileLinkColor + '\'' + @@ -557,6 +585,9 @@ public class User extends TwitterResponseObject implements Comparable { ", ostatusUri='" + ostatusUri + '\'' + ", profileImageUrlOriginal='" + profileImageUrlOriginal + '\'' + ", profileImageUrlProfileSize='" + profileImageUrlProfileSize + '\'' + + ", followsYou=" + followsYou + + ", blocksYou=" + blocksYou + + ", statusnetBlocking=" + statusnetBlocking + "} " + super.toString(); } 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 1d3c14f7a..80336bc05 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 @@ -169,6 +169,7 @@ public interface IntentConstants { String EXTRA_PERMISSIONS = "permissions"; String EXTRA_LOCATION = "location"; String EXTRA_URL = "url"; + String EXTRA_PROFILE_URL = "profile_url"; String EXTRA_NEXT_PAGE = "next_page"; String EXTRA_NEXT_CURSOR = "next_cursor"; String EXTRA_PREV_CURSOR = "prev_cursor"; diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableStatus.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableStatus.java index f60ffaf0f..b779eab47 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableStatus.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/ParcelableStatus.java @@ -508,6 +508,9 @@ public class ParcelableStatus implements Parcelable, Comparable { @Override public String toString() { return "ParcelableUser{" + - "account_id=" + account_key + + "account_key=" + account_key + ", account_color=" + account_color + - ", id=" + key + + ", key=" + key + ", created_at=" + created_at + ", position=" + position + ", is_protected=" + is_protected + @@ -267,6 +267,7 @@ public class ParcelableUser implements Parcelable, Comparable { ", location='" + location + '\'' + ", profile_image_url='" + profile_image_url + '\'' + ", profile_banner_url='" + profile_banner_url + '\'' + + ", profile_background_url='" + profile_background_url + '\'' + ", url='" + url + '\'' + ", url_expanded='" + url_expanded + '\'' + ", description_html='" + description_html + '\'' + @@ -284,6 +285,8 @@ public class ParcelableUser implements Parcelable, Comparable { ", is_cache=" + is_cache + ", is_basic=" + is_basic + ", extras=" + extras + + ", color=" + color + + ", nickname='" + nickname + '\'' + '}'; } @@ -319,6 +322,15 @@ public class ParcelableUser implements Parcelable, Comparable { @JsonField(name = "unique_id") @ParcelableThisPlease public String unique_id; + @JsonField(name = "statusnet_blocking") + @ParcelableThisPlease + public boolean statusnet_blocking; + @JsonField(name = "statusnet_blocked_by") + @ParcelableThisPlease + public boolean statusnet_blocked_by; + @JsonField(name = "statusnet_followed_by") + @ParcelableThisPlease + public boolean statusnet_followed_by; @Override @@ -331,6 +343,21 @@ public class ParcelableUser implements Parcelable, Comparable { ParcelableUser$ExtrasParcelablePlease.writeToParcel(this, dest, flags); } + @Override + public String toString() { + return "Extras{" + + "statusnet_profile_url='" + statusnet_profile_url + '\'' + + ", ostatus_uri='" + ostatus_uri + '\'' + + ", profile_image_url_original='" + profile_image_url_original + '\'' + + ", profile_image_url_profile_size='" + profile_image_url_profile_size + '\'' + + ", groups_count=" + groups_count + + ", unique_id='" + unique_id + '\'' + + ", statusnet_blocking=" + statusnet_blocking + + ", statusnet_blocked_by=" + statusnet_blocked_by + + ", statusnet_followed_by=" + statusnet_followed_by + + '}'; + } + public static final Creator CREATOR = new Creator() { public Extras createFromParcel(Parcel source) { Extras target = new Extras(); diff --git a/twidere/build.gradle b/twidere/build.gradle index 1d9efb542..73e98a7a2 100644 --- a/twidere/build.gradle +++ b/twidere/build.gradle @@ -21,8 +21,8 @@ android { applicationId "org.mariotaku.twidere" minSdkVersion 14 targetSdkVersion 23 - versionCode 178 - versionName "3.1.1.6" + versionCode 179 + versionName "3.1.1.7" multiDexEnabled true generatedDensities = [] diff --git a/twidere/proguard-rules.pro b/twidere/proguard-rules.pro index 69eeeaa49..c36ff99fd 100644 --- a/twidere/proguard-rules.pro +++ b/twidere/proguard-rules.pro @@ -46,4 +46,11 @@ -keepclassmembers class org.mariotaku.twidere.activity.BrowserSignInActivity.InjectorJavaScriptInterface { public *; -} \ No newline at end of file +} + +# Fuck shitsung +-keep class !android.support.v7.view.menu.*MenuBuilder*, android.support.v7.** { *; } +-keep interface android.support.v7.* { *; } + +# Fuck xiaomi +-keep class !org.apache.commons.lang3.** { *; } \ No newline at end of file diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/HomeActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/HomeActivity.java index 0e74e4c1f..b7b09d5de 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/HomeActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/HomeActivity.java @@ -73,6 +73,7 @@ import org.mariotaku.twidere.annotation.ReadPositionTag; import org.mariotaku.twidere.fragment.AccountsDashboardFragment; import org.mariotaku.twidere.fragment.CustomTabsFragment; import org.mariotaku.twidere.fragment.DirectMessagesFragment; +import org.mariotaku.twidere.fragment.MessagesEntriesFragment; import org.mariotaku.twidere.fragment.TrendsSuggestionsFragment; import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface; import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback; @@ -886,6 +887,8 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag final SupportTabSpec tab = mPagerAdapter.getTab(position); if (DirectMessagesFragment.class == tab.cls) { IntentUtils.openMessageConversation(this, null, null); + } else if (MessagesEntriesFragment.class == tab.cls) { + IntentUtils.openMessageConversation(this, null, null); } else if (TrendsSuggestionsFragment.class == tab.cls) { openSearchView(null); } else { @@ -902,6 +905,9 @@ public class HomeActivity extends BaseActivity implements OnClickListener, OnPag if (DirectMessagesFragment.class == tab.cls) { icon = R.drawable.ic_action_add; title = R.string.new_direct_message; + } else if (MessagesEntriesFragment.class == tab.cls) { + icon = R.drawable.ic_action_add; + title = R.string.new_direct_message; } else if (TrendsSuggestionsFragment.class == tab.cls) { icon = R.drawable.ic_action_search; title = android.R.string.search_go; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java index 735bbf576..ec54971a6 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/MediaViewerActivity.java @@ -382,6 +382,10 @@ public final class MediaViewerActivity extends AbsMediaViewerActivity implements shareMedia(CacheProvider.Type.VIDEO); } else if (object instanceof ImagePageFragment) { shareMedia(CacheProvider.Type.IMAGE); + } else if (object instanceof GifPageFragment) { + shareMedia(CacheProvider.Type.IMAGE); + } else { + throw new UnsupportedOperationException("Unsupported fragment " + object); } } else { final ParcelableMedia media = getMedia()[currentItem]; diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsWizardActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsWizardActivity.java index 668ec32e6..f379f47c5 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsWizardActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/SettingsWizardActivity.java @@ -55,6 +55,7 @@ import org.mariotaku.twidere.fragment.BaseSupportFragment; import org.mariotaku.twidere.fragment.DirectMessagesFragment; import org.mariotaku.twidere.fragment.HomeTimelineFragment; import org.mariotaku.twidere.fragment.InteractionsTimelineFragment; +import org.mariotaku.twidere.fragment.MessagesEntriesFragment; import org.mariotaku.twidere.fragment.SupportProgressDialogFragment; import org.mariotaku.twidere.model.CustomTabConfiguration; import org.mariotaku.twidere.model.SupportTabSpec; @@ -647,7 +648,8 @@ public class SettingsWizardActivity extends BaseActivity implements Constants { for (final SupportTabSpec spec : tabs) { if (spec.cls == HomeTimelineFragment.class || spec.cls == InteractionsTimelineFragment.class - || spec.cls == DirectMessagesFragment.class) return true; + || spec.cls == DirectMessagesFragment.class + || spec.cls == MessagesEntriesFragment.class) return true; } return false; } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java index 1132830fb..a29478a0f 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/AbsStatusesFragment.java @@ -418,11 +418,12 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag @Override public void onUserProfileClick(IStatusViewHolder holder, int position) { - final FragmentActivity activity = getActivity(); final ParcelableStatus status = getAdapter().getStatus(position); - IntentUtils.openUserProfile(activity, status.account_key, status.user_key, - status.user_screen_name, null, mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), - UserFragment.Referral.TIMELINE_STATUS); + final Intent intent = IntentUtils.userProfile(status.account_key, status.user_key, + status.user_screen_name, UserFragment.Referral.TIMELINE_STATUS, + status.extras.user_statusnet_profile_url); + IntentUtils.applyNewDocument(intent, mPreferences.getBoolean(KEY_NEW_DOCUMENT_API)); + startActivity(intent); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesEntriesFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesEntriesFragment.java new file mode 100644 index 000000000..0e1c1852c --- /dev/null +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/MessagesEntriesFragment.java @@ -0,0 +1,9 @@ +package org.mariotaku.twidere.fragment; + +import android.support.v4.app.Fragment; + +/** + * Created by mariotaku on 16/3/28. + */ +public class MessagesEntriesFragment extends Fragment { +} diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java index d4a413ba0..6a1871ace 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/ParcelableUsersFragment.java @@ -20,8 +20,6 @@ package org.mariotaku.twidere.fragment; import android.content.Context; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -43,12 +41,10 @@ import org.mariotaku.twidere.loader.iface.IExtendedLoader; import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.model.UserKey; import org.mariotaku.twidere.model.message.FriendshipTaskEvent; -import org.mariotaku.twidere.model.util.UserKeyUtils; import org.mariotaku.twidere.util.AsyncTwitterWrapper; import org.mariotaku.twidere.util.IntentUtils; import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback; -import org.mariotaku.twidere.util.LinkCreator; import org.mariotaku.twidere.util.ParcelUtils; import org.mariotaku.twidere.util.RecyclerViewNavigationHelper; import org.mariotaku.twidere.view.holder.UserViewHolder; @@ -166,18 +162,8 @@ public abstract class ParcelableUsersFragment extends AbsContentListRecyclerView public void onUserClick(UserViewHolder holder, int position) { final ParcelableUser user = getAdapter().getUser(position); final FragmentActivity activity = getActivity(); - if (UserKeyUtils.isSameHost(user.account_key, user.key)) { - IntentUtils.openUserProfile(activity, user, null, - mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), getUserReferral()); - } else if (user.extras != null && user.extras.statusnet_profile_url != null) { - final Uri uri = Uri.parse(user.extras.statusnet_profile_url); - final Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } else { - final Uri uri = LinkCreator.getTwitterUserLink(user.screen_name); - final Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - } + IntentUtils.openUserProfile(activity, user, null, mPreferences.getBoolean(KEY_NEW_DOCUMENT_API), + getUserReferral()); } @Override 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 12975b332..6c6d635a4 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserFragment.java @@ -110,6 +110,7 @@ import org.mariotaku.twidere.loader.ParcelableUserLoader; import org.mariotaku.twidere.model.CachedRelationship; import org.mariotaku.twidere.model.CachedRelationshipValuesCreator; import org.mariotaku.twidere.model.ConsumerKeyType; +import org.mariotaku.twidere.model.ParcelableCredentials; import org.mariotaku.twidere.model.ParcelableMedia; import org.mariotaku.twidere.model.ParcelableUser; import org.mariotaku.twidere.model.ParcelableUserList; @@ -124,6 +125,7 @@ import org.mariotaku.twidere.model.message.TaskStateChangedEvent; import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils; import org.mariotaku.twidere.model.util.ParcelableMediaUtils; import org.mariotaku.twidere.model.util.ParcelableUserUtils; +import org.mariotaku.twidere.model.util.UserKeyUtils; import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships; import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers; import org.mariotaku.twidere.provider.TwidereDataStore.Filters; @@ -243,8 +245,8 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mFollowProgress.setVisibility(View.VISIBLE); mFollowingYouIndicator.setVisibility(View.GONE); final UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY); - final String userId = args.getString(EXTRA_USER_ID); - return new UserRelationshipLoader(getActivity(), accountKey, userId); + final ParcelableUser user = args.getParcelable(EXTRA_USER); + return new UserRelationshipLoader(getActivity(), accountKey, user); } @Override @@ -268,7 +270,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener public Loader> onCreateLoader(final int id, final Bundle args) { final boolean omitIntentExtra = args.getBoolean(EXTRA_OMIT_INTENT_EXTRA, true); final UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY); - final String userId = args.getString(EXTRA_USER_ID); + final UserKey userId = args.getParcelable(EXTRA_USER_KEY); final String screenName = args.getString(EXTRA_SCREEN_NAME); if (mUser == null && (!omitIntentExtra || !args.containsKey(EXTRA_USER))) { mCardContent.setVisibility(View.GONE); @@ -278,7 +280,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mHeaderErrorTextView.setVisibility(View.GONE); } final ParcelableUser user = mUser; - final boolean loadFromCache = user == null || !user.is_cache && user.key.check(userId, null); + final boolean loadFromCache = user == null || !user.is_cache && user.key.maybeEquals(userId); return new ParcelableUserLoader(getActivity(), accountKey, userId, screenName, getArguments(), omitIntentExtra, loadFromCache); } @@ -303,6 +305,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener final Bundle args = new Bundle(); args.putParcelable(EXTRA_ACCOUNT_KEY, user.account_key); args.putString(EXTRA_USER_ID, user.key.getId()); + args.putParcelable(EXTRA_USER_KEY, user.key); args.putString(EXTRA_SCREEN_NAME, user.screen_name); args.putBoolean(EXTRA_OMIT_INTENT_EXTRA, true); getLoaderManager().restartLoader(LOADER_ID_USER, args, this); @@ -348,14 +351,12 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mRelationship = userRelationship; } invalidateOptionsMenu(); - final Relationship relationship = userRelationship.relationship; - mFollowButton.setEnabled(relationship.isSourceBlockingTarget() || - !relationship.isSourceBlockedByTarget()); - if (relationship.isSourceBlockedByTarget()) { + mFollowButton.setEnabled(userRelationship.blocking || !userRelationship.blocked_by); + if (userRelationship.blocked_by) { mPagesErrorContainer.setVisibility(View.GONE); mPagesErrorText.setText(null); mPagesContent.setVisibility(View.VISIBLE); - } else if (!relationship.isSourceFollowingTarget() && user.is_protected) { + } else if (!userRelationship.following && user.is_protected) { mPagesErrorContainer.setVisibility(View.VISIBLE); mPagesErrorText.setText(R.string.user_protected_summary); mPagesErrorIcon.setImageResource(R.drawable.ic_info_locked); @@ -365,9 +366,9 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mPagesErrorText.setText(null); mPagesContent.setVisibility(View.VISIBLE); } - if (relationship.isSourceBlockingTarget()) { + if (userRelationship.blocking) { mFollowButton.setText(R.string.unblock); - } else if (relationship.isSourceFollowingTarget()) { + } else if (userRelationship.following) { mFollowButton.setText(R.string.unfollow); } else if (user.is_follow_request_sent) { mFollowButton.setText(R.string.requested); @@ -375,10 +376,10 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mFollowButton.setText(R.string.follow); } mFollowButton.setCompoundDrawablePadding(Math.round(mFollowButton.getTextSize() * 0.25f)); - mFollowingYouIndicator.setVisibility(relationship.isTargetFollowingSource() ? View.VISIBLE : View.GONE); + mFollowingYouIndicator.setVisibility(userRelationship.followed_by ? View.VISIBLE : View.GONE); final CacheUserInfoRunnable task = new CacheUserInfoRunnable(getContext().getApplicationContext()); - task.setParams(Pair.create(user, relationship)); + task.setParams(Pair.create(user, userRelationship)); TaskStarter.execute(task); mFollowButton.setVisibility(View.VISIBLE); } @@ -625,14 +626,14 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener return mUser; } - public void getUserInfo(final UserKey accountId, final String userId, final String screenName, + public void getUserInfo(final UserKey accountId, final UserKey userId, final String screenName, final boolean omitIntentExtra) { final LoaderManager lm = getLoaderManager(); lm.destroyLoader(LOADER_ID_USER); lm.destroyLoader(LOADER_ID_FRIENDSHIP); final Bundle args = new Bundle(); args.putParcelable(EXTRA_ACCOUNT_KEY, accountId); - args.putString(EXTRA_USER_ID, userId); + args.putParcelable(EXTRA_USER_ID, userId); args.putString(EXTRA_SCREEN_NAME, screenName); args.putBoolean(EXTRA_OMIT_INTENT_EXTRA, omitIntentExtra); if (!mGetUserInfoLoaderInitialized) { @@ -735,13 +736,13 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener mActionBarShadowColor = 0xA0000000; final Bundle args = getArguments(); UserKey accountId = null; - String userId = null; + UserKey userId = null; String screenName = null; if (savedInstanceState != null) { args.putAll(savedInstanceState); } else { accountId = args.getParcelable(EXTRA_ACCOUNT_KEY); - userId = args.getString(EXTRA_USER_ID); + userId = args.getParcelable(EXTRA_USER_KEY); screenName = args.getString(EXTRA_SCREEN_NAME); } @@ -895,28 +896,26 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener final UserRelationship userRelationship = mRelationship; if (!isMyself && userRelationship != null) { - final Relationship relationship = userRelationship.relationship; - MenuUtils.setMenuItemAvailability(menu, R.id.send_direct_message, relationship.canSourceDMTarget()); + MenuUtils.setMenuItemAvailability(menu, R.id.send_direct_message, userRelationship.can_dm); MenuUtils.setMenuItemAvailability(menu, R.id.block, true); MenuUtils.setMenuItemAvailability(menu, R.id.mute_user, true); final MenuItem blockItem = menu.findItem(R.id.block); if (blockItem != null) { - final boolean blocking = relationship.isSourceBlockingTarget(); - ActionIconDrawable.setMenuHighlight(blockItem, new TwidereMenuInfo(blocking)); - blockItem.setTitle(blocking ? R.string.unblock : R.string.block); + ActionIconDrawable.setMenuHighlight(blockItem, new TwidereMenuInfo(userRelationship.blocking)); + blockItem.setTitle(userRelationship.blocking ? R.string.unblock : R.string.block); } final MenuItem muteItem = menu.findItem(R.id.mute_user); if (muteItem != null) { - muteItem.setChecked(relationship.isSourceMutingTarget()); + muteItem.setChecked(userRelationship.muting); } final MenuItem filterItem = menu.findItem(R.id.add_to_filter); if (filterItem != null) { - ActionIconDrawable.setMenuHighlight(filterItem, new TwidereMenuInfo(userRelationship.isFiltering)); - filterItem.setTitle(userRelationship.isFiltering ? R.string.remove_from_filter : R.string.add_to_filter); + ActionIconDrawable.setMenuHighlight(filterItem, new TwidereMenuInfo(userRelationship.filtering)); + filterItem.setTitle(userRelationship.filtering ? R.string.remove_from_filter : R.string.add_to_filter); } final MenuItem wantRetweetsItem = menu.findItem(R.id.enable_retweets); if (wantRetweetsItem != null) { - wantRetweetsItem.setChecked(relationship.isSourceWantRetweetsFromTarget()); + wantRetweetsItem.setChecked(userRelationship.retweet_enabled); } } else { MenuUtils.setMenuItemAvailability(menu, R.id.send_direct_message, false); @@ -951,7 +950,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener switch (item.getItemId()) { case R.id.block: { if (userRelationship == null) return true; - if (userRelationship.relationship.isSourceBlockingTarget()) { + if (userRelationship.blocking) { twitter.destroyBlockAsync(user.account_key, user.key); } else { CreateUserBlockDialogFragment.show(getFragmentManager(), user); @@ -965,7 +964,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener case R.id.add_to_filter: { if (userRelationship == null) return true; final ContentResolver cr = getContentResolver(); - if (userRelationship.isFiltering) { + if (userRelationship.filtering) { final String where = Expression.equalsArgs(Filters.Users.USER_KEY).getSQL(); final String[] whereArgs = {user.key.toString()}; cr.delete(Filters.Users.CONTENT_URI, where, whereArgs); @@ -978,7 +977,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener } case R.id.mute_user: { if (userRelationship == null) return true; - if (userRelationship.relationship.isSourceMutingTarget()) { + if (userRelationship.muting) { twitter.destroyMuteAsync(user.account_key, user.key); } else { CreateUserMuteDialogFragment.show(getFragmentManager(), user); @@ -1040,11 +1039,10 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener } case R.id.follow: { if (userRelationship == null) return true; - final boolean isFollowing = userRelationship.relationship.isSourceFollowingTarget(); final boolean updatingRelationship = twitter.isUpdatingRelationship(user.account_key, user.key); if (!updatingRelationship) { - if (isFollowing) { + if (userRelationship.following) { DestroyFriendshipDialogFragment.show(getFragmentManager(), user); } else { twitter.createFriendshipAsync(user.account_key, user.key); @@ -1275,9 +1273,9 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener final UserRelationship userRelationship = mRelationship; final AsyncTwitterWrapper twitter = mTwitterWrapper; if (userRelationship == null || twitter == null) return; - if (userRelationship.relationship.isSourceBlockingTarget()) { + if (userRelationship.blocking) { twitter.destroyBlockAsync(user.account_key, user.key); - } else if (userRelationship.relationship.isSourceFollowingTarget()) { + } else if (userRelationship.following) { DestroyFriendshipDialogFragment.show(getFragmentManager(), user); } else { twitter.createFriendshipAsync(user.account_key, user.key); @@ -1433,7 +1431,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener lm.destroyLoader(LOADER_ID_FRIENDSHIP); final Bundle args = new Bundle(); args.putParcelable(EXTRA_ACCOUNT_KEY, user.account_key); - args.putString(EXTRA_USER_ID, user.key.getId()); + args.putParcelable(EXTRA_USER, user); if (!mGetFriendShipLoaderInitialized) { lm.initLoader(LOADER_ID_FRIENDSHIP, args, mFriendshipLoaderCallbacks); mGetFriendShipLoaderInitialized = true; @@ -1445,7 +1443,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener private void getUserInfo(final boolean omitIntentExtra) { final ParcelableUser user = mUser; if (user == null) return; - getUserInfo(user.account_key, user.key.getId(), user.screen_name, omitIntentExtra); + getUserInfo(user.account_key, user.key, user.screen_name, omitIntentExtra); } private void setUiColor(int color) { @@ -1730,39 +1728,51 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener static class UserRelationshipLoader extends AsyncTaskLoader> { private final Context context; + @Nullable private final UserKey mAccountKey; - private final String mUserId; + @Nullable + private final ParcelableUser mUser; public UserRelationshipLoader(final Context context, @Nullable final UserKey accountKey, - final String userId) { + @Nullable final ParcelableUser user) { super(context); this.context = context; this.mAccountKey = accountKey; - this.mUserId = userId; + this.mUser = user; } @Override public SingleResponse loadInBackground() { - if (mAccountKey == null) { + if (mAccountKey == null || mUser == null) { + return SingleResponse.getInstance(new TwitterException("Null parameters")); + } + final boolean isFiltering = DataStoreUtils.isFilteringUser(context, mUser.key); + if (mAccountKey.equals(mUser.key)) + return SingleResponse.getInstance(); + final ParcelableCredentials credentials = ParcelableCredentialsUtils.getCredentials(context, + mAccountKey); + if (credentials == null) { return SingleResponse.getInstance(new TwitterException("No Account")); } - final boolean isFiltering = DataStoreUtils.isFilteringUser(context, mUserId); - if (mAccountKey.getId().equals(mUserId)) - return SingleResponse.getInstance(); + if (TwitterAPIFactory.isStatusNetCredentials(credentials)) { + if (!UserKeyUtils.isSameHost(mAccountKey, mUser.key)) { + return SingleResponse.getInstance(new UserRelationship(mUser, isFiltering)); + } + } final Twitter twitter = TwitterAPIFactory.getTwitterInstance(context, mAccountKey, false); if (twitter == null) { return SingleResponse.getInstance(new TwitterException("No Account")); } try { - final Relationship relationship = twitter.showFriendship(mUserId); - final UserKey userKey = new UserKey(mUserId, mAccountKey.getHost()); + final Relationship relationship = twitter.showFriendship(mUser.key.getId()); + final UserKey userKey = mUser.key; if (relationship.isSourceBlockingTarget() || relationship.isSourceBlockedByTarget()) { Utils.setLastSeen(context, userKey, -1); } else { Utils.setLastSeen(context, userKey, System.currentTimeMillis()); } Utils.updateRelationship(context, mAccountKey, userKey, relationship); - return SingleResponse.getInstance(new UserRelationship(relationship, isFiltering)); + return SingleResponse.getInstance(new UserRelationship(mAccountKey, relationship, isFiltering)); } catch (final TwitterException e) { return SingleResponse.getInstance(e); } @@ -1774,27 +1784,45 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener } } - static class UserRelationship { - @NonNull - Relationship relationship; - boolean isFiltering; + static class UserRelationship extends CachedRelationship { + final String source, target; + boolean filtering; + boolean can_dm; - public UserRelationship(@NonNull Relationship relationship, boolean isFiltering) { - this.relationship = relationship; - this.isFiltering = isFiltering; + public UserRelationship(@NonNull UserKey accountKey, @NonNull Relationship relationship, + boolean filtering) { + super(accountKey, relationship.getTargetUserId(), relationship); + this.source = relationship.getSourceUserId(); + this.target = relationship.getTargetUserId(); + this.filtering = filtering; + this.can_dm = relationship.canSourceDMTarget(); + } + + public UserRelationship(@NonNull ParcelableUser user, boolean filtering) { + this.source = user.account_key.getId(); + this.target = user.key.getId(); + this.filtering = filtering; + if (user.extras != null) { + this.following = user.is_following; + this.followed_by = user.extras.statusnet_followed_by; + this.blocking = user.extras.statusnet_blocking; + this.blocked_by = user.extras.statusnet_blocked_by; + this.can_dm = user.extras.statusnet_followed_by; + } } public boolean check(@NonNull ParcelableUser user) { - if (!TextUtils.equals(relationship.getSourceUserId(), user.account_key.getId())) { + if (!TextUtils.equals(source, user.account_key.getId())) { return false; } - final String targetUserId = relationship.getTargetUserId(); - return (user.extras != null && TextUtils.equals(targetUserId, user.extras.unique_id)) - || TextUtils.equals(targetUserId, user.key.getId()); + return (user.extras != null && TextUtils.equals(target, user.extras.unique_id)) + || TextUtils.equals(target, user.key.getId()); } + } - private static class CacheUserInfoRunnable extends AbstractTask, Object, Object> { + private static class CacheUserInfoRunnable extends AbstractTask, Object, Object> { private final Context context; public CacheUserInfoRunnable(Context context) { @@ -1802,12 +1830,12 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener } @Override - public Object doLongOperation(Pair args) { + public Object doLongOperation(Pair args) { final ContentResolver resolver = context.getContentResolver(); final ParcelableUser user = args.first; resolver.insert(CachedUsers.CONTENT_URI, ParcelableUserValuesCreator.create(user)); - resolver.insert(CachedRelationships.CONTENT_URI, CachedRelationshipValuesCreator.create( - new CachedRelationship(user.account_key, user.key.getId(), args.second))); + resolver.insert(CachedRelationships.CONTENT_URI, + CachedRelationshipValuesCreator.create(args.second)); return null; } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserProfileEditorFragment.java b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserProfileEditorFragment.java index 3e5f90f2b..a6a726afa 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/fragment/UserProfileEditorFragment.java +++ b/twidere/src/main/java/org/mariotaku/twidere/fragment/UserProfileEditorFragment.java @@ -49,6 +49,7 @@ import android.widget.Toast; import com.rengwuxian.materialedittext.MaterialEditText; import com.twitter.Validator; +import org.mariotaku.abstask.library.TaskStarter; import org.mariotaku.twidere.R; import org.mariotaku.twidere.activity.ColorPickerDialogActivity; import org.mariotaku.twidere.activity.ThemedImagePickerActivity; @@ -67,7 +68,6 @@ import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils; import org.mariotaku.twidere.model.util.ParcelableUserUtils; import org.mariotaku.twidere.task.UpdateAccountInfoTask; import org.mariotaku.twidere.task.UpdateProfileBannerImageTask; -import org.mariotaku.abstask.library.TaskStarter; import org.mariotaku.twidere.util.AsyncTaskUtils; import org.mariotaku.twidere.util.AsyncTwitterWrapper.UpdateProfileImageTask; import org.mariotaku.twidere.util.HtmlEscapeHelper; @@ -171,8 +171,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On public Loader> onCreateLoader(final int id, final Bundle args) { mProgressContainer.setVisibility(View.VISIBLE); mEditProfileContent.setVisibility(View.GONE); - return new ParcelableUserLoader(getActivity(), mAccountId, mAccountId.getId(), null, - getArguments(), false, false); + return new ParcelableUserLoader(getActivity(), mAccountId, mAccountId, null, getArguments(), + false, false); } @Override diff --git a/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableUserLoader.java b/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableUserLoader.java index ef1ac3379..6e1df9a54 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableUserLoader.java +++ b/twidere/src/main/java/org/mariotaku/twidere/loader/ParcelableUserLoader.java @@ -25,9 +25,11 @@ import android.content.Context; import android.database.Cursor; import android.os.Bundle; import android.support.v4.content.AsyncTaskLoader; +import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import org.mariotaku.abstask.library.TaskStarter; import org.mariotaku.sqliteqb.library.Expression; import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.api.twitter.Twitter; @@ -45,7 +47,6 @@ import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils; import org.mariotaku.twidere.model.util.ParcelableUserUtils; import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers; import org.mariotaku.twidere.task.UpdateAccountInfoTask; -import org.mariotaku.abstask.library.TaskStarter; import org.mariotaku.twidere.util.TwitterAPIFactory; import org.mariotaku.twidere.util.TwitterWrapper; import org.mariotaku.twidere.util.UserColorNameManager; @@ -60,14 +61,15 @@ public final class ParcelableUserLoader extends AsyncTaskLoader= Build.VERSION_CODES.LOLLIPOP && newDocument) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); } @@ -101,6 +93,16 @@ public class IntentUtils implements Constants { } } + public static Intent userProfile(@Nullable UserKey accountKey, UserKey userKey, String screenName, + @UserFragment.Referral String referral, String profileUrl) { + if (userKey == null && isEmpty(screenName)) return null; + final Uri uri = LinkCreator.getTwidereUserLink(accountKey, userKey, screenName); + final Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.putExtra(EXTRA_REFERRAL, referral); + intent.putExtra(EXTRA_PROFILE_URL, profileUrl); + return intent; + } + public static void openItems(@NonNull final Context context, final List items) { if (items == null) return; final Bundle extras = new Bundle(); @@ -662,4 +664,10 @@ public class IntentUtils implements Constants { intent.setPackage(BuildConfig.APPLICATION_ID); context.startActivity(intent); } + + public static void applyNewDocument(Intent intent, boolean enable) { + if (enable && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + } + } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/TwidereLinkify.java b/twidere/src/main/java/org/mariotaku/twidere/util/TwidereLinkify.java index ad6657db6..245f5071a 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/TwidereLinkify.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/TwidereLinkify.java @@ -232,7 +232,7 @@ public final class TwidereLinkify implements Constants { // Extend selection if (isAtSymbol(ch)) { start = start - 1; - } else if (isHashSymbol(ch) && end < length - 1 && isHashSymbol(string.charAt(end))) { + } else if (isHashSymbol(ch) && end < length && isHashSymbol(string.charAt(end))) { start = start - 1; end = end + 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 e298be8fa..fc9e3e4e1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/Utils.java @@ -136,6 +136,7 @@ import org.mariotaku.twidere.fragment.InteractionsTimelineFragment; import org.mariotaku.twidere.fragment.ItemsListFragment; import org.mariotaku.twidere.fragment.ListsFragment; import org.mariotaku.twidere.fragment.MessagesConversationFragment; +import org.mariotaku.twidere.fragment.MessagesEntriesFragment; import org.mariotaku.twidere.fragment.MutesUsersListFragment; import org.mariotaku.twidere.fragment.PublicTimelineFragment; import org.mariotaku.twidere.fragment.SavedSearchesListFragment; @@ -502,12 +503,16 @@ public final class Utils implements Constants { fragment = new UserFragment(); final String paramScreenName = uri.getQueryParameter(QUERY_PARAM_SCREEN_NAME); final String paramUserId = uri.getQueryParameter(QUERY_PARAM_USER_ID); + final UserKey paramUserKey = UserKey.valueOf(uri.getQueryParameter(QUERY_PARAM_USER_KEY)); if (!args.containsKey(EXTRA_SCREEN_NAME)) { args.putString(EXTRA_SCREEN_NAME, paramScreenName); } if (!args.containsKey(EXTRA_USER_ID)) { args.putString(EXTRA_USER_ID, paramUserId); } + if (!args.containsKey(EXTRA_USER_KEY)) { + args.putParcelable(EXTRA_USER_KEY, paramUserKey); + } args.putString(EXTRA_REFERRAL, intent.getStringExtra(EXTRA_REFERRAL)); break; } @@ -614,7 +619,11 @@ public final class Utils implements Constants { break; } case LINK_ID_DIRECT_MESSAGES: { - fragment = new DirectMessagesFragment(); + if (BuildConfig.DEBUG) { + fragment = new MessagesEntriesFragment(); + } else { + fragment = new DirectMessagesFragment(); + } break; } case LINK_ID_INTERACTIONS: {