fixed fallback intent

This commit is contained in:
Mariotaku Lee 2016-04-01 22:15:53 +08:00
parent 16201b8142
commit 78bc7e6d55
31 changed files with 457 additions and 526 deletions

View File

@ -41,7 +41,7 @@ dependencies {
apt 'com.github.mariotaku.ObjectCursor:processor:0.9.7' apt 'com.github.mariotaku.ObjectCursor:processor:0.9.7'
compile 'com.android.support:support-annotations:23.2.1' compile 'com.android.support:support-annotations:23.2.1'
compile 'com.bluelinelabs:logansquare:1.3.7' compile 'com.bluelinelabs:logansquare:1.3.7'
compile 'com.github.mariotaku.RestFu:library:0.9.25' compile 'com.github.mariotaku.RestFu:library:0.9.26-SNAPSHOT'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.7' compile 'com.github.mariotaku.ObjectCursor:core:0.9.7'
compile fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])

View File

@ -98,7 +98,6 @@ public interface UsersResources {
ResponseList<User> lookupUsersByScreenName(@Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException; ResponseList<User> lookupUsersByScreenName(@Param(value = "screen_name", arrayDelimiter = ',') String[] screenNames) throws TwitterException;
@POST("/account/remove_profile_banner.json") @POST("/account/remove_profile_banner.json")
@BodyType(BodyType.FORM)
ResponseCode removeProfileBannerImage() throws TwitterException; ResponseCode removeProfileBannerImage() throws TwitterException;
@GET("/users/search.json") @GET("/users/search.json")
@ -111,34 +110,27 @@ public interface UsersResources {
User showUserByScreenName(@Query("screen_name") String screenName) throws TwitterException; User showUserByScreenName(@Query("screen_name") String screenName) throws TwitterException;
@POST("/account/settings.json") @POST("/account/settings.json")
@BodyType(BodyType.FORM)
AccountSettings updateAccountSettings(@Param SettingsUpdate settingsUpdate) throws TwitterException; AccountSettings updateAccountSettings(@Param SettingsUpdate settingsUpdate) throws TwitterException;
@POST("/account/update_profile.json") @POST("/account/update_profile.json")
@BodyType(BodyType.FORM)
User updateProfile(@Param ProfileUpdate profileUpdate) throws TwitterException; User updateProfile(@Param ProfileUpdate profileUpdate) throws TwitterException;
@POST("/account/update_profile_background_image.json") @POST("/account/update_profile_background_image.json")
@BodyType(BodyType.MULTIPART)
User updateProfileBackgroundImage(@Param("image") FileBody data, @Param("tile") boolean tile) throws TwitterException; User updateProfileBackgroundImage(@Param("image") FileBody data, @Param("tile") boolean tile) throws TwitterException;
@POST("/account/update_profile_background_image.json") @POST("/account/update_profile_background_image.json")
@BodyType(BodyType.FORM)
User updateProfileBackgroundImage(@Param("media_id") long mediaId, @Param("tile") boolean tile) throws TwitterException; User updateProfileBackgroundImage(@Param("media_id") long mediaId, @Param("tile") boolean tile) throws TwitterException;
@POST("/account/update_profile_banner.json") @POST("/account/update_profile_banner.json")
@BodyType(BodyType.MULTIPART)
ResponseCode updateProfileBannerImage(@Param("banner") FileBody data, @Param("width") int width, ResponseCode updateProfileBannerImage(@Param("banner") FileBody data, @Param("width") int width,
@Param("height") int height, @Param("offset_left") int offsetLeft, @Param("height") int height, @Param("offset_left") int offsetLeft,
@Param("offset_top") int offsetTop) @Param("offset_top") int offsetTop)
throws TwitterException; throws TwitterException;
@POST("/account/update_profile_banner.json") @POST("/account/update_profile_banner.json")
@BodyType(BodyType.MULTIPART)
ResponseCode updateProfileBannerImage(@Param("banner") FileBody data) throws TwitterException; ResponseCode updateProfileBannerImage(@Param("banner") FileBody data) throws TwitterException;
@POST("/account/update_profile_image.json") @POST("/account/update_profile_image.json")
@BodyType(BodyType.MULTIPART)
User updateProfileImage(@Param("image") FileBody data) throws TwitterException; User updateProfileImage(@Param("image") FileBody data) throws TwitterException;
@GET("/account/verify_credentials.json") @GET("/account/verify_credentials.json")

View File

@ -68,7 +68,6 @@ public interface IntentConstants {
String INTENT_ACTION_SEND_DIRECT_MESSAGE = INTENT_PACKAGE_PREFIX + "SEND_DIRECT_MESSAGE"; String INTENT_ACTION_SEND_DIRECT_MESSAGE = INTENT_PACKAGE_PREFIX + "SEND_DIRECT_MESSAGE";
String INTENT_ACTION_DISCARD_DRAFT = INTENT_PACKAGE_PREFIX + "DISCARD_DRAFT"; String INTENT_ACTION_DISCARD_DRAFT = INTENT_PACKAGE_PREFIX + "DISCARD_DRAFT";
String INTENT_ACTION_SEND_DRAFT = INTENT_PACKAGE_PREFIX + "SEND_DRAFT"; String INTENT_ACTION_SEND_DRAFT = INTENT_PACKAGE_PREFIX + "SEND_DRAFT";
String INTENT_ACTION_PICK_ACTIVITY = "org.mariotaku.twidere.PICK_ACTIVITY";
String INTENT_ACTION_PEBBLE_NOTIFICATION = "com.getpebble.action.SEND_NOTIFICATION"; String INTENT_ACTION_PEBBLE_NOTIFICATION = "com.getpebble.action.SEND_NOTIFICATION";

View File

@ -139,8 +139,8 @@ dependencies {
compile 'com.bluelinelabs:logansquare:1.3.7' compile 'com.bluelinelabs:logansquare:1.3.7'
compile 'com.soundcloud.android:android-crop:1.0.1@aar' compile 'com.soundcloud.android:android-crop:1.0.1@aar'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2' compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.2'
compile 'com.github.mariotaku:PickNCrop:0.9.3' compile 'com.github.mariotaku:PickNCrop:0.9.4-SNAPSHOT'
compile 'com.github.mariotaku.RestFu:okhttp3:0.9.25' compile 'com.github.mariotaku.RestFu:okhttp3:0.9.26-SNAPSHOT'
compile 'com.squareup.okhttp3:okhttp:3.2.0' compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.lnikkila:extendedtouchview:0.1.0' compile 'com.lnikkila:extendedtouchview:0.1.0'
compile 'com.google.dagger:dagger:2.1' compile 'com.google.dagger:dagger:2.1'
@ -150,7 +150,7 @@ dependencies {
compile 'com.github.mariotaku.SQLiteQB:library:0.9.6' compile 'com.github.mariotaku.SQLiteQB:library:0.9.6'
compile 'com.github.mariotaku.ObjectCursor:core:0.9.7' compile 'com.github.mariotaku.ObjectCursor:core:0.9.7'
compile 'com.github.mariotaku:MultiValueSwitch:0.9.4' compile 'com.github.mariotaku:MultiValueSwitch:0.9.4'
compile 'com.github.mariotaku:AbstractTask:0.9' compile 'com.github.mariotaku:AbstractTask:0.9.1'
} }
task svgToDrawable(type: SvgDrawableTask) { task svgToDrawable(type: SvgDrawableTask) {

View File

@ -387,15 +387,6 @@
android:name=".activity.DataImportActivity" android:name=".activity.DataImportActivity"
android:label="@string/import_settings" android:label="@string/import_settings"
android:theme="@style/Theme.Twidere.NoDisplay"/> android:theme="@style/Theme.Twidere.NoDisplay"/>
<activity
android:name=".activity.ActivityPickerActivity"
android:theme="@style/Theme.Twidere.Dialog">
<intent-filter>
<action android:name="org.mariotaku.twidere.PICK_ACTIVITY"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity <activity
android:name=".activity.TwitterLinkHandlerActivity" android:name=".activity.TwitterLinkHandlerActivity"
android:excludeFromRecents="true" android:excludeFromRecents="true"

View File

@ -1,73 +0,0 @@
package org.mariotaku.twidere.activity;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.adapter.ResolveInfoListAdapter;
import org.mariotaku.twidere.loader.IntentActivitiesLoader;
import java.util.List;
public class ActivityPickerActivity extends BaseActivity implements
LoaderCallbacks<List<ResolveInfo>>, OnItemClickListener {
private ResolveInfoListAdapter mAdapter;
private ListView mListView;
@Override
public void onContentChanged() {
super.onContentChanged();
mListView = (ListView) findViewById(android.R.id.list);
}
@Override
public Loader<List<ResolveInfo>> onCreateLoader(final int id, final Bundle args) {
final Intent intent = getIntent();
final Intent extraIntent = intent.getParcelableExtra(EXTRA_INTENT);
final String[] blacklist = intent.getStringArrayExtra(EXTRA_BLACKLIST);
return new IntentActivitiesLoader(this, extraIntent, blacklist, 0);
}
@Override
public void onItemClick(final AdapterView<?> parent, final View view, final int position, final long id) {
final Intent intent = getIntent(), data = new Intent();
data.putExtra(EXTRA_DATA, mAdapter.getItem(position));
data.putExtra(EXTRA_INTENT, intent.getParcelableExtra(EXTRA_INTENT));
setResult(RESULT_OK, data);
finish();
}
@Override
public void onLoaderReset(final Loader<List<ResolveInfo>> loader) {
mAdapter.clear();
}
@Override
public void onLoadFinished(final Loader<List<ResolveInfo>> loader, final List<ResolveInfo> data) {
mAdapter.clear();
if (data != null) {
mAdapter.addAll(data);
}
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_picker);
mAdapter = new ResolveInfoListAdapter(this);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(this);
getSupportLoaderManager().initLoader(0, null, this);
}
}

View File

@ -1914,7 +1914,8 @@ public class ComposeActivity extends BaseActivity implements OnMenuItemClickList
} }
@Override @Override
protected void beforeExecute(ParcelableLocation location) { protected void beforeExecute() {
ParcelableLocation location = getParams();
final TextView textView = getCallback(); final TextView textView = getCallback();
if (textView == null) return; if (textView == null) return;

View File

@ -1,6 +1,7 @@
package org.mariotaku.twidere.activity; package org.mariotaku.twidere.activity;
import android.app.Activity; import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
@ -15,8 +16,10 @@ import android.util.Pair;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.math.NumberUtils; import org.apache.commons.lang3.math.NumberUtils;
import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.util.BugReporter;
import org.mariotaku.twidere.util.IntentUtils;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.support.IntentSupport;
import java.util.List; import java.util.List;
@ -97,20 +100,20 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants {
startActivity(handled.first); startActivity(handled.first);
} else { } else {
if (!handled.second) { if (!handled.second) {
// BugReporter.error(new TwitterLinkException("Unable to handle twitter uri " + uri)); BugReporter.logException(new TwitterLinkException("Unable to handle twitter uri " + uri));
} }
final String packageName = mPreferences.getString(KEY_FALLBACK_TWITTER_LINK_HANDLER, null);
final Intent fallbackIntent = new Intent(Intent.ACTION_VIEW, uri); final Intent fallbackIntent = new Intent(Intent.ACTION_VIEW, uri);
IntentSupport.setSelector(intent, new Intent(Intent.ACTION_VIEW).addCategory(IntentSupport.CATEGORY_APP_BROWSER)); fallbackIntent.addCategory(Intent.CATEGORY_BROWSABLE);
fallbackIntent.setPackage(packageName); fallbackIntent.setPackage(IntentUtils.getDefaultBrowserPackage(this));
if (TextUtils.isEmpty(packageName) || packageManager.queryIntentActivities(fallbackIntent, 0).isEmpty()) { final ComponentName componentName = fallbackIntent.resolveActivity(packageManager);
final Intent pickIntent = new Intent(INTENT_ACTION_PICK_ACTIVITY); if (componentName == null) {
pickIntent.putExtra(EXTRA_INTENT, new Intent(Intent.ACTION_VIEW, uri)); final Intent targetIntent = new Intent(Intent.ACTION_VIEW, uri);
pickIntent.putExtra(EXTRA_BLACKLIST, new String[]{getPackageName()}); targetIntent.addCategory(Intent.CATEGORY_BROWSABLE);
startActivityForResult(pickIntent, REQUEST_PICK_ACTIVITY); startActivity(Intent.createChooser(targetIntent, getString(R.string.open_in_browser)));
return; } else if (!TextUtils.equals(getPackageName(), componentName.getPackageName())) {
} else {
startActivity(fallbackIntent); startActivity(fallbackIntent);
} else {
// TODO show error
} }
} }
finish(); finish();
@ -180,6 +183,7 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants {
return Pair.create(null, false); return Pair.create(null, false);
} }
@NonNull
private Pair<Intent, Boolean> handleUserSpecificPageIntent(Uri uri, List<String> pathSegments, String screenName) { private Pair<Intent, Boolean> handleUserSpecificPageIntent(Uri uri, List<String> pathSegments, String screenName) {
final int segsSize = pathSegments.size(); final int segsSize = pathSegments.size();
if (segsSize == 1) { if (segsSize == 1) {

View File

@ -1,35 +0,0 @@
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import org.mariotaku.twidere.R;
public class ResolveInfoListAdapter extends ArrayAdapter<ResolveInfo> {
private final PackageManager mPackageManager;
public ResolveInfoListAdapter(final Context context) {
super(context, R.layout.list_item_two_line_small);
mPackageManager = context.getPackageManager();
}
@Override
public View getView(final int position, final View convertView, final ViewGroup parent) {
final View view = super.getView(position, convertView, parent);
final ResolveInfo info = getItem(position);
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
icon.setImageDrawable(info.loadIcon(mPackageManager));
text1.setText(info.loadLabel(mPackageManager));
text2.setVisibility(View.GONE);
return view;
}
}

View File

@ -48,6 +48,7 @@ import android.widget.TextView;
import com.afollestad.appthemeengine.ATE; import com.afollestad.appthemeengine.ATE;
import com.afollestad.appthemeengine.Config; import com.afollestad.appthemeengine.Config;
import com.pnikosis.materialishprogress.ProgressWheel; import com.pnikosis.materialishprogress.ProgressWheel;
import com.rengwuxian.materialedittext.MaterialEditText;
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.BuildConfig; import org.mariotaku.twidere.BuildConfig;
@ -73,6 +74,7 @@ import org.mariotaku.twidere.util.theme.FloatingActionButtonViewProcessor;
import org.mariotaku.twidere.util.theme.FontFamilyTagProcessor; import org.mariotaku.twidere.util.theme.FontFamilyTagProcessor;
import org.mariotaku.twidere.util.theme.IconActionButtonTagProcessor; import org.mariotaku.twidere.util.theme.IconActionButtonTagProcessor;
import org.mariotaku.twidere.util.theme.ImageViewViewProcessor; import org.mariotaku.twidere.util.theme.ImageViewViewProcessor;
import org.mariotaku.twidere.util.theme.MaterialEditTextViewProcessor;
import org.mariotaku.twidere.util.theme.OptimalLinkColorTagProcessor; import org.mariotaku.twidere.util.theme.OptimalLinkColorTagProcessor;
import org.mariotaku.twidere.util.theme.ProfileImageViewViewProcessor; import org.mariotaku.twidere.util.theme.ProfileImageViewViewProcessor;
import org.mariotaku.twidere.util.theme.ProgressWheelViewProcessor; import org.mariotaku.twidere.util.theme.ProgressWheelViewProcessor;
@ -152,6 +154,7 @@ public class TwidereApplication extends Application implements Constants,
ATE.registerViewProcessor(TimelineContentTextView.class, new TimelineContentTextViewViewProcessor()); ATE.registerViewProcessor(TimelineContentTextView.class, new TimelineContentTextViewViewProcessor());
ATE.registerViewProcessor(TextView.class, new TextViewViewProcessor()); ATE.registerViewProcessor(TextView.class, new TextViewViewProcessor());
ATE.registerViewProcessor(ImageView.class, new ImageViewViewProcessor()); ATE.registerViewProcessor(ImageView.class, new ImageViewViewProcessor());
ATE.registerViewProcessor(MaterialEditText.class, new MaterialEditTextViewProcessor());
ATE.registerViewProcessor(ProgressWheel.class, new ProgressWheelViewProcessor()); ATE.registerViewProcessor(ProgressWheel.class, new ProgressWheelViewProcessor());
ATE.registerViewProcessor(ProfileImageView.class, mProfileImageViewViewProcessor); ATE.registerViewProcessor(ProfileImageView.class, mProfileImageViewViewProcessor);
ATE.registerTagProcessor(OptimalLinkColorTagProcessor.TAG, new OptimalLinkColorTagProcessor()); ATE.registerTagProcessor(OptimalLinkColorTagProcessor.TAG, new OptimalLinkColorTagProcessor());

View File

@ -22,8 +22,6 @@ package org.mariotaku.twidere.fragment;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.AsyncTask.Status;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment; import android.support.v4.app.DialogFragment;
@ -49,6 +47,7 @@ import android.widget.Toast;
import com.rengwuxian.materialedittext.MaterialEditText; import com.rengwuxian.materialedittext.MaterialEditText;
import com.twitter.Validator; import com.twitter.Validator;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.abstask.library.TaskStarter; import org.mariotaku.abstask.library.TaskStarter;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.ColorPickerDialogActivity; import org.mariotaku.twidere.activity.ColorPickerDialogActivity;
@ -67,8 +66,8 @@ import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils; import org.mariotaku.twidere.model.util.ParcelableCredentialsUtils;
import org.mariotaku.twidere.model.util.ParcelableUserUtils; import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.task.UpdateAccountInfoTask; import org.mariotaku.twidere.task.UpdateAccountInfoTask;
import org.mariotaku.twidere.task.UpdateProfileBackgroundImageTask;
import org.mariotaku.twidere.task.UpdateProfileBannerImageTask; import org.mariotaku.twidere.task.UpdateProfileBannerImageTask;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.AsyncTwitterWrapper.UpdateProfileImageTask; import org.mariotaku.twidere.util.AsyncTwitterWrapper.UpdateProfileImageTask;
import org.mariotaku.twidere.util.HtmlEscapeHelper; import org.mariotaku.twidere.util.HtmlEscapeHelper;
import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
@ -90,15 +89,17 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
private static final int REQUEST_UPLOAD_PROFILE_IMAGE = 1; private static final int REQUEST_UPLOAD_PROFILE_IMAGE = 1;
private static final int REQUEST_UPLOAD_PROFILE_BANNER_IMAGE = 2; private static final int REQUEST_UPLOAD_PROFILE_BANNER_IMAGE = 2;
private static final int REQUEST_PICK_LINK_COLOR = 3; private static final int REQUEST_UPLOAD_PROFILE_BACKGROUND_IMAGE = 3;
private static final int REQUEST_PICK_BACKGROUND_COLOR = 4; private static final int REQUEST_PICK_LINK_COLOR = 11;
private static final int REQUEST_PICK_BACKGROUND_COLOR = 12;
private static final int RESULT_REMOVE_BANNER = 101; private static final int RESULT_REMOVE_BANNER = 101;
private static final String UPDATE_PROFILE_DIALOG_FRAGMENT_TAG = "update_profile"; private static final String UPDATE_PROFILE_DIALOG_FRAGMENT_TAG = "update_profile";
private AsyncTask<Object, Object, ?> mTask; private AbstractTask<?, ?, UserProfileEditorFragment> mTask;
private ImageView mProfileImageView; private ImageView mProfileImageView;
private ImageView mProfileBannerView; private ImageView mProfileBannerView;
private ImageView mProfileBackgroundView;
private MaterialEditText mEditName; private MaterialEditText mEditName;
private MaterialEditText mEditDescription; private MaterialEditText mEditDescription;
private MaterialEditText mEditLocation; private MaterialEditText mEditLocation;
@ -106,6 +107,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
private View mProgressContainer, mEditProfileContent; private View mProgressContainer, mEditProfileContent;
private View mEditProfileImage; private View mEditProfileImage;
private View mEditProfileBanner; private View mEditProfileBanner;
private View mEditProfileBackground;
private View mSetLinkColor, mSetBackgroundColor; private View mSetLinkColor, mSetBackgroundColor;
private ForegroundColorView mLinkColor, mBackgroundColor; private ForegroundColorView mLinkColor, mBackgroundColor;
private UserKey mAccountId; private UserKey mAccountId;
@ -129,7 +131,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
@Override @Override
public void onClick(final View view) { public void onClick(final View view) {
final ParcelableUser user = mUser; final ParcelableUser user = mUser;
if (user == null || (mTask != null && mTask.getStatus() == AsyncTask.Status.RUNNING)) if (user == null || (mTask != null && !mTask.isFinished()))
return; return;
switch (view.getId()) { switch (view.getId()) {
case R.id.profile_image: { case R.id.profile_image: {
@ -150,6 +152,11 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE); startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
break; break;
} }
case R.id.edit_profile_background: {
final Intent intent = ThemedImagePickerActivity.withThemed(getActivity()).build();
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BACKGROUND_IMAGE);
break;
}
case R.id.set_link_color: { case R.id.set_link_color: {
final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class); final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
intent.putExtra(EXTRA_COLOR, user.link_color); intent.putExtra(EXTRA_COLOR, user.link_color);
@ -206,7 +213,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
final int backgroundColor = mBackgroundColor.getColor(); final int backgroundColor = mBackgroundColor.getColor();
mTask = new UpdateProfileTaskInternal(this, mAccountId, mUser, name, url, location, mTask = new UpdateProfileTaskInternal(this, mAccountId, mUser, name, url, location,
description, linkColor, backgroundColor); description, linkColor, backgroundColor);
AsyncTaskUtils.executeTask(mTask); TaskStarter.execute(mTask);
return true; return true;
} }
} }
@ -236,8 +243,12 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
mProfileImageView.setOnClickListener(this); mProfileImageView.setOnClickListener(this);
mProfileBannerView.setOnClickListener(this); mProfileBannerView.setOnClickListener(this);
mEditProfileBanner.setOnClickListener(this); mProfileBackgroundView.setOnClickListener(this);
mEditProfileImage.setOnClickListener(this); mEditProfileImage.setOnClickListener(this);
mEditProfileBanner.setOnClickListener(this);
mEditProfileBackground.setOnClickListener(this);
mSetLinkColor.setOnClickListener(this); mSetLinkColor.setOnClickListener(this);
mSetBackgroundColor.setOnClickListener(this); mSetBackgroundColor.setOnClickListener(this);
@ -279,14 +290,16 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
mProgressContainer = view.findViewById(R.id.progress_container); mProgressContainer = view.findViewById(R.id.progress_container);
mEditProfileContent = view.findViewById(R.id.edit_profile_content); mEditProfileContent = view.findViewById(R.id.edit_profile_content);
mProfileBannerView = (ImageView) view.findViewById(R.id.profile_banner);
mProfileImageView = (ImageView) view.findViewById(R.id.profile_image); mProfileImageView = (ImageView) view.findViewById(R.id.profile_image);
mProfileBannerView = (ImageView) view.findViewById(R.id.profile_banner);
mProfileBackgroundView = (ImageView) view.findViewById(R.id.profile_background);
mEditName = (MaterialEditText) view.findViewById(R.id.name); mEditName = (MaterialEditText) view.findViewById(R.id.name);
mEditDescription = (MaterialEditText) view.findViewById(R.id.description); mEditDescription = (MaterialEditText) view.findViewById(R.id.description);
mEditLocation = (MaterialEditText) view.findViewById(R.id.location); mEditLocation = (MaterialEditText) view.findViewById(R.id.location);
mEditUrl = (MaterialEditText) view.findViewById(R.id.url); mEditUrl = (MaterialEditText) view.findViewById(R.id.url);
mEditProfileImage = view.findViewById(R.id.edit_profile_image); mEditProfileImage = view.findViewById(R.id.edit_profile_image);
mEditProfileBanner = view.findViewById(R.id.edit_profile_banner); mEditProfileBanner = view.findViewById(R.id.edit_profile_banner);
mEditProfileBackground = view.findViewById(R.id.edit_profile_background);
mLinkColor = (ForegroundColorView) view.findViewById(R.id.link_color); mLinkColor = (ForegroundColorView) view.findViewById(R.id.link_color);
mBackgroundColor = (ForegroundColorView) view.findViewById(R.id.background_color); mBackgroundColor = (ForegroundColorView) view.findViewById(R.id.background_color);
mSetLinkColor = view.findViewById(R.id.set_link_color); mSetLinkColor = view.findViewById(R.id.set_link_color);
@ -298,17 +311,26 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
if (resultCode == FragmentActivity.RESULT_CANCELED) return; if (resultCode == FragmentActivity.RESULT_CANCELED) return;
switch (requestCode) { switch (requestCode) {
case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: { case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: {
if (mTask != null && mTask.getStatus() == Status.RUNNING) return; if (mTask != null && !mTask.isFinished()) return;
if (resultCode == RESULT_REMOVE_BANNER) { if (resultCode == RESULT_REMOVE_BANNER) {
mTask = new RemoveProfileBannerTaskInternal(mAccountId); mTask = new RemoveProfileBannerTaskInternal(mAccountId);
} else { } else {
mTask = new UpdateProfileBannerImageTaskInternal(getActivity(), mAccountId, data.getData(), true); mTask = new UpdateProfileBannerImageTaskInternal(getActivity(), mAccountId,
data.getData(), true);
} }
break; break;
} }
case REQUEST_UPLOAD_PROFILE_BACKGROUND_IMAGE: {
//TODO upload profile background
if (mTask != null && !mTask.isFinished()) return;
mTask = new UpdateProfileBackgroundImageTaskInternal(getActivity(), mAccountId,
data.getData(), false, true);
break;
}
case REQUEST_UPLOAD_PROFILE_IMAGE: { case REQUEST_UPLOAD_PROFILE_IMAGE: {
if (mTask != null && mTask.getStatus() == Status.RUNNING) return; if (mTask != null && !mTask.isFinished()) return;
mTask = new UpdateProfileImageTaskInternal(getActivity(), mAccountId, data.getData(), true); mTask = new UpdateProfileImageTaskInternal(getActivity(), mAccountId,
data.getData(), true);
break; break;
} }
case REQUEST_PICK_LINK_COLOR: { case REQUEST_PICK_LINK_COLOR: {
@ -341,10 +363,16 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
mEditLocation.setText(user.location); mEditLocation.setText(user.location);
mEditUrl.setText(isEmpty(user.url_expanded) ? user.url : user.url_expanded); mEditUrl.setText(isEmpty(user.url_expanded) ? user.url : user.url_expanded);
mMediaLoader.displayProfileImage(mProfileImageView, user); mMediaLoader.displayProfileImage(mProfileImageView, user);
final int def_width = getResources().getDisplayMetrics().widthPixels; final int defWidth = getResources().getDisplayMetrics().widthPixels;
mMediaLoader.displayProfileBanner(mProfileBannerView, user.profile_banner_url, def_width); mMediaLoader.displayProfileBanner(mProfileBannerView, user.profile_banner_url, defWidth);
mMediaLoader.displayImage(mProfileBackgroundView, user.profile_background_url);
mLinkColor.setColor(user.link_color); mLinkColor.setColor(user.link_color);
mBackgroundColor.setColor(user.background_color); mBackgroundColor.setColor(user.background_color);
if (USER_TYPE_FANFOU_COM.equals(user.key.getHost())) {
mEditProfileBanner.setVisibility(View.GONE);
} else {
mEditProfileBanner.setVisibility(View.VISIBLE);
}
} else { } else {
mProgressContainer.setVisibility(View.GONE); mProgressContainer.setVisibility(View.GONE);
mEditProfileContent.setVisibility(View.GONE); mEditProfileContent.setVisibility(View.GONE);
@ -368,8 +396,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (mTask != null && mTask.getStatus() == Status.PENDING) { if (mTask != null && !mTask.isFinished()) {
AsyncTaskUtils.executeTask(mTask); TaskStarter.execute(mTask);
} }
} }
@ -415,7 +443,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
static class UpdateProfileTaskInternal extends AsyncTask<Object, Object, SingleResponse<ParcelableUser>> { static class UpdateProfileTaskInternal extends AbstractTask<Object, SingleResponse<ParcelableUser>,
UserProfileEditorFragment> {
private static final String DIALOG_FRAGMENT_TAG = "updating_user_profile"; private static final String DIALOG_FRAGMENT_TAG = "updating_user_profile";
private final UserProfileEditorFragment mFragment; private final UserProfileEditorFragment mFragment;
@ -449,7 +478,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected SingleResponse<ParcelableUser> doInBackground(final Object... params) { protected SingleResponse<ParcelableUser> doLongOperation(final Object params) {
final ParcelableCredentials credentials = ParcelableCredentialsUtils.getCredentials(mActivity, mAccountKey); final ParcelableCredentials credentials = ParcelableCredentialsUtils.getCredentials(mActivity, mAccountKey);
if (credentials == null) return SingleResponse.getInstance(); if (credentials == null) return SingleResponse.getInstance();
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, credentials, final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mActivity, credentials,
@ -495,8 +524,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableUser> result) { protected void afterExecute(SingleResponse<ParcelableUser> result) {
super.onPostExecute(result); super.afterExecute(result);
if (result.hasData()) { if (result.hasData()) {
final ParcelableAccount account = result.getExtras().getParcelable(EXTRA_ACCOUNT); final ParcelableAccount account = result.getExtras().getParcelable(EXTRA_ACCOUNT);
if (account != null) { if (account != null) {
@ -518,7 +547,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPreExecute() { protected void beforeExecute() {
super.beforeExecute();
mFragment.executeAfterFragmentResumed(new Action() { mFragment.executeAfterFragmentResumed(new Action() {
@Override @Override
public void execute(IBaseFragment fragment) { public void execute(IBaseFragment fragment) {
@ -526,12 +556,11 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
df.setCancelable(false); df.setCancelable(false);
} }
}); });
super.onPreExecute();
} }
} }
class RemoveProfileBannerTaskInternal extends AsyncTask<Object, Object, SingleResponse<Boolean>> { class RemoveProfileBannerTaskInternal extends AbstractTask<Object, SingleResponse<Boolean>, UserProfileEditorFragment> {
private final UserKey mAccountKey; private final UserKey mAccountKey;
@ -540,13 +569,13 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected SingleResponse<Boolean> doInBackground(final Object... params) { protected SingleResponse<Boolean> doLongOperation(final Object params) {
return TwitterWrapper.deleteProfileBannerImage(getActivity(), mAccountKey); return TwitterWrapper.deleteProfileBannerImage(getActivity(), mAccountKey);
} }
@Override @Override
protected void onPostExecute(final SingleResponse<Boolean> result) { protected void afterExecute(final SingleResponse<Boolean> result) {
super.onPostExecute(result); super.afterExecute(result);
if (result.getData() != null && result.getData()) { if (result.getData() != null && result.getData()) {
getUserInfo(); getUserInfo();
Toast.makeText(getActivity(), R.string.profile_banner_image_updated, Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), R.string.profile_banner_image_updated, Toast.LENGTH_SHORT).show();
@ -558,14 +587,14 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPreExecute() { protected void beforeExecute() {
super.onPreExecute(); super.beforeExecute();
setUpdateState(true); setUpdateState(true);
} }
} }
private class UpdateProfileBannerImageTaskInternal extends UpdateProfileBannerImageTask { private class UpdateProfileBannerImageTaskInternal extends UpdateProfileBannerImageTask<UserProfileEditorFragment> {
public UpdateProfileBannerImageTaskInternal(final Context context, final UserKey accountKey, public UpdateProfileBannerImageTaskInternal(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean deleteImage) { final Uri imageUri, final boolean deleteImage) {
@ -573,21 +602,44 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableUser> result) { protected void afterExecute(final SingleResponse<ParcelableUser> result) {
super.onPostExecute(result); super.afterExecute(result);
setUpdateState(false); setUpdateState(false);
getUserInfo(); getUserInfo();
} }
@Override @Override
protected void onPreExecute() { protected void beforeExecute() {
super.onPreExecute(); super.beforeExecute();
setUpdateState(true); setUpdateState(true);
} }
} }
private class UpdateProfileImageTaskInternal extends UpdateProfileImageTask { private class UpdateProfileBackgroundImageTaskInternal extends UpdateProfileBackgroundImageTask<UserProfileEditorFragment> {
public UpdateProfileBackgroundImageTaskInternal(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean tile,
final boolean deleteImage) {
super(context, accountKey, imageUri, tile, deleteImage);
}
@Override
protected void afterExecute(final SingleResponse<ParcelableUser> result) {
super.afterExecute(result);
setUpdateState(false);
getUserInfo();
}
@Override
protected void beforeExecute() {
super.beforeExecute();
setUpdateState(true);
}
}
private class UpdateProfileImageTaskInternal extends UpdateProfileImageTask<UserProfileEditorFragment> {
public UpdateProfileImageTaskInternal(final Context context, final UserKey accountKey, public UpdateProfileImageTaskInternal(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean deleteImage) { final Uri imageUri, final boolean deleteImage) {
@ -595,8 +647,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableUser> result) { protected void afterExecute(SingleResponse<ParcelableUser> result) {
super.onPostExecute(result); super.afterExecute(result);
if (result != null && result.getData() != null) { if (result != null && result.getData() != null) {
displayUser(result.getData()); displayUser(result.getData());
} }
@ -604,8 +656,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
} }
@Override @Override
protected void onPreExecute() { protected void beforeExecute() {
super.onPreExecute(); super.beforeExecute();
setUpdateState(true); setUpdateState(true);
} }

View File

@ -1,177 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.loader;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.support.v4.content.AsyncTaskLoader;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.Constants;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class IntentActivitiesLoader extends AsyncTaskLoader<List<ResolveInfo>> implements Constants {
private PackageIntentReceiver mPackageObserver;
private final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
private final PackageManager mPackageManager;
private final Intent mIntent;
private final String[] mPackagesBlacklist;
private final int mFlags;
public IntentActivitiesLoader(final Context context, final Intent intent) {
this(context, intent, null, 0);
}
public IntentActivitiesLoader(final Context context, final Intent intent, final String[] packagesBlacklist,
final int flags) {
super(context);
mPackageManager = context.getPackageManager();
mIntent = intent;
mPackagesBlacklist = packagesBlacklist;
mFlags = flags;
}
@Override
public List<ResolveInfo> loadInBackground() {
if (mIntent == null) return Collections.emptyList();
final List<ResolveInfo> activities = mPackageManager.queryIntentActivities(mIntent, mFlags);
final List<ResolveInfo> result = new ArrayList<>();
for (final ResolveInfo activity : activities) {
final ActivityInfo activityInfo = activity.activityInfo;
if (mPackagesBlacklist == null || !ArrayUtils.contains(mPackagesBlacklist, activityInfo.packageName)) {
result.add(activity);
}
}
return result;
}
/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
// Stop monitoring for changes.
if (mPackageObserver != null) {
getContext().unregisterReceiver(mPackageObserver);
mPackageObserver = null;
}
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
// Start watching for changes in the app data.
if (mPackageObserver == null) {
mPackageObserver = new PackageIntentReceiver(this);
}
// Has something interesting in the configuration changed since we
// last built the app list?
final boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());
if (takeContentChanged() || configChange) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Helper for determining if the configuration has changed in an interesting
* way so we need to rebuild the app list.
*/
public static class InterestingConfigChanges {
final Configuration mLastConfiguration = new Configuration();
int mLastDensity;
boolean applyNewConfig(final Resources res) {
final int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
final boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
if (densityChanged
|| (configChanges & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
mLastDensity = res.getDisplayMetrics().densityDpi;
return true;
}
return false;
}
}
/**
* Helper class to look for interesting changes to the installed apps so
* that the loader can be updated.
*/
public static class PackageIntentReceiver extends BroadcastReceiver {
final IntentActivitiesLoader mLoader;
public PackageIntentReceiver(final IntentActivitiesLoader loader) {
mLoader = loader;
final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
filter.addDataScheme("package");
mLoader.getContext().registerReceiver(this, filter);
// Register for events related to sdcard installation.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
final IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mLoader.getContext().registerReceiver(this, sdFilter);
}
}
@Override
public void onReceive(final Context context, final Intent intent) {
// Tell the loader about the change.
mLoader.onContentChanged();
}
}
}

View File

@ -52,7 +52,8 @@ public abstract class AbsFriendshipOperationTask extends AbstractTask<AbsFriends
@Override @Override
protected final void beforeExecute(Arguments params) { protected final void beforeExecute() {
Arguments params = getParams();
twitter.addUpdatingRelationshipId(params.accountKey, params.userKey); twitter.addUpdatingRelationshipId(params.accountKey, params.userKey);
final FriendshipTaskEvent event = new FriendshipTaskEvent(action, params.accountKey, final FriendshipTaskEvent event = new FriendshipTaskEvent(action, params.accountKey,
params.userKey); params.userKey);

View File

@ -40,6 +40,7 @@ public abstract class ProgressSaveFileTask extends SaveFileTask {
super(context, source, destination, getMimeType); super(context, source, destination, getMimeType);
} }
@Override
protected void showProgress() { protected void showProgress() {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;
@ -53,6 +54,7 @@ public abstract class ProgressSaveFileTask extends SaveFileTask {
}); });
} }
@Override
protected void dismissProgress() { protected void dismissProgress() {
final Context context = getContext(); final Context context = getContext();
if (context == null) return; if (context == null) return;

View File

@ -0,0 +1,91 @@
package org.mariotaku.twidere.task;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.squareup.otto.Bus;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.User;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.message.ProfileUpdatedEvent;
import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.IOException;
import javax.inject.Inject;
/**
* Created by mariotaku on 16/3/11.
*/
public class UpdateProfileBackgroundImageTask<ResultHandler> extends AbstractTask<Object,
SingleResponse<ParcelableUser>, ResultHandler> implements Constants {
@Inject
protected Bus mBus;
private final UserKey mAccountKey;
private final Uri mImageUri;
private boolean mTile;
private final boolean mDeleteImage;
private final Context mContext;
public UpdateProfileBackgroundImageTask(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean tile,
final boolean deleteImage) {
//noinspection unchecked
GeneralComponentHelper.build(context).inject((UpdateProfileBackgroundImageTask<Object>) this);
mContext = context;
mAccountKey = accountKey;
mImageUri = imageUri;
mDeleteImage = deleteImage;
mTile = tile;
}
@Override
protected void afterExecute(SingleResponse<ParcelableUser> result) {
super.afterExecute(result);
if (result.hasData()) {
Utils.showOkMessage(mContext, R.string.profile_banner_image_updated, false);
mBus.post(new ProfileUpdatedEvent(result.getData()));
} else {
Utils.showErrorMessage(mContext, R.string.action_updating_profile_background_image,
result.getException(),
true);
}
}
@Override
protected SingleResponse<ParcelableUser> doLongOperation(final Object params) {
try {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey,
true);
TwitterWrapper.updateProfileBackgroundImage(mContext, twitter, mImageUri, mTile,
mDeleteImage);
// Wait for 5 seconds, see
// https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
Log.w(LOGTAG, e);
}
final User user = twitter.verifyCredentials();
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountKey));
} catch (TwitterException | IOException e) {
return SingleResponse.getInstance(e);
}
}
}

View File

@ -4,6 +4,10 @@ import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import com.squareup.otto.Bus;
import org.mariotaku.abstask.library.AbstractTask;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R; import org.mariotaku.twidere.R;
import org.mariotaku.twidere.api.twitter.Twitter; import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException; import org.mariotaku.twidere.api.twitter.TwitterException;
@ -16,13 +20,20 @@ import org.mariotaku.twidere.model.util.ParcelableUserUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory; import org.mariotaku.twidere.util.TwitterAPIFactory;
import org.mariotaku.twidere.util.TwitterWrapper; import org.mariotaku.twidere.util.TwitterWrapper;
import org.mariotaku.twidere.util.Utils; import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.FileNotFoundException; import java.io.IOException;
import javax.inject.Inject;
/** /**
* Created by mariotaku on 16/3/11. * Created by mariotaku on 16/3/11.
*/ */
public class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Object, SingleResponse<ParcelableUser>> { public class UpdateProfileBannerImageTask<ResultHandler> extends AbstractTask<Object,
SingleResponse<ParcelableUser>, ResultHandler> implements Constants {
@Inject
protected Bus mBus;
private final UserKey mAccountKey; private final UserKey mAccountKey;
private final Uri mImageUri; private final Uri mImageUri;
@ -31,7 +42,8 @@ public class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Objec
public UpdateProfileBannerImageTask(final Context context, final UserKey accountKey, public UpdateProfileBannerImageTask(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean deleteImage) { final Uri imageUri, final boolean deleteImage) {
super(context); //noinspection unchecked
GeneralComponentHelper.build(context).inject((UpdateProfileBannerImageTask<Object>) this);
mContext = context; mContext = context;
mAccountKey = accountKey; mAccountKey = accountKey;
mImageUri = imageUri; mImageUri = imageUri;
@ -39,11 +51,11 @@ public class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Objec
} }
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableUser> result) { protected void afterExecute(final SingleResponse<ParcelableUser> result) {
super.onPostExecute(result); super.afterExecute(result);
if (result.hasData()) { if (result.hasData()) {
Utils.showOkMessage(mContext, R.string.profile_banner_image_updated, false); Utils.showOkMessage(mContext, R.string.profile_banner_image_updated, false);
bus.post(new ProfileUpdatedEvent(result.getData())); mBus.post(new ProfileUpdatedEvent(result.getData()));
} else { } else {
Utils.showErrorMessage(mContext, R.string.action_updating_profile_banner_image, result.getException(), Utils.showErrorMessage(mContext, R.string.action_updating_profile_banner_image, result.getException(),
true); true);
@ -51,7 +63,7 @@ public class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Objec
} }
@Override @Override
protected SingleResponse<ParcelableUser> doInBackground(final Object... params) { protected SingleResponse<ParcelableUser> doLongOperation(final Object params) {
try { try {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey, final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey,
true); true);
@ -65,7 +77,7 @@ public class UpdateProfileBannerImageTask extends ManagedAsyncTask<Object, Objec
} }
final User user = twitter.verifyCredentials(); final User user = twitter.verifyCredentials();
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountKey)); return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountKey));
} catch (TwitterException | FileNotFoundException e) { } catch (TwitterException | IOException e) {
return SingleResponse.getInstance(e); return SingleResponse.getInstance(e);
} }
} }

View File

@ -206,7 +206,7 @@ public abstract class GetActivitiesTask extends AbstractTask<RefreshTaskParam, O
@UiThread @UiThread
@Override @Override
public void beforeExecute(RefreshTaskParam params) { public void beforeExecute() {
bus.post(new GetActivitiesTaskEvent(getContentUri(), true, null)); bus.post(new GetActivitiesTaskEvent(getContentUri(), true, null));
} }
} }

View File

@ -93,7 +93,7 @@ public abstract class GetStatusesTask extends AbstractTask<RefreshTaskParam,
} }
@Override @Override
protected void beforeExecute(RefreshTaskParam refreshTaskParam) { protected void beforeExecute() {
bus.post(new GetStatusesTaskEvent(getContentUri(), true, null)); bus.post(new GetStatusesTaskEvent(getContentUri(), true, null));
} }

View File

@ -110,12 +110,15 @@ import org.mariotaku.twidere.task.GetSavedSearchesTask;
import org.mariotaku.twidere.task.ManagedAsyncTask; import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.ReportSpamAndBlockTask; import org.mariotaku.twidere.task.ReportSpamAndBlockTask;
import org.mariotaku.twidere.task.twitter.GetActivitiesTask; import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
import java.io.FileNotFoundException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.inject.Inject;
import edu.tsinghua.hotmobi.HotMobiLogger; import edu.tsinghua.hotmobi.HotMobiLogger;
import edu.tsinghua.hotmobi.model.TimelineType; import edu.tsinghua.hotmobi.model.TimelineType;
import edu.tsinghua.hotmobi.model.TweetEvent; import edu.tsinghua.hotmobi.model.TweetEvent;
@ -552,7 +555,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
return mUpdatingRelationshipIds.contains(ParcelableUser.calculateHashCode(accountId, userId)); return mUpdatingRelationshipIds.contains(ParcelableUser.calculateHashCode(accountId, userId));
} }
public static class UpdateProfileImageTask extends ManagedAsyncTask<Object, Object, SingleResponse<ParcelableUser>> { public static class UpdateProfileImageTask<ResultHandler> extends AbstractTask<Object,
SingleResponse<ParcelableUser>, ResultHandler> {
@Inject
protected Bus mBus;
private final UserKey mAccountKey; private final UserKey mAccountKey;
private final Uri mImageUri; private final Uri mImageUri;
@ -561,7 +568,8 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
public UpdateProfileImageTask(final Context context, final UserKey accountKey, public UpdateProfileImageTask(final Context context, final UserKey accountKey,
final Uri imageUri, final boolean deleteImage) { final Uri imageUri, final boolean deleteImage) {
super(context); //noinspection unchecked
GeneralComponentHelper.build(context).inject((UpdateProfileImageTask<Object>) this);
this.mContext = context; this.mContext = context;
this.mAccountKey = accountKey; this.mAccountKey = accountKey;
this.mImageUri = imageUri; this.mImageUri = imageUri;
@ -569,7 +577,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
} }
@Override @Override
protected SingleResponse<ParcelableUser> doInBackground(final Object... params) { protected SingleResponse<ParcelableUser> doLongOperation(final Object params) {
try { try {
final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey, true); final Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, mAccountKey, true);
TwitterWrapper.updateProfileImage(mContext, twitter, mImageUri, mDeleteImage); TwitterWrapper.updateProfileImage(mContext, twitter, mImageUri, mDeleteImage);
@ -582,17 +590,17 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
} }
final User user = twitter.verifyCredentials(); final User user = twitter.verifyCredentials();
return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountKey)); return SingleResponse.getInstance(ParcelableUserUtils.fromUser(user, mAccountKey));
} catch (TwitterException | FileNotFoundException e) { } catch (TwitterException | IOException e) {
return SingleResponse.getInstance(e); return SingleResponse.getInstance(e);
} }
} }
@Override @Override
protected void onPostExecute(final SingleResponse<ParcelableUser> result) { protected void afterExecute(SingleResponse<ParcelableUser> result) {
super.onPostExecute(result); super.afterExecute(result);
if (result.hasData()) { if (result.hasData()) {
Utils.showOkMessage(mContext, R.string.profile_image_updated, false); Utils.showOkMessage(mContext, R.string.profile_image_updated, false);
bus.post(new ProfileUpdatedEvent(result.getData())); mBus.post(new ProfileUpdatedEvent(result.getData()));
} else { } else {
Utils.showErrorMessage(mContext, R.string.action_updating_profile_image, result.getException(), true); Utils.showErrorMessage(mContext, R.string.action_updating_profile_image, result.getException(), true);
} }

View File

@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -35,6 +36,7 @@ import org.mariotaku.twidere.model.util.ParcelableLocationUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random;
import static android.text.TextUtils.isEmpty; import static android.text.TextUtils.isEmpty;
@ -195,6 +197,27 @@ public class IntentUtils implements Constants {
} }
} }
public static String getDefaultBrowserPackage(Context context) {
Uri.Builder builder = new Uri.Builder();
builder.scheme(SCHEME_HTTP);
StringBuilder sb = new StringBuilder();
Random random = new Random();
int range = 'z' - 'a';
for (int i = 0; i < 20; i++) {
sb.append((char) ('a' + (Math.abs(random.nextInt()) % range)));
}
sb.append(".com");
builder.authority(sb.toString());
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
intent.addCategory(Intent.CATEGORY_BROWSABLE);
List<ResolveInfo> info = context.getPackageManager().queryIntentActivities(intent, 0);
if (info.isEmpty()) return null;
for (ResolveInfo item : info) {
if (item.isDefault) return item.activityInfo.packageName;
}
return info.get(0).activityInfo.packageName;
}
public static void openMediaDirectly(@NonNull final Context context, public static void openMediaDirectly(@NonNull final Context context,
@Nullable final UserKey accountKey, @Nullable final UserKey accountKey,
final ParcelableDirectMessage message, final ParcelableMedia current, final ParcelableDirectMessage message, final ParcelableMedia current,

View File

@ -222,12 +222,8 @@ public class MediaLoaderWrapper implements Constants {
} }
public void displayImage(final ImageView view, final String url, DisplayImageOptions options) { public void displayImage(final ImageView view, final String url) {
mImageLoader.displayImage(url, view, options); mImageLoader.displayImage(url, view);
}
public DisplayImageOptions getProfileImageDisplayOptions() {
return mProfileImageDisplayOptions;
} }
public void displayProfileImage(final ImageView view, final String url, final ImageLoadingListener listener) { public void displayProfileImage(final ImageView view, final String url, final ImageLoadingListener listener) {

View File

@ -19,13 +19,16 @@
package org.mariotaku.twidere.util; package org.mariotaku.twidere.util;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.util.SimpleArrayMap; import android.support.v4.util.SimpleArrayMap;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.webkit.MimeTypeMap;
import org.mariotaku.restfu.http.ContentType;
import org.mariotaku.restfu.http.mime.FileBody; import org.mariotaku.restfu.http.mime.FileBody;
import org.mariotaku.twidere.Constants; import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.api.twitter.Twitter; import org.mariotaku.twidere.api.twitter.Twitter;
@ -44,6 +47,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -174,13 +178,34 @@ public class TwitterWrapper implements Constants {
public static void updateProfileBannerImage(final Context context, final Twitter twitter, public static void updateProfileBannerImage(final Context context, final Twitter twitter,
final Uri imageUri, final boolean deleteImage) final Uri imageUri, final boolean deleteImage)
throws FileNotFoundException, TwitterException { throws IOException, TwitterException {
InputStream is = null; FileBody fileBody = null;
try { try {
is = context.getContentResolver().openInputStream(imageUri); fileBody = getFileBody(context, imageUri);
twitter.updateProfileBannerImage(new FileBody(is, "image", -1, null)); twitter.updateProfileBannerImage(fileBody);
} finally { } finally {
Utils.closeSilently(is); Utils.closeSilently(fileBody);
if (deleteImage && "file".equals(imageUri.getScheme())) {
final File file = new File(imageUri.getPath());
if (!file.delete()) {
Log.w(LOGTAG, String.format("Unable to delete %s", file));
}
}
}
}
public static void updateProfileBackgroundImage(@NonNull final Context context,
@NonNull final Twitter twitter,
@NonNull final Uri imageUri,
final boolean tile,
final boolean deleteImage)
throws IOException, TwitterException {
FileBody fileBody = null;
try {
fileBody = getFileBody(context, imageUri);
twitter.updateProfileBackgroundImage(fileBody, tile);
} finally {
Utils.closeSilently(fileBody);
if (deleteImage && "file".equals(imageUri.getScheme())) { if (deleteImage && "file".equals(imageUri.getScheme())) {
final File file = new File(imageUri.getPath()); final File file = new File(imageUri.getPath());
if (!file.delete()) { if (!file.delete()) {
@ -192,13 +217,13 @@ public class TwitterWrapper implements Constants {
public static User updateProfileImage(final Context context, final Twitter twitter, public static User updateProfileImage(final Context context, final Twitter twitter,
final Uri imageUri, final boolean deleteImage) final Uri imageUri, final boolean deleteImage)
throws FileNotFoundException, TwitterException { throws IOException, TwitterException {
InputStream is = null; FileBody fileBody = null;
try { try {
is = context.getContentResolver().openInputStream(imageUri); fileBody = getFileBody(context, imageUri);
return twitter.updateProfileImage(new FileBody(is, "image", -1, null)); return twitter.updateProfileImage(fileBody);
} finally { } finally {
Utils.closeSilently(is); Utils.closeSilently(fileBody);
if (deleteImage && "file".equals(imageUri.getScheme())) { if (deleteImage && "file".equals(imageUri.getScheme())) {
final File file = new File(imageUri.getPath()); final File file = new File(imageUri.getPath());
if (!file.delete()) { if (!file.delete()) {
@ -208,6 +233,33 @@ public class TwitterWrapper implements Constants {
} }
} }
private static FileBody getFileBody(Context context, Uri imageUri) throws IOException {
final ContentResolver cr = context.getContentResolver();
String type = cr.getType(imageUri);
if (type == null) {
type = Utils.getImageMimeType(cr, imageUri);
}
final ContentType contentType;
final String extension;
if (type != null) {
contentType = ContentType.parse(type);
extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(type);
} else {
contentType = null;
extension = null;
}
final InputStream is = cr.openInputStream(imageUri);
if (is == null) throw new FileNotFoundException(imageUri.toString());
final String fileName;
if (extension != null) {
fileName = "image." + extension;
} else {
fileName = "image";
}
return new FileBody(is, fileName, is.available(), contentType);
}
public static final class MessageListResponse extends TwitterListResponse<DirectMessage> { public static final class MessageListResponse extends TwitterListResponse<DirectMessage> {
public MessageListResponse(final UserKey accountKey, final Exception exception) { public MessageListResponse(final UserKey accountKey, final Exception exception) {

View File

@ -41,7 +41,6 @@ import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuff.Mode;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable; import android.graphics.drawable.NinePatchDrawable;
@ -75,13 +74,10 @@ import android.support.v4.view.GravityCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.system.ErrnoException; import android.system.ErrnoException;
import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.text.format.Time; import android.text.format.Time;
import android.text.style.CharacterStyle;
import android.text.style.StyleSpan;
import android.transition.Transition; import android.transition.Transition;
import android.transition.TransitionInflater; import android.transition.TransitionInflater;
import android.util.Log; import android.util.Log;
@ -1239,6 +1235,23 @@ public final class Utils implements Constants {
return o.outMimeType; return o.outMimeType;
} }
@Nullable
public static String getImageMimeType(ContentResolver cr, final Uri uri) {
if (uri == null) return null;
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
InputStream is = null;
try {
is = cr.openInputStream(uri);
BitmapFactory.decodeStream(is, null, o);
return o.outMimeType;
} catch (IOException e) {
return null;
} finally {
closeSilently(is);
}
}
public static String getImagePathFromUri(final Context context, final Uri uri) { public static String getImagePathFromUri(final Context context, final Uri uri) {
if (context == null || uri == null) return null; if (context == null || uri == null) return null;
@ -1290,28 +1303,6 @@ public final class Utils implements Constants {
return new File(context.getCacheDir(), cacheDirName); return new File(context.getCacheDir(), cacheDirName);
} }
public static CharSequence getKeywordBoldedText(final CharSequence orig, final String... keywords) {
return getKeywordHighlightedText(orig, new StyleSpan(Typeface.BOLD), keywords);
}
public static CharSequence getKeywordHighlightedText(final CharSequence orig, final CharacterStyle style,
final String... keywords) {
if (keywords == null || keywords.length == 0 || orig == null) return orig;
final SpannableStringBuilder sb = SpannableStringBuilder.valueOf(orig);
final StringBuilder patternBuilder = new StringBuilder();
for (int i = 0, j = keywords.length; i < j; i++) {
if (i != 0) {
patternBuilder.append('|');
}
patternBuilder.append(Pattern.quote(keywords[i]));
}
final Matcher m = Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE).matcher(orig);
while (m.find()) {
sb.setSpan(style, m.start(), m.end(), SpannableStringBuilder.SPAN_INCLUSIVE_INCLUSIVE);
}
return sb;
}
public static String getLinkHighlightingStyleName(final Context context) { public static String getLinkHighlightingStyleName(final Context context) {
if (context == null) return null; if (context == null) return null;
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE); final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
@ -1785,7 +1776,7 @@ public final class Utils implements Constants {
if (absListView == null) return; if (absListView == null) return;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
if (absListView instanceof ListView) { if (absListView instanceof ListView) {
final ListView listView = ((ListView) absListView); final ListView listView = (ListView) absListView;
listView.setSelectionFromTop(position, offset); listView.setSelectionFromTop(position, offset);
} else { } else {
absListView.setSelection(position); absListView.setSelection(position);
@ -1794,7 +1785,7 @@ public final class Utils implements Constants {
} else { } else {
stopListView(absListView); stopListView(absListView);
if (absListView instanceof ListView) { if (absListView instanceof ListView) {
final ListView listView = ((ListView) absListView); final ListView listView = (ListView) absListView;
listView.setSelectionFromTop(position, offset); listView.setSelectionFromTop(position, offset);
} else { } else {
absListView.setSelection(position); absListView.setSelection(position);
@ -1929,6 +1920,9 @@ public final class Utils implements Constants {
.getMessage(context, te.getStatusCode(), te.getErrorCode()); .getMessage(context, te.getStatusCode(), te.getErrorCode());
message = context.getString(R.string.error_message_with_action, action, msg != null ? msg message = context.getString(R.string.error_message_with_action, action, msg != null ? msg
: trimLineBreak(te.getMessage())); : trimLineBreak(te.getMessage()));
} else if (!TextUtils.isEmpty(te.getErrorMessage())) {
message = context.getString(R.string.error_message_with_action, action,
trimLineBreak(te.getErrorMessage()));
} else if (te.getCause() instanceof SSLException) { } else if (te.getCause() instanceof SSLException) {
final String msg = te.getCause().getMessage(); final String msg = te.getCause().getMessage();
if (msg != null && msg.contains("!=")) { if (msg != null && msg.contains("!=")) {
@ -2148,8 +2142,8 @@ public final class Utils implements Constants {
public static boolean isCustomConsumerKeySecret(String consumerKey, String consumerSecret) { public static boolean isCustomConsumerKeySecret(String consumerKey, String consumerSecret) {
if (TextUtils.isEmpty(consumerKey) || TextUtils.isEmpty(consumerSecret)) return false; if (TextUtils.isEmpty(consumerKey) || TextUtils.isEmpty(consumerSecret)) return false;
return (!TWITTER_CONSUMER_KEY.equals(consumerKey) && !TWITTER_CONSUMER_SECRET.equals(consumerKey)) return !TWITTER_CONSUMER_KEY.equals(consumerKey) && !TWITTER_CONSUMER_SECRET.equals(consumerKey)
&& (!TWITTER_CONSUMER_KEY_LEGACY.equals(consumerKey) && !TWITTER_CONSUMER_SECRET_LEGACY.equals(consumerSecret)); && !TWITTER_CONSUMER_KEY_LEGACY.equals(consumerKey) && !TWITTER_CONSUMER_SECRET_LEGACY.equals(consumerSecret);
} }
public static boolean isStreamingEnabled() { public static boolean isStreamingEnabled() {

View File

@ -32,9 +32,9 @@ import org.mariotaku.twidere.adapter.ComposeAutoCompleteAdapter;
import org.mariotaku.twidere.adapter.DraftsAdapter; import org.mariotaku.twidere.adapter.DraftsAdapter;
import org.mariotaku.twidere.adapter.DummyItemAdapter; import org.mariotaku.twidere.adapter.DummyItemAdapter;
import org.mariotaku.twidere.adapter.UserAutoCompleteAdapter; import org.mariotaku.twidere.adapter.UserAutoCompleteAdapter;
import org.mariotaku.twidere.fragment.BaseFiltersFragment;
import org.mariotaku.twidere.fragment.BaseListFragment; import org.mariotaku.twidere.fragment.BaseListFragment;
import org.mariotaku.twidere.fragment.BasePreferenceFragment; import org.mariotaku.twidere.fragment.BasePreferenceFragment;
import org.mariotaku.twidere.fragment.BaseFiltersFragment;
import org.mariotaku.twidere.fragment.BaseSupportDialogFragment; import org.mariotaku.twidere.fragment.BaseSupportDialogFragment;
import org.mariotaku.twidere.fragment.BaseSupportFragment; import org.mariotaku.twidere.fragment.BaseSupportFragment;
import org.mariotaku.twidere.fragment.MessagesConversationFragment; import org.mariotaku.twidere.fragment.MessagesConversationFragment;
@ -51,10 +51,13 @@ import org.mariotaku.twidere.task.AbsFriendshipOperationTask;
import org.mariotaku.twidere.task.GetDirectMessagesTask; import org.mariotaku.twidere.task.GetDirectMessagesTask;
import org.mariotaku.twidere.task.GetTrendsTask; import org.mariotaku.twidere.task.GetTrendsTask;
import org.mariotaku.twidere.task.ManagedAsyncTask; import org.mariotaku.twidere.task.ManagedAsyncTask;
import org.mariotaku.twidere.task.UpdateProfileBackgroundImageTask;
import org.mariotaku.twidere.task.UpdateProfileBannerImageTask;
import org.mariotaku.twidere.task.twitter.GetActivitiesTask; import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
import org.mariotaku.twidere.task.twitter.GetStatusesTask; import org.mariotaku.twidere.task.twitter.GetStatusesTask;
import org.mariotaku.twidere.text.util.EmojiEditableFactory; import org.mariotaku.twidere.text.util.EmojiEditableFactory;
import org.mariotaku.twidere.text.util.EmojiSpannableFactory; import org.mariotaku.twidere.text.util.EmojiSpannableFactory;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MultiSelectEventHandler; import org.mariotaku.twidere.util.MultiSelectEventHandler;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -138,4 +141,10 @@ public interface GeneralComponent {
void inject(ParcelableStatusLoader loader); void inject(ParcelableStatusLoader loader);
void inject(GetTrendsTask task); void inject(GetTrendsTask task);
void inject(UpdateProfileBackgroundImageTask<Object> task);
void inject(UpdateProfileBannerImageTask<Object> task);
void inject(AsyncTwitterWrapper.UpdateProfileImageTask<Object> task);
} }

View File

@ -0,0 +1,21 @@
package org.mariotaku.twidere.util.theme;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.afollestad.appthemeengine.Config;
import com.afollestad.appthemeengine.viewprocessors.ViewProcessor;
import com.rengwuxian.materialedittext.MaterialEditText;
/**
* Created by mariotaku on 16/4/1.
*/
public class MaterialEditTextViewProcessor implements ViewProcessor<MaterialEditText, Void> {
@Override
public void process(@NonNull Context context, @Nullable String key, @Nullable MaterialEditText target, @Nullable Void extra) {
if (target == null) return;
int accentColor = Config.accentColor(context, key);
target.setPrimaryColor(accentColor);
}
}

View File

@ -40,6 +40,9 @@ public class HomeDrawerLayout extends DrawerLayout implements ViewInterface {
} }
private void init(Context context, @Nullable ATEActivity keyContext) { private void init(Context context, @Nullable ATEActivity keyContext) {
if (keyContext == null && context instanceof ATEActivity) {
keyContext = (ATEActivity) context;
}
final String key = keyContext != null ? keyContext.getATEKey() : null; final String key = keyContext != null ? keyContext.getATEKey() : null;
if (Config.coloredStatusBar(context, key)) { if (Config.coloredStatusBar(context, key)) {
// Sets the status bar overlayed by the DrawerLayout // Sets the status bar overlayed by the DrawerLayout

View File

@ -1,53 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view.themed;
import android.content.Context;
import android.content.res.ColorStateList;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import com.rengwuxian.materialedittext.MaterialEditText;
import org.mariotaku.twidere.view.iface.IThemeBackgroundTintView;
/**
* TextView with tint background support
*/
public class BackgroundTintMaterialEditText extends MaterialEditText implements IThemeBackgroundTintView {
public BackgroundTintMaterialEditText(Context context) {
super(context);
}
public BackgroundTintMaterialEditText(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BackgroundTintMaterialEditText(Context context, AttributeSet attrs, int style) {
super(context, attrs, style);
}
@Override
public void setBackgroundTintColor(@NonNull ColorStateList color) {
setPrimaryColor(color.getDefaultColor());
}
}

View File

@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@ -24,7 +24,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:padding="@dimen/element_spacing_normal"> android:padding="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -39,7 +39,7 @@
app:met_floatingLabelText="@string/name" app:met_floatingLabelText="@string/name"
app:met_maxCharacters="25"/> app:met_maxCharacters="25"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/description" android:id="@+id/description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -59,7 +59,8 @@
android:layout_height="@dimen/element_size_mlarge" android:layout_height="@dimen/element_size_mlarge"
android:layout_gravity="center" android:layout_gravity="center"
android:foreground="?selectableItemBackground" android:foreground="?selectableItemBackground"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"
tools:src="@drawable/ic_launcher_web"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -81,7 +82,9 @@
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/element_spacing_normal"> android:padding="@dimen/element_spacing_normal"
android:visibility="gone"
tools:visibility="visible">
<org.mariotaku.twidere.view.ForegroundImageView <org.mariotaku.twidere.view.ForegroundImageView
android:id="@+id/profile_banner" android:id="@+id/profile_banner"
@ -89,7 +92,8 @@
android:layout_height="@dimen/element_size_mlarge" android:layout_height="@dimen/element_size_mlarge"
android:layout_gravity="center" android:layout_gravity="center"
android:foreground="?selectableItemBackground" android:foreground="?selectableItemBackground"
android:scaleType="centerCrop"/> android:scaleType="centerCrop"
tools:src="@drawable/nyan_stars_background_tile"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -103,6 +107,37 @@
android:textStyle="bold"/> android:textStyle="bold"/>
</LinearLayout> </LinearLayout>
<LinearLayout
android:id="@+id/edit_profile_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.ForegroundImageView
android:id="@+id/profile_background"
android:layout_width="@dimen/element_size_mlarge"
android:layout_height="@dimen/element_size_mlarge"
android:layout_gravity="center"
android:foreground="?selectableItemBackground"
android:scaleType="centerCrop"
tools:src="@drawable/nyan_stars_background_tile"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:text="@string/profile_background"
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
<Space <Space
@ -116,7 +151,7 @@
android:orientation="vertical" android:orientation="vertical"
android:padding="@dimen/element_spacing_normal"> android:padding="@dimen/element_spacing_normal">
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/name" android:id="@+id/name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -125,9 +160,11 @@
app:met_baseColor="?android:textColorPrimary" app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal" app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/name" app:met_floatingLabelText="@string/name"
app:met_maxCharacters="20"/> app:met_maxCharacters="20"
app:met_primaryColor="?colorAccent"
tools:text="TwidereProject"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/description" android:id="@+id/description"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -137,9 +174,11 @@
app:met_baseColor="?android:textColorPrimary" app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal" app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/description" app:met_floatingLabelText="@string/description"
app:met_maxCharacters="160"/> app:met_maxCharacters="160"
app:met_primaryColor="?colorAccent"
tools:text="@string/sample_status_text"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/location" android:id="@+id/location"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -148,9 +187,11 @@
app:met_baseColor="?android:textColorPrimary" app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal" app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/location" app:met_floatingLabelText="@string/location"
app:met_maxCharacters="30"/> app:met_maxCharacters="30"
app:met_primaryColor="?colorAccent"
tools:text="Earth"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText <com.rengwuxian.materialedittext.MaterialEditText
android:id="@+id/url" android:id="@+id/url"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -159,7 +200,9 @@
app:met_baseColor="?android:textColorPrimary" app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal" app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/url" app:met_floatingLabelText="@string/url"
app:met_maxCharacters="100"/> app:met_maxCharacters="100"
app:met_primaryColor="?colorAccent"
tools:text="https://github.com/TwidereProject/"/>
</LinearLayout> </LinearLayout>
<Space <Space
@ -185,7 +228,8 @@
android:id="@+id/link_color" android:id="@+id/link_color"
android:layout_width="@dimen/element_size_normal" android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal" android:layout_height="@dimen/element_size_normal"
android:layout_weight="0"/> android:layout_weight="0"
tools:color="@color/branding_color"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -214,7 +258,8 @@
android:id="@+id/background_color" android:id="@+id/background_color"
android:layout_width="@dimen/element_size_normal" android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal" android:layout_height="@dimen/element_size_normal"
android:layout_weight="0"/> android:layout_weight="0"
tools:color="@color/branding_color"/>
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -303,6 +303,7 @@
<string name="action_updating_profile">updating profile</string> <string name="action_updating_profile">updating profile</string>
<string name="action_updating_profile_image">updating profile image</string> <string name="action_updating_profile_image">updating profile image</string>
<string name="action_updating_profile_banner_image">updating profile header image</string> <string name="action_updating_profile_banner_image">updating profile header image</string>
<string name="action_updating_profile_background_image">updating profile background image</string>
<string name="action_removing_profile_banner_image">removing profile header image</string> <string name="action_removing_profile_banner_image">removing profile header image</string>
<string name="action_updating_details">updating details</string> <string name="action_updating_details">updating details</string>
<string name="action_blocking">blocking</string> <string name="action_blocking">blocking</string>
@ -588,6 +589,7 @@
<string name="function">Function</string> <string name="function">Function</string>
<string name="replies">Replies</string> <string name="replies">Replies</string>
<string name="profile_banner">Profile banner</string> <string name="profile_banner">Profile banner</string>
<string name="profile_background">Profile background</string>
<string name="profile">Profile</string> <string name="profile">Profile</string>
<string name="listed">Listed</string> <string name="listed">Listed</string>
<string name="state_blocking">Blocking</string> <string name="state_blocking">Blocking</string>