1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-01-31 17:04:59 +01:00

moved image picker to independent component

This commit is contained in:
Mariotaku Lee 2015-06-18 21:30:46 +08:00
parent 9d73a4bb3a
commit 6cde1e4877
13 changed files with 185 additions and 550 deletions

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip

View File

@ -57,6 +57,7 @@ configurations {
dependencies {
// wearApp project(':twidere.wear')
apt 'com.bluelinelabs:logansquare-compiler:1.1.0'
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:support-v13:22.2.0'
compile 'com.android.support:appcompat-v7:22.2.0'
@ -88,6 +89,8 @@ dependencies {
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4'
compile 'com.makeramen:roundedimageview:2.1.0'
compile 'com.soundcloud.android:android-crop:1.0.0@aar'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1'
compile 'com.github.mariotaku:PickNCrop:76563fae81'
googleCompile 'com.google.android.gms:play-services-maps:7.5.0'
googleCompile 'com.google.maps.android:android-maps-utils:0.3.4'
fdroidCompile 'org.osmdroid:osmdroid-android:4.3'

View File

@ -316,7 +316,7 @@
</intent-filter>
</activity>
<activity
android:name=".activity.support.ImagePickerActivity"
android:name=".activity.support.ThemedImagePickerActivity"
android:exported="false"
android:theme="@style/Theme.Twidere.Light.NoDisplay"
android:windowSoftInputMode="adjustResize">

View File

@ -736,9 +736,8 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
if (s instanceof Spannable && count == 1 && before == 0) {
final ImageSpan[] imageSpans = ((Spannable) s).getSpans(start, start + count, ImageSpan.class);
if (imageSpans.length == 1) {
final Intent intent = new Intent(ComposeActivity.this, ImagePickerActivity.class);
intent.setAction(ImagePickerActivity.INTENT_ACTION_GET_IMAGE);
intent.setData(Uri.parse(imageSpans[0].getSource()));
final Intent intent = ThemedImagePickerActivity.withThemed(ComposeActivity.this)
.getImage(Uri.parse(imageSpans[0].getSource())).build();
startActivityForResult(intent, REQUEST_PICK_IMAGE);
((Spannable) s).setSpan(new MarkForDeleteSpan(), start, start + count,
Spanned.SPAN_INCLUSIVE_INCLUSIVE);
@ -1050,8 +1049,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
}
private boolean pickImage() {
final Intent intent = new Intent(this, ImagePickerActivity.class);
intent.setAction(ImagePickerActivity.INTENT_ACTION_PICK_IMAGE);
final Intent intent = ThemedImagePickerActivity.withThemed(this).pickImage().build();
startActivityForResult(intent, REQUEST_PICK_IMAGE);
return true;
}
@ -1177,8 +1175,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
}
private boolean takePhoto() {
final Intent intent = new Intent(this, ImagePickerActivity.class);
intent.setAction(ImagePickerActivity.INTENT_ACTION_TAKE_PHOTO);
final Intent intent = ThemedImagePickerActivity.withThemed(this).takePhoto().build();
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
return true;
}

View File

@ -1,369 +0,0 @@
package org.mariotaku.twidere.activity.support;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.github.ooxi.jdatauri.DataUri;
import com.soundcloud.android.crop.Crop;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.ImageCropperActivity;
import org.mariotaku.twidere.fragment.ProgressDialogFragment;
import org.mariotaku.twidere.fragment.support.BaseSupportDialogFragment;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.util.RestFuNetworkStreamDownloader;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import static android.os.Environment.getExternalStorageState;
public class ImagePickerActivity extends ThemedFragmentActivity {
public static final int REQUEST_PICK_IMAGE = 101;
public static final int REQUEST_TAKE_PHOTO = 102;
public static final int REQUEST_CROP = 103;
public static final String INTENT_ACTION_TAKE_PHOTO = INTENT_PACKAGE_PREFIX + "TAKE_PHOTO";
public static final String INTENT_ACTION_PICK_IMAGE = INTENT_PACKAGE_PREFIX + "PICK_IMAGE";
public static final String INTENT_ACTION_GET_IMAGE = INTENT_PACKAGE_PREFIX + "GET_IMAGE";
public static final String EXTRA_ASPECT_X = "aspect_x";
public static final String EXTRA_ASPECT_Y = "aspect_y";
public static final String EXTRA_MAX_WIDTH = "max_width";
public static final String EXTRA_MAX_HEIGHT = "max_height";
private Uri mTempPhotoUri;
private CopyImageTask mTask;
private Runnable mImageSelectedRunnable;
@Override
public int getThemeColor() {
return ThemeUtils.getUserAccentColor(this);
}
@Override
public int getThemeResourceId() {
return ThemeUtils.getNoDisplayThemeResource(this);
}
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
if (resultCode != RESULT_OK) {
setResult(RESULT_CANCELED);
finish();
return;
}
final boolean needsCrop;
final Uri src;
switch (requestCode) {
case REQUEST_PICK_IMAGE: {
needsCrop = true;
src = intent.getData();
break;
}
case REQUEST_TAKE_PHOTO: {
needsCrop = true;
src = mTempPhotoUri;
break;
}
case REQUEST_CROP: {
needsCrop = false;
src = mTempPhotoUri;
break;
}
default: {
finish();
return;
}
}
if (src == null) return;
mImageSelectedRunnable = new Runnable() {
@Override
public void run() {
imageSelected(src, needsCrop, !needsCrop);
}
};
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (mImageSelectedRunnable != null) {
runOnUiThread(mImageSelectedRunnable);
}
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Intent intent = getIntent();
final String action = intent.getAction();
if (INTENT_ACTION_TAKE_PHOTO.equals(action)) {
takePhoto();
} else if (INTENT_ACTION_PICK_IMAGE.equals(action)) {
pickImage();
} else if (INTENT_ACTION_GET_IMAGE.equals(action)) {
imageSelected(intent.getData(), true, false);
} else {
new ImageSourceDialogFragment().show(getSupportFragmentManager(), "image_source");
}
}
@Override
protected void onStop() {
mImageSelectedRunnable = null;
super.onStop();
}
private void imageSelected(final Uri uri, final boolean needsCrop, final boolean deleteSource) {
final CopyImageTask task = mTask;
if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) return;
mTask = new CopyImageTask(this, uri, needsCrop, deleteSource);
mTask.execute();
}
private void pickImage() {
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
startActivityForResult(intent, REQUEST_PICK_IMAGE);
} catch (final ActivityNotFoundException ignored) {
}
}
private void takePhoto() {
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final Uri uri = createTempImageUri();
mTempPhotoUri = uri;
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
try {
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
} catch (final ActivityNotFoundException ignored) {
takePhotoFallback(mTempPhotoUri);
}
}
private Uri createTempImageUri() {
if (!getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return null;
final File extCacheDir = getExternalCacheDir();
final File file;
try {
file = File.createTempFile("temp_image_", ".tmp", extCacheDir);
} catch (final IOException e) {
return null;
}
return Uri.fromFile(file);
}
private boolean takePhotoFallback(Uri uri) {
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
try {
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
} catch (final ActivityNotFoundException e) {
return false;
}
return true;
}
private static class CopyImageTask extends AsyncTask<Object, Object, SingleResponse<File>> {
private static final String TAG_COPYING_IMAGE = "copying_image";
private final ImagePickerActivity mActivity;
private final Uri mUri;
private final boolean mNeedsCrop;
private final boolean mDeleteSource;
public CopyImageTask(final ImagePickerActivity activity, final Uri uri, final boolean needsCrop, final boolean deleteSource) {
mActivity = activity;
mUri = uri;
mNeedsCrop = needsCrop;
mDeleteSource = deleteSource;
}
@Override
protected SingleResponse<File> doInBackground(final Object... params) {
final ContentResolver cr = mActivity.getContentResolver();
InputStream is = null;
OutputStream os = null;
try {
final File cacheDir = mActivity.getCacheDir();
final Uri uri = this.mUri;
final String mimeType;
final String scheme = uri.getScheme();
if (SCHEME_HTTP.equals(scheme) || SCHEME_HTTPS.equals(scheme)) {
final NetworkStreamDownloader downloader = new RestFuNetworkStreamDownloader(mActivity);
final NetworkStreamDownloader.DownloadResult result = downloader.get(uri);
is = result.stream;
mimeType = result.mimeType;
} else if (SCHEME_DATA.equals(scheme)) {
final DataUri dataUri = DataUri.parse(uri.toString(), Charset.defaultCharset());
is = new ByteArrayInputStream(dataUri.getData());
mimeType = dataUri.getMime();
} else {
is = cr.openInputStream(uri);
final BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(cr.openInputStream(uri), null, opts);
mimeType = opts.outMimeType;
}
final String suffix = mimeType != null ? "."
+ MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) : null;
final File outFile = File.createTempFile("temp_image_", suffix, cacheDir);
os = new FileOutputStream(outFile);
Utils.copyStream(is, os);
if (mDeleteSource && SCHEME_FILE.equals(scheme)) {
final File sourceFile = new File(mUri.getPath());
sourceFile.delete();
}
return SingleResponse.getInstance(outFile);
} catch (final IOException e) {
return SingleResponse.getInstance(e);
} finally {
Utils.closeSilently(os);
Utils.closeSilently(is);
}
}
@Override
protected void onPreExecute() {
final ProgressDialogFragment f = ProgressDialogFragment.show(mActivity, TAG_COPYING_IMAGE);
f.setCancelable(false);
}
@Override
protected void onPostExecute(final SingleResponse<File> result) {
final Fragment f = mActivity.getSupportFragmentManager().findFragmentByTag(TAG_COPYING_IMAGE);
if (f instanceof DialogFragment) {
((DialogFragment) f).dismiss();
}
if (result.hasData()) {
final Uri dstUri = Uri.fromFile(result.getData());
final Intent callingIntent = mActivity.getIntent();
if (mNeedsCrop && ((callingIntent.hasExtra(EXTRA_ASPECT_X) && callingIntent.hasExtra(EXTRA_ASPECT_Y))
|| (callingIntent.hasExtra(EXTRA_MAX_WIDTH) && callingIntent.hasExtra(EXTRA_MAX_HEIGHT)))) {
final Uri tempImageUri = mActivity.createTempImageUri();
final Crop crop = Crop.of(dstUri, tempImageUri);
final int aspectX = callingIntent.getIntExtra(EXTRA_ASPECT_X, -1);
final int aspectY = callingIntent.getIntExtra(EXTRA_ASPECT_Y, -1);
if (aspectX > 0 && aspectY > 0) {
crop.withAspect(aspectX, aspectY);
}
final int maxWidth = callingIntent.getIntExtra(EXTRA_MAX_WIDTH, -1);
final int maxHeight = callingIntent.getIntExtra(EXTRA_MAX_HEIGHT, -1);
if (maxWidth > 0 && maxHeight > 0) {
crop.withMaxSize(maxWidth, maxHeight);
}
final Intent cropIntent = crop.getIntent(mActivity);
cropIntent.setClass(mActivity, ImageCropperActivity.class);
mActivity.mTempPhotoUri = tempImageUri;
mActivity.startActivityForResult(cropIntent, REQUEST_CROP);
return;
}
final Intent data = new Intent();
data.setData(dstUri);
mActivity.setResult(RESULT_OK, data);
} else if (result.hasException()) {
Log.w(LOGTAG, result.getException());
}
mActivity.finish();
}
}
public static class ImageSourceDialogFragment extends BaseSupportDialogFragment implements OnClickListener {
@Override
public void onClick(final DialogInterface dialog, final int which) {
final FragmentActivity activity = getActivity();
if (!(activity instanceof ImagePickerActivity)) return;
final ImagePickerActivity addImageActivity = (ImagePickerActivity) activity;
final String source = getResources().getStringArray(R.array.value_image_sources)[which];
if ("gallery".equals(source)) {
addImageActivity.pickImage();
} else if ("camera".equals(source)) {
addImageActivity.takePhoto();
}
}
@NonNull
@Override
public Dialog onCreateDialog(final Bundle savedInstanceState) {
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setItems(R.array.entries_image_sources, this);
return builder.create();
}
@Override
public void onCancel(final DialogInterface dialog) {
super.onCancel(dialog);
final FragmentActivity a = getActivity();
if (a != null) {
a.finish();
}
}
@Override
public void onDismiss(final DialogInterface dialog) {
super.onDismiss(dialog);
}
}
public static abstract class NetworkStreamDownloader {
private final Context mContext;
protected NetworkStreamDownloader(Context context) {
mContext = context;
}
public final Context getContext() {
return mContext;
}
public abstract DownloadResult get(Uri uri) throws IOException;
public static final class DownloadResult {
private final InputStream stream;
private final String mimeType;
public DownloadResult(final InputStream stream, final String mimeType) {
this.stream = stream;
this.mimeType = mimeType;
}
public static DownloadResult get(InputStream stream, String mimeType) {
return new DownloadResult(stream, mimeType);
}
}
}
}

View File

@ -0,0 +1,73 @@
package org.mariotaku.twidere.activity.support;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.annotation.NonNull;
import org.mariotaku.pickncrop.library.ImagePickerActivity;
import org.mariotaku.twidere.activity.ImageCropperActivity;
import org.mariotaku.twidere.util.RestFuNetworkStreamDownloader;
import org.mariotaku.twidere.util.ThemeUtils;
public class ThemedImagePickerActivity extends ImagePickerActivity {
@Override
public void setTheme(final int resid) {
super.setTheme(ThemeUtils.getNoDisplayThemeResource(this));
}
public static ThemedIntentBuilder withThemed(Context context) {
return new ThemedIntentBuilder(context);
}
public static final class ThemedIntentBuilder {
private final Context context;
private final IntentBuilder intentBuilder;
public ThemedIntentBuilder(final Context context) {
this.context = context;
this.intentBuilder = new IntentBuilder(context);
intentBuilder.cropImageActivityClass(ImageCropperActivity.class);
intentBuilder.streamDownloaderClass(RestFuNetworkStreamDownloader.class);
}
public ThemedIntentBuilder takePhoto() {
intentBuilder.takePhoto();
return this;
}
public ThemedIntentBuilder getImage(@NonNull final Uri uri) {
intentBuilder.getImage(uri);
return this;
}
public Intent build() {
final Intent intent = intentBuilder.build();
intent.setClass(context, ThemedImagePickerActivity.class);
return intent;
}
public ThemedIntentBuilder pickImage() {
intentBuilder.pickImage();
return this;
}
public ThemedIntentBuilder addEntry(final String name, final String value, final int result) {
intentBuilder.addEntry(name, value, result);
return this;
}
public ThemedIntentBuilder maximumSize(final int w, final int h) {
intentBuilder.maximumSize(w, h);
return this;
}
public ThemedIntentBuilder aspectRatio(final int x, final int y) {
intentBuilder.aspectRatio(x, y);
return this;
}
}
}

View File

@ -78,7 +78,7 @@ import org.mariotaku.querybuilder.OrderBy;
import org.mariotaku.querybuilder.RawItemArray;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.BaseAppCompatActivity;
import org.mariotaku.twidere.activity.support.ImagePickerActivity;
import org.mariotaku.twidere.activity.support.ThemedImagePickerActivity;
import org.mariotaku.twidere.adapter.AccountsSpinnerAdapter;
import org.mariotaku.twidere.adapter.MessageConversationAdapter;
import org.mariotaku.twidere.adapter.SimpleParcelableUsersAdapter;
@ -467,7 +467,7 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
break;
}
case R.id.add_image: {
final Intent intent = new Intent(getActivity(), ImagePickerActivity.class);
final Intent intent = ThemedImagePickerActivity.withThemed(getActivity()).build();
startActivityForResult(intent, REQUEST_PICK_IMAGE);
break;
}

View File

@ -50,7 +50,7 @@ import com.twitter.Validator;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
import org.mariotaku.twidere.activity.support.ImagePickerActivity;
import org.mariotaku.twidere.activity.support.ThemedImagePickerActivity;
import org.mariotaku.twidere.api.twitter.Twitter;
import org.mariotaku.twidere.api.twitter.TwitterException;
import org.mariotaku.twidere.api.twitter.model.ProfileUpdate;
@ -86,6 +86,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
private static final int REQUEST_PICK_LINK_COLOR = 3;
private static final int REQUEST_PICK_BACKGROUND_COLOR = 4;
private static final int RESULT_REMOVE_BANNER = 101;
private MediaLoaderWrapper mLazyImageLoader;
private AsyncTaskManager mAsyncTaskManager;
private AsyncTask<Object, Object, ?> mTask;
@ -93,8 +95,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
private ImageView mProfileBannerView;
private MaterialEditText mEditName, mEditDescription, mEditLocation, mEditUrl;
private View mProgressContainer, mEditProfileContent;
private View mProfileImageCamera, mProfileImageGallery;
private View mProfileBannerGallery, mProfileBannerRemove;
private View mEditProfileImage;
private View mEditProfileBanner;
private View mSetLinkColor, mSetBackgroundColor;
private ForegroundColorView mLinkColor, mBackgroundColor;
private long mAccountId;
@ -127,41 +129,18 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
case R.id.profile_banner: {
break;
}
case R.id.profile_image_camera: {
final Intent intent = new Intent(getActivity(), ImagePickerActivity.class);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_X, 1);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_Y, 1);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_WIDTH, 512);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_HEIGHT, 512);
intent.setAction(ImagePickerActivity.INTENT_ACTION_TAKE_PHOTO);
case R.id.edit_profile_image: {
final Intent intent = ThemedImagePickerActivity.withThemed(getActivity()).aspectRatio(1, 1)
.maximumSize(512, 512).build();
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
break;
}
case R.id.profile_image_gallery: {
final Intent intent = new Intent(getActivity(), ImagePickerActivity.class);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_X, 3);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_Y, 1);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_WIDTH, 1500);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_HEIGHT, 500);
intent.setAction(ImagePickerActivity.INTENT_ACTION_PICK_IMAGE);
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
break;
}
case R.id.profile_banner_gallery: {
final Intent intent = new Intent(getActivity(), ImagePickerActivity.class);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_X, 1);
intent.putExtra(ImagePickerActivity.EXTRA_ASPECT_Y, 1);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_WIDTH, 512);
intent.putExtra(ImagePickerActivity.EXTRA_MAX_HEIGHT, 512);
intent.setAction(ImagePickerActivity.INTENT_ACTION_PICK_IMAGE);
case R.id.edit_profile_banner: {
final Intent intent = ThemedImagePickerActivity.withThemed(getActivity()).aspectRatio(3, 1)
.maximumSize(1500, 500).addEntry(getString(R.string.remove), "remove_banner", RESULT_REMOVE_BANNER).build();
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
break;
}
case R.id.profile_banner_remove: {
mTask = new RemoveProfileBannerTaskInternal(user.account_id);
AsyncTaskUtils.executeTask(mTask);
break;
}
case R.id.set_link_color: {
final Intent intent = new Intent(getActivity(), ColorPickerDialogActivity.class);
intent.putExtra(EXTRA_COLOR, user.link_color);
@ -249,10 +228,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
mProfileImageView.setOnClickListener(this);
mProfileBannerView.setOnClickListener(this);
mProfileImageCamera.setOnClickListener(this);
mProfileImageGallery.setOnClickListener(this);
mProfileBannerGallery.setOnClickListener(this);
mProfileBannerRemove.setOnClickListener(this);
mEditProfileBanner.setOnClickListener(this);
mEditProfileImage.setOnClickListener(this);
mSetLinkColor.setOnClickListener(this);
mSetBackgroundColor.setOnClickListener(this);
@ -299,10 +276,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
mEditDescription = (MaterialEditText) view.findViewById(R.id.description);
mEditLocation = (MaterialEditText) view.findViewById(R.id.location);
mEditUrl = (MaterialEditText) view.findViewById(R.id.url);
mProfileImageCamera = view.findViewById(R.id.profile_image_camera);
mProfileImageGallery = view.findViewById(R.id.profile_image_gallery);
mProfileBannerGallery = view.findViewById(R.id.profile_banner_gallery);
mProfileBannerRemove = view.findViewById(R.id.profile_banner_remove);
mEditProfileImage = view.findViewById(R.id.edit_profile_image);
mEditProfileBanner = view.findViewById(R.id.edit_profile_banner);
mLinkColor = (ForegroundColorView) view.findViewById(R.id.link_color);
mBackgroundColor = (ForegroundColorView) view.findViewById(R.id.background_color);
mSetLinkColor = view.findViewById(R.id.set_link_color);
@ -315,7 +290,11 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
switch (requestCode) {
case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: {
if (mTask != null && mTask.getStatus() == Status.RUNNING) return;
mTask = new UpdateProfileBannerImageTaskInternal(getActivity(), mAsyncTaskManager, mAccountId, data.getData(), true);
if (resultCode == RESULT_REMOVE_BANNER) {
mTask = new RemoveProfileBannerTaskInternal(mAccountId);
} else {
mTask = new UpdateProfileBannerImageTaskInternal(getActivity(), mAsyncTaskManager, mAccountId, data.getData(), true);
}
AsyncTaskUtils.executeTask(mTask);
break;
}
@ -343,6 +322,7 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
}
boolean isProfileChanged() {
final ParcelableUser user = mUser;
if (user == null) return true;

View File

@ -19,9 +19,14 @@
package org.mariotaku.twidere.util;
import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Build;
import android.support.annotation.Nullable;
import android.text.Spanned;
import android.text.style.ImageSpan;
public final class ClipboardUtils {
@ -31,4 +36,30 @@ public final class ClipboardUtils {
clipboardManager.setPrimaryClip(ClipData.newPlainText(text, text));
return true;
}
@Nullable
public static String getImageUrl(final Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return null;
return ClipboardUtilsAPI16.getImageUrl(context);
}
private static class ClipboardUtilsAPI16 {
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public static String getImageUrl(final Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return null;
final ClipboardManager cm = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
final ClipData primaryClip = cm.getPrimaryClip();
if (primaryClip.getItemCount() > 0) {
final ClipData.Item item = primaryClip.getItemAt(0);
final CharSequence styledText = item.coerceToStyledText(context);
if (styledText instanceof Spanned) {
final Spanned spanned = (Spanned) styledText;
final ImageSpan[] imageSpans = spanned.getSpans(0, spanned.length(), ImageSpan.class);
if (imageSpans.length == 1) return imageSpans[0].getSource();
}
}
return null;
}
}
}

View File

@ -28,14 +28,14 @@ import org.mariotaku.restfu.http.RestHttpClient;
import org.mariotaku.restfu.http.RestHttpRequest;
import org.mariotaku.restfu.http.RestHttpResponse;
import org.mariotaku.restfu.http.mime.TypedData;
import org.mariotaku.twidere.activity.support.ImagePickerActivity;
import org.mariotaku.twidere.activity.support.ThemedImagePickerActivity;
import java.io.IOException;
/**
* Created by mariotaku on 15/6/17.
*/
public class RestFuNetworkStreamDownloader extends ImagePickerActivity.NetworkStreamDownloader {
public class RestFuNetworkStreamDownloader extends ThemedImagePickerActivity.NetworkStreamDownloader {
public RestFuNetworkStreamDownloader(Context context) {
super(context);

View File

@ -17,10 +17,11 @@
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout
android:id="@+id/main_content"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
@ -53,8 +54,11 @@
android:orientation="vertical">
<LinearLayout
android:id="@+id/edit_profile_image"
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">
@ -64,71 +68,27 @@
android:layout_height="@dimen/element_size_mlarge"
android:layout_gravity="center"
android:foreground="?selectableItemBackground"
android:scaleType="centerCrop" />
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
<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:paddingTop="@dimen/element_spacing_normal"
android:text="@string/profile_image"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:splitMotionEvents="false">
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/profile_image_camera"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:drawableLeft="@drawable/ic_action_camera"
android:drawableStart="@drawable/ic_action_camera"
android:paddingBottom="0dp"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="0dp"
android:text="@string/photo" />
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/profile_image_gallery"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:drawableLeft="@drawable/ic_action_gallery"
android:drawableStart="@drawable/ic_action_gallery"
android:paddingBottom="0dp"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="0dp"
android:text="@string/gallery" />
</LinearLayout>
</LinearLayout>
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:text="@string/profile_image"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
</LinearLayout>
<LinearLayout
android:id="@+id/edit_profile_banner"
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">
@ -138,65 +98,19 @@
android:layout_height="@dimen/element_size_mlarge"
android:layout_gravity="center"
android:foreground="?selectableItemBackground"
android:scaleType="centerCrop" />
android:scaleType="centerCrop"/>
<LinearLayout
android:layout_width="match_parent"
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
<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:paddingTop="@dimen/element_spacing_normal"
android:text="@string/profile_banner"
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:splitMotionEvents="false">
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/profile_banner_gallery"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:drawableLeft="@drawable/ic_action_gallery"
android:drawableStart="@drawable/ic_action_gallery"
android:paddingBottom="0dp"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="0dp"
android:text="@string/gallery" />
<org.mariotaku.twidere.view.ActionIconThemedTextView
android:id="@+id/profile_banner_remove"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?selectableItemBackground"
android:drawableLeft="@drawable/ic_action_cancel"
android:drawableStart="@drawable/ic_action_cancel"
android:paddingBottom="0dp"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
android:paddingTop="0dp"
android:text="@string/remove" />
</LinearLayout>
</LinearLayout>
android:layout_marginLeft="@dimen/element_spacing_normal"
android:layout_marginStart="@dimen/element_spacing_normal"
android:paddingTop="@dimen/element_spacing_normal"
android:text="@string/profile_banner"
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold"/>
</LinearLayout>
</LinearLayout>
@ -227,7 +141,7 @@
app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/name"
app:met_maxCharacters="20" />
app:met_maxCharacters="20"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText
android:id="@+id/description"
@ -239,7 +153,7 @@
app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/description"
app:met_maxCharacters="160" />
app:met_maxCharacters="160"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText
android:id="@+id/location"
@ -250,7 +164,7 @@
app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/location"
app:met_maxCharacters="30" />
app:met_maxCharacters="30"/>
<org.mariotaku.twidere.view.themed.BackgroundTintMaterialEditText
android:id="@+id/url"
@ -261,7 +175,7 @@
app:met_baseColor="?android:textColorPrimary"
app:met_floatingLabel="normal"
app:met_floatingLabelText="@string/url"
app:met_maxCharacters="100" />
app:met_maxCharacters="100"/>
</LinearLayout>
</android.support.v7.widget.CardView>
@ -294,7 +208,7 @@
android:id="@+id/link_color"
android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal"
android:layout_weight="0" />
android:layout_weight="0"/>
<TextView
android:layout_width="match_parent"
@ -306,7 +220,7 @@
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold" />
android:textStyle="bold"/>
</LinearLayout>
@ -323,7 +237,7 @@
android:id="@+id/background_color"
android:layout_width="@dimen/element_size_normal"
android:layout_height="@dimen/element_size_normal"
android:layout_weight="0" />
android:layout_weight="0"/>
<TextView
android:layout_width="match_parent"
@ -335,7 +249,7 @@
android:textAllCaps="true"
android:textAppearance="?android:textAppearanceSmall"
android:textColor="?android:textColorPrimary"
android:textStyle="bold" />
android:textStyle="bold"/>
</LinearLayout>
@ -353,7 +267,7 @@
android:visibility="visible"
tools:visibility="gone">
<include layout="@layout/layout_progress_wheel_medium" />
<include layout="@layout/layout_progress_wheel_medium"/>
</FrameLayout>
</FrameLayout>

View File

@ -104,12 +104,14 @@
<item>@string/scale</item>
</string-array>
<string-array name="entries_image_sources">
<item>@string/from_camera</item>
<item>@string/from_gallery</item>
<item>@string/source_camera</item>
<item>@string/source_gallery</item>
<item>@string/source_clipboard</item>
</string-array>
<string-array name="value_image_sources">
<item>camera</item>
<item>gallery</item>
<item>clipboard</item>
</string-array>
<string-array name="values_profile_image_style">
<item>round</item>

View File

@ -646,7 +646,11 @@
<string name="state_blocking">Blocking</string>
<string name="load_more">Load more</string>
<string name="photo">Photo</string>
<string name="camera">Camera</string>
<string name="gallery">Gallery</string>
<string name="source_camera">Camera</string>
<string name="source_gallery">Gallery</string>
<string name="source_clipboard">Clipboard</string>
<string name="remove">Remove</string>
<string name="load_media">Load media</string>
<string name="profile_text_color">Text color</string>