fixed gif sharing

improved gnu social user
improved fanfou hashtag
This commit is contained in:
Mariotaku Lee 2016-03-29 11:09:26 +08:00
parent 7cb22ce556
commit f8d6644858
23 changed files with 277 additions and 118 deletions

View File

@ -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;
}

View File

@ -215,13 +215,25 @@ public class User extends TwitterResponseObject implements Comparable<User> {
@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<User> {
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<User> {
", 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<User> {
", 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<User> {
", 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<User> {
", ostatusUri='" + ostatusUri + '\'' +
", profileImageUrlOriginal='" + profileImageUrlOriginal + '\'' +
", profileImageUrlProfileSize='" + profileImageUrlProfileSize + '\'' +
", followsYou=" + followsYou +
", blocksYou=" + blocksYou +
", statusnetBlocking=" + statusnetBlocking +
"} " + super.toString();
}

View File

@ -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";

View File

@ -508,6 +508,9 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
@JsonField(name = "user_profile_image_url_profile_size")
@ParcelableThisPlease
public String user_profile_image_url_profile_size;
@JsonField(name = "user_statusnet_profile_url")
@ParcelableThisPlease
public String user_statusnet_profile_url;
@Override
public int describeContents() {

View File

@ -252,9 +252,9 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
@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<ParcelableUser> {
", 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<ParcelableUser> {
", is_cache=" + is_cache +
", is_basic=" + is_basic +
", extras=" + extras +
", color=" + color +
", nickname='" + nickname + '\'' +
'}';
}
@ -319,6 +322,15 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
@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> {
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<Extras> CREATOR = new Creator<Extras>() {
public Extras createFromParcel(Parcel source) {
Extras target = new Extras();

View File

@ -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 = []

View File

@ -47,3 +47,10 @@
-keepclassmembers class org.mariotaku.twidere.activity.BrowserSignInActivity.InjectorJavaScriptInterface {
public *;
}
# 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.** { *; }

View File

@ -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;

View File

@ -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];

View File

@ -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;
}

View File

@ -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

View File

@ -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 {
}

View File

@ -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

View File

@ -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<SingleResponse<ParcelableUser>> 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<SingleResponse<UserRelationship>> {
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<UserRelationship> 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<Pair<ParcelableUser, Relationship>, Object, Object> {
}
private static class CacheUserInfoRunnable extends AbstractTask<Pair<ParcelableUser,
? extends CachedRelationship>, 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<ParcelableUser, Relationship> args) {
public Object doLongOperation(Pair<ParcelableUser, ? extends CachedRelationship> 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;
}
}

View File

@ -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<SingleResponse<ParcelableUser>> 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

View File

@ -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<SingleResponse<P
private final boolean mOmitIntentExtra, mLoadFromCache;
private final Bundle mExtras;
private final UserKey mAccountKey;
private final String mUserId;
private final UserKey mUserKey;
private final String mScreenName;
@Inject
UserColorNameManager mUserColorNameManager;
public ParcelableUserLoader(final Context context, final UserKey accountKey, final String userId,
final String screenName, final Bundle extras, final boolean omitIntentExtra,
public ParcelableUserLoader(final Context context, final UserKey accountKey,
final UserKey userKey, final String screenName,
final Bundle extras, final boolean omitIntentExtra,
final boolean loadFromCache) {
super(context);
GeneralComponentHelper.build(context).inject(this);
@ -75,7 +77,7 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
this.mLoadFromCache = loadFromCache;
this.mExtras = extras;
this.mAccountKey = accountKey;
this.mUserId = userId;
this.mUserKey = userKey;
this.mScreenName = screenName;
}
@ -109,9 +111,9 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
if (mLoadFromCache) {
final Expression where;
final String[] whereArgs;
if (mUserId != null) {
if (mUserKey != null) {
where = Expression.equalsArgs(CachedUsers.USER_KEY);
whereArgs = new String[]{mUserId};
whereArgs = new String[]{mUserKey.toString()};
} else {
where = Expression.equalsArgs(CachedUsers.SCREEN_NAME);
whereArgs = new String[]{mScreenName};
@ -137,9 +139,20 @@ public final class ParcelableUserLoader extends AsyncTaskLoader<SingleResponse<P
if (mExtras != null && UserFragment.Referral.SELF_PROFILE.equals(mExtras.getString(EXTRA_REFERRAL))) {
twitterUser = twitter.verifyCredentials();
} else {
twitterUser = TwitterWrapper.tryShowUser(twitter, mUserId, mScreenName,
String mProfileUrl = null;
if (mExtras != null) {
mProfileUrl = mExtras.getString(EXTRA_PROFILE_URL);
}
if (TwitterAPIFactory.isStatusNetCredentials(credentials) && mUserKey != null &&
mProfileUrl != null && !TextUtils.equals(credentials.account_key.getHost(),
mUserKey.getHost())) {
twitterUser = twitter.showExternalProfile(mProfileUrl);
} else {
final String id = mUserKey != null ? mUserKey.getId() : null;
twitterUser = TwitterWrapper.tryShowUser(twitter, id, mScreenName,
credentials.account_type);
}
}
final ContentValues cachedUserValues = createCachedUser(twitterUser);
resolver.insert(CachedUsers.CONTENT_URI, cachedUserValues);
final ParcelableUser user = ParcelableUserUtils.fromUser(twitterUser, accountKey);

View File

@ -140,6 +140,7 @@ public class ParcelableStatusUtils implements Constants {
result.user_is_verified = user.isVerified();
result.user_is_following = user.isFollowing();
result.extras.user_profile_image_url_profile_size = user.getProfileImageUrlProfileSize();
result.extras.user_statusnet_profile_url = user.getStatusnetProfileUrl();
if (result.extras.user_profile_image_url_profile_size == null) {
result.extras.user_profile_image_url_profile_size = user.getProfileImageUrlLarge();
}

View File

@ -71,6 +71,9 @@ public class ParcelableUserUtils implements TwidereConstants {
ParcelableUser.Extras extras = new ParcelableUser.Extras();
extras.ostatus_uri = user.getOstatusUri();
extras.statusnet_blocking = user.isStatusnetBlocking();
extras.statusnet_blocked_by = user.isBlocksYou();
extras.statusnet_followed_by = user.isFollowsYou();
extras.statusnet_profile_url = user.getStatusnetProfileUrl();
extras.profile_image_url_original = user.getProfileImageUrlOriginal();
extras.profile_image_url_profile_size = user.getProfileImageUrlProfileSize();

View File

@ -35,6 +35,7 @@ import android.support.v4.content.res.ResourcesCompat;
import android.text.TextUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.annotation.CustomTabType;
@ -43,6 +44,7 @@ import org.mariotaku.twidere.fragment.DirectMessagesFragment;
import org.mariotaku.twidere.fragment.HomeTimelineFragment;
import org.mariotaku.twidere.fragment.InteractionsTimelineFragment;
import org.mariotaku.twidere.fragment.InvalidTabFragment;
import org.mariotaku.twidere.fragment.MessagesEntriesFragment;
import org.mariotaku.twidere.fragment.RetweetsOfMeFragment;
import org.mariotaku.twidere.fragment.StatusesSearchFragment;
import org.mariotaku.twidere.fragment.TrendsSuggestionsFragment;
@ -84,9 +86,15 @@ public class CustomTabUtils implements Constants {
ExtraConfiguration.newBoolean(EXTRA_MY_FOLLOWING_ONLY, R.string.following_only, false),
ExtraConfiguration.newBoolean(EXTRA_MENTIONS_ONLY, R.string.mentions_only, false)));
if (BuildConfig.DEBUG) {
CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.DIRECT_MESSAGES, new CustomTabConfiguration(
DirectMessagesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false));
} else {
CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.DIRECT_MESSAGES, new CustomTabConfiguration(
MessagesEntriesFragment.class, R.string.direct_messages, R.drawable.ic_action_message,
CustomTabConfiguration.ACCOUNT_OPTIONAL, CustomTabConfiguration.FIELD_TYPE_NONE, 2, false));
}
CUSTOM_TABS_CONFIGURATION_MAP.put(CustomTabType.TRENDS_SUGGESTIONS, new CustomTabConfiguration(
TrendsSuggestionsFragment.class, R.string.trends, R.drawable.ic_action_hashtag,

View File

@ -820,6 +820,10 @@ public class DataStoreUtils implements Constants {
sAccountScreenNames.clear();
}
public static boolean isFilteringUser(Context context, UserKey userKey) {
return isFilteringUser(context, userKey.toString());
}
public static boolean isFilteringUser(Context context, String userKey) {
final ContentResolver cr = context.getContentResolver();
final Expression where = Expression.equalsArgs(Filters.Users.USER_KEY);

View File

@ -59,17 +59,11 @@ public class IntentUtils implements Constants {
@UserFragment.Referral final String referral) {
final Bundle extras = new Bundle();
extras.putParcelable(EXTRA_USER, user);
final Uri.Builder builder = new Uri.Builder();
builder.scheme(SCHEME_TWIDERE);
builder.authority(AUTHORITY_USER);
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, user.account_key.toString());
if (user.key != null) {
builder.appendQueryParameter(QUERY_PARAM_USER_ID, user.key.toString());
if (user.extras != null) {
extras.putString(EXTRA_PROFILE_URL, user.extras.statusnet_profile_url);
}
if (user.screen_name != null) {
builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, user.screen_name);
}
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
final Uri uri = LinkCreator.getTwidereUserLink(user.account_key, user.key, user.screen_name);
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.setExtrasClassLoader(context.getClassLoader());
intent.putExtras(extras);
intent.putExtra(EXTRA_REFERRAL, referral);
@ -87,10 +81,8 @@ public class IntentUtils implements Constants {
final UserKey userKey, final String screenName,
final Bundle activityOptions, final boolean newDocument,
@UserFragment.Referral final String referral) {
if (userKey == null && isEmpty(screenName)) return;
final Uri uri = LinkCreator.getTwidereUserLink(accountKey, userKey, screenName);
final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(EXTRA_REFERRAL, referral);
final Intent intent = userProfile(accountKey, userKey, screenName, referral, null);
if (intent == null) return;
if (Build.VERSION.SDK_INT >= 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<Parcelable> 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);
}
}
}

View File

@ -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;
}

View File

@ -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: {
if (BuildConfig.DEBUG) {
fragment = new MessagesEntriesFragment();
} else {
fragment = new DirectMessagesFragment();
}
break;
}
case LINK_ID_INTERACTIONS: {