mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-21 23:15:23 +00:00
Replace Avatar Cropper.
This commit is contained in:
parent
0cb2404735
commit
286b64274c
@ -403,7 +403,8 @@
|
||||
android:theme="@style/TextSecure.ScribbleTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
||||
<activity android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||
android:theme="@style/TextSecure.DarkTheme"/>
|
||||
|
||||
<activity android:name=".CreateProfileActivity"
|
||||
android:theme="@style/TextSecure.LightRegistrationTheme"
|
||||
|
@ -106,7 +106,7 @@ dependencies {
|
||||
compile 'com.pnikosis:materialish-progress:1.5'
|
||||
compile 'org.greenrobot:eventbus:3.0.0'
|
||||
compile 'pl.tajchert:waitingdots:0.1.0'
|
||||
compile 'com.soundcloud.android:android-crop:0.9.10@aar'
|
||||
compile 'com.theartofdev.edmodo:android-image-cropper:2.7.0'
|
||||
compile 'com.melnykov:floatingactionbutton:1.3.0'
|
||||
compile 'com.google.zxing:android-integration:3.1.0'
|
||||
compile 'com.squareup.dagger:dagger:1.2.2'
|
||||
@ -172,6 +172,7 @@ dependencyVerification {
|
||||
'com.android.support:preference-v7:75eabe936d1fc3b178450a554c4d433466036f2be6d6dccdf971eac9590fdbf5',
|
||||
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
||||
'pl.tajchert:waitingdots:2835d49e0787dbcb606c5a60021ced66578503b1e9fddcd7a5ef0cd5f095ba2c',
|
||||
'com.theartofdev.edmodo:android-image-cropper:72a1b03c5642fe8489061c732e43b10558c850129b576970e4f77a5d4c25317a',
|
||||
'mobi.upod:time-duration-picker:db469ce0f48dd96b892eac424ed76870e54bf00fe0a28cdcddfbe5f2a226a0e1',
|
||||
'com.codewaves.stickyheadergrid:stickyheadergrid:5b4aa6a52a957cfd55f60f4220c11c0c371385a3cb9786cae03c260dcdef5794',
|
||||
'com.android.support:appcompat-v7:a3a8e5230359746ed91801579b5fbe4668e3b1c4e6a14c7d67c8f58cb0311752',
|
||||
@ -202,7 +203,6 @@ dependencyVerification {
|
||||
'com.github.bumptech.glide:glide:997de7ac95be6c944d3b8cbe13de11307736ea45451c1b09a6cec7c328ead59f',
|
||||
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
|
||||
'org.greenrobot:eventbus:180d4212467df06f2fbc9c8d8a2984533ac79c87769ad883bc421612f0b4e17c',
|
||||
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
|
||||
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
|
||||
'com.squareup.dagger:dagger:789aca24537022e49f91fc6444078d9de8f1dd99e1bfb090f18491b186967883',
|
||||
'com.amulyakhare:com.amulyakhare.textdrawable:54c92b5fba38cfd316a07e5a30528068f45ce8515a6890f1297df4c401af5dcb',
|
||||
|
@ -65,4 +65,6 @@
|
||||
|
||||
<color name="logsubmit_confirmation_background">#44ff2d00</color>
|
||||
|
||||
<color name="avatar_background">@color/transparent_black_90</color>
|
||||
|
||||
</resources>
|
||||
|
@ -381,6 +381,10 @@
|
||||
<!-- GroupMembersDialog -->
|
||||
<string name="GroupMembersDialog_me">Me</string>
|
||||
|
||||
<!-- CropImageActivity -->
|
||||
<string name="CropImageActivity_group_avatar">@string/GroupCreateActivity_avatar_content_description</string>
|
||||
<string name="CropImageActivity_profile_avatar">Avatar</string>
|
||||
|
||||
<!-- InputPanel -->
|
||||
<string name="InputPanel_tap_and_hold_to_record_a_voice_message_release_to_send">Tap and hold to record a voice message, release to send</string>
|
||||
|
||||
|
@ -12,28 +12,25 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection;
|
||||
import org.thoughtcrime.securesms.components.LabeledEditText;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewAnimationUtils;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.dd.CircularProgressButton;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.InputAwareLayout;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
|
||||
@ -53,8 +50,6 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicRegistrationTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.FileProviderUtil;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@ -67,14 +62,10 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.provider.MediaStore.EXTRA_OUTPUT;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class CreateProfileActivity extends BaseActionBarActivity implements InjectableType {
|
||||
|
||||
@ -83,8 +74,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
public static final String NEXT_INTENT = "next_intent";
|
||||
public static final String EXCLUDE_SYSTEM = "exclude_system";
|
||||
|
||||
private static final int REQUEST_CODE_AVATAR = 1;
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicRegistrationTheme();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
@ -153,7 +142,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_AVATAR:
|
||||
case AvatarSelection.REQUEST_CODE_AVATAR:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
Uri outputFile = Uri.fromFile(new File(getCacheDir(), "cropped"));
|
||||
Uri inputFile = (data != null ? data.getData() : null);
|
||||
@ -166,18 +155,18 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
avatarBytes = null;
|
||||
avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_camera_alt_white_24dp).asDrawable(this, getResources().getColor(R.color.grey_400)));
|
||||
} else {
|
||||
new Crop(inputFile).output(outputFile).asSquare().start(this);
|
||||
AvatarSelection.circularCropImage(this, inputFile, outputFile, R.string.CropImageActivity_profile_avatar);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case Crop.REQUEST_CROP:
|
||||
case AvatarSelection.REQUEST_CODE_CROP_IMAGE:
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
new AsyncTask<Void, Void, byte[]>() {
|
||||
@Override
|
||||
protected byte[] doInBackground(Void... params) {
|
||||
try {
|
||||
BitmapUtil.ScaleResult result = BitmapUtil.createScaledBytes(CreateProfileActivity.this, Crop.getOutput(data), new ProfileMediaConstraints());
|
||||
BitmapUtil.ScaleResult result = BitmapUtil.createScaledBytes(CreateProfileActivity.this, AvatarSelection.getResultUri(data), new ProfileMediaConstraints());
|
||||
return result.getBitmap();
|
||||
} catch (BitmapDecodingException e) {
|
||||
Log.w(TAG, e);
|
||||
@ -220,7 +209,7 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
this.avatar.setOnClickListener(view -> Permissions.with(this)
|
||||
.request(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||
.ifNecessary()
|
||||
.onAnyResult(this::handleAvatarSelectionWithPermissions)
|
||||
.onAnyResult(this::startAvatarSelection)
|
||||
.execute());
|
||||
|
||||
this.name.getInput().addTextChangedListener(new TextWatcher() {
|
||||
@ -354,53 +343,8 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Inje
|
||||
this.name.setOnClickListener(v -> container.showSoftkey(name.getInput()));
|
||||
}
|
||||
|
||||
private Intent createAvatarSelectionIntent(@Nullable File captureFile, boolean includeClear, boolean includeCamera) {
|
||||
List<Intent> extraIntents = new LinkedList<>();
|
||||
Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
|
||||
galleryIntent.setType("image/*");
|
||||
|
||||
if (!IntentUtils.isResolvable(CreateProfileActivity.this, galleryIntent)) {
|
||||
galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
galleryIntent.setType("image/*");
|
||||
}
|
||||
|
||||
if (includeCamera) {
|
||||
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
|
||||
if (captureFile != null && cameraIntent.resolveActivity(getPackageManager()) != null) {
|
||||
cameraIntent.putExtra(EXTRA_OUTPUT, FileProviderUtil.getUriFor(this, captureFile));
|
||||
extraIntents.add(cameraIntent);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeClear) {
|
||||
extraIntents.add(new Intent("org.thoughtcrime.securesms.action.CLEAR_PROFILE_PHOTO"));
|
||||
}
|
||||
|
||||
Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.CreateProfileActivity_profile_photo));
|
||||
|
||||
if (!extraIntents.isEmpty()) {
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Intent[0]));
|
||||
}
|
||||
|
||||
|
||||
return chooserIntent;
|
||||
}
|
||||
|
||||
private void handleAvatarSelectionWithPermissions() {
|
||||
boolean hasCameraPermission = Permissions.hasAll(this, Manifest.permission.CAMERA);
|
||||
|
||||
if (hasCameraPermission) {
|
||||
try {
|
||||
captureFile = File.createTempFile("capture", "jpg", getExternalCacheDir());
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
captureFile = null;
|
||||
}
|
||||
}
|
||||
|
||||
Intent chooserIntent = createAvatarSelectionIntent(captureFile, avatarBytes != null, hasCameraPermission);
|
||||
startActivityForResult(chooserIntent, REQUEST_CODE_AVATAR);
|
||||
private void startAvatarSelection() {
|
||||
captureFile = AvatarSelection.startAvatarSelection(this, avatarBytes != null, true);
|
||||
}
|
||||
|
||||
private void handleUpload() {
|
||||
|
@ -27,6 +27,7 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.avatar.AvatarSelection;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationActivity;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import android.view.Menu;
|
||||
@ -42,7 +43,6 @@ import android.widget.Toast;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel;
|
||||
import org.thoughtcrime.securesms.components.PushRecipientsPanel.RecipientsPanelChangedListener;
|
||||
@ -190,7 +190,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
recipientsPanel.setPanelChangeListener(this);
|
||||
findViewById(R.id.contacts_button).setOnClickListener(new AddRecipientButtonListener());
|
||||
avatar.setImageDrawable(new ResourceContactPhoto(R.drawable.ic_group_white_24dp).asDrawable(this, ContactColors.UNKNOWN_COLOR.toConversationColor(this)));
|
||||
avatar.setOnClickListener(view -> Crop.pickImage(GroupCreateActivity.this));
|
||||
avatar.setOnClickListener(view -> AvatarSelection.startAvatarSelection(this, false, false));
|
||||
}
|
||||
|
||||
private void initializeExistingGroup() {
|
||||
@ -293,13 +293,14 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_PICK:
|
||||
new Crop(data.getData()).output(outputFile).asSquare().start(this);
|
||||
case AvatarSelection.REQUEST_CODE_AVATAR:
|
||||
AvatarSelection.circularCropImage(this, data.getData(), outputFile, R.string.CropImageActivity_group_avatar);
|
||||
break;
|
||||
case Crop.REQUEST_CROP:
|
||||
case AvatarSelection.REQUEST_CODE_CROP_IMAGE:
|
||||
final Uri resultUri = AvatarSelection.getResultUri(data);
|
||||
GlideApp.with(this)
|
||||
.asBitmap()
|
||||
.load(Crop.getOutput(data))
|
||||
.load(resultUri)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.centerCrop()
|
||||
@ -307,7 +308,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
setAvatar(Crop.getOutput(data), resource);
|
||||
setAvatar(resultUri, resource);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
115
src/org/thoughtcrime/securesms/avatar/AvatarSelection.java
Normal file
115
src/org/thoughtcrime/securesms/avatar/AvatarSelection.java
Normal file
@ -0,0 +1,115 @@
|
||||
package org.thoughtcrime.securesms.avatar;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
|
||||
import com.theartofdev.edmodo.cropper.CropImage;
|
||||
import com.theartofdev.edmodo.cropper.CropImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.util.FileProviderUtil;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.provider.MediaStore.EXTRA_OUTPUT;
|
||||
|
||||
public final class AvatarSelection {
|
||||
|
||||
private static final String TAG = AvatarSelection.class.getSimpleName();
|
||||
|
||||
private AvatarSelection() {
|
||||
}
|
||||
|
||||
public static final int REQUEST_CODE_CROP_IMAGE = CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE;
|
||||
public static final int REQUEST_CODE_AVATAR = REQUEST_CODE_CROP_IMAGE + 1;
|
||||
|
||||
/**
|
||||
* Returns result on {@link #REQUEST_CODE_CROP_IMAGE}
|
||||
*/
|
||||
public static void circularCropImage(Activity activity, Uri inputFile, Uri outputFile, @StringRes int title) {
|
||||
CropImage.activity(inputFile)
|
||||
.setGuidelines(CropImageView.Guidelines.ON)
|
||||
.setAspectRatio(1, 1)
|
||||
.setCropShape(CropImageView.CropShape.OVAL)
|
||||
.setOutputUri(outputFile)
|
||||
.setAllowRotation(true)
|
||||
.setAllowFlipping(true)
|
||||
.setBackgroundColor(ContextCompat.getColor(activity, R.color.avatar_background))
|
||||
.setActivityTitle(activity.getString(title))
|
||||
.start(activity);
|
||||
}
|
||||
|
||||
public static Uri getResultUri(Intent data) {
|
||||
return CropImage.getActivityResult(data).getUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns result on {@link #REQUEST_CODE_AVATAR}
|
||||
*
|
||||
* @return Temporary capture file if created.
|
||||
*/
|
||||
public static File startAvatarSelection(Activity activity, boolean includeClear, boolean attemptToIncludeCamera) {
|
||||
File captureFile = null;
|
||||
|
||||
if (attemptToIncludeCamera) {
|
||||
if (Permissions.hasAll(activity, Manifest.permission.CAMERA)) {
|
||||
try {
|
||||
captureFile = File.createTempFile("capture", "jpg", activity.getExternalCacheDir());
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
captureFile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Intent chooserIntent = createAvatarSelectionIntent(activity, captureFile, includeClear);
|
||||
activity.startActivityForResult(chooserIntent, REQUEST_CODE_AVATAR);
|
||||
return captureFile;
|
||||
}
|
||||
|
||||
private static Intent createAvatarSelectionIntent(Context context, @Nullable File tempCaptureFile, boolean includeClear) {
|
||||
List<Intent> extraIntents = new LinkedList<>();
|
||||
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
|
||||
|
||||
galleryIntent.setDataAndType(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI, "image/*");
|
||||
|
||||
if (!IntentUtils.isResolvable(context, galleryIntent)) {
|
||||
galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
galleryIntent.setType("image/*");
|
||||
}
|
||||
|
||||
if (tempCaptureFile != null) {
|
||||
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
|
||||
if (cameraIntent.resolveActivity(context.getPackageManager()) != null) {
|
||||
cameraIntent.putExtra(EXTRA_OUTPUT, FileProviderUtil.getUriFor(context, tempCaptureFile));
|
||||
extraIntents.add(cameraIntent);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeClear) {
|
||||
extraIntents.add(new Intent("org.thoughtcrime.securesms.action.CLEAR_PROFILE_PHOTO"));
|
||||
}
|
||||
|
||||
Intent chooserIntent = Intent.createChooser(galleryIntent, context.getString(R.string.CreateProfileActivity_profile_photo));
|
||||
|
||||
if (!extraIntents.isEmpty()) {
|
||||
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents.toArray(new Intent[0]));
|
||||
}
|
||||
|
||||
return chooserIntent;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user