Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
a57b354247
5 changed files with 124 additions and 101 deletions
|
@ -1,4 +1,4 @@
|
|||
[![Translate - with Stringlate](https://img.shields.io/badge/translate%20with-stringlate-green.svg)](https://lonamiwebs.github.io/stringlate/translate?git=https%3A%2F%2Fgithub.com%2Ftuskyapp%2FTusky) [![Build Status](https://app.bitrise.io/app/55b2f0c77c4bba74/status.svg?token=elUl9fieM5K34iLRL0rpoA&branch=master)](https://app.bitrise.io/app/55b2f0c77c4bba74) [![CircleCI](https://circleci.com/gh/tuskyapp/Tusky.svg?style=svg)](https://circleci.com/gh/tuskyapp/Tusky)
|
||||
[![Translate - with Stringlate](https://img.shields.io/badge/translate%20with-stringlate-green.svg)](https://lonamiwebs.github.io/stringlate/translate?git=https%3A%2F%2Fgithub.com%2Ftuskyapp%2FTusky) [![Build Status](https://app.bitrise.io/app/a3e773c3c57a894c/status.svg?token=qLu_Ti4Gp2LWcYT4eo2INQ&branch=master)](https://app.bitrise.io/app/a3e773c3c57a894c#/builds) [![CircleCI](https://circleci.com/gh/tuskyapp/Tusky.svg?style=svg)](https://circleci.com/gh/tuskyapp/Tusky)
|
||||
# Tusky
|
||||
|
||||
![](/fastlane/metadata/android/en-US/images/icon.png)
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.keylesspalace.tusky;
|
|||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ProgressDialog;
|
||||
import android.arch.lifecycle.Lifecycle;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
|
@ -135,12 +136,20 @@ import java.util.Locale;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import at.connyduck.sparkbutton.helpers.Utils;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.SingleObserver;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.MultipartBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
import static com.uber.autodispose.AutoDispose.autoDisposable;
|
||||
import static com.uber.autodispose.android.lifecycle.AndroidLifecycleScopeProvider.from;
|
||||
|
||||
public final class ComposeActivity
|
||||
extends BaseActivity
|
||||
implements ComposeOptionsListener,
|
||||
|
@ -1121,11 +1130,24 @@ public final class ComposeActivity
|
|||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||
|
||||
Picasso.with(this)
|
||||
.load(item.uri)
|
||||
.resize(displayMetrics.widthPixels, displayMetrics.heightPixels)
|
||||
.onlyScaleDown()
|
||||
.into(imageView);
|
||||
Single.fromCallable(() ->
|
||||
MediaUtils.getSampledBitmap(getContentResolver(), item.uri, displayMetrics.widthPixels, displayMetrics.heightPixels))
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.as(autoDisposable(from(this, Lifecycle.Event.ON_DESTROY)))
|
||||
.subscribe(new SingleObserver<Bitmap>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Bitmap bitmap) {
|
||||
imageView.setImageBitmap(bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) { }
|
||||
});
|
||||
|
||||
|
||||
int margin = Utils.dpToPx(this, 4);
|
||||
dialogLayout.addView(imageView);
|
||||
|
|
|
@ -420,7 +420,7 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
|
|||
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
startActivityWithSlideInAnimation(intent);
|
||||
startActivity(intent);
|
||||
finishWithoutSlideOutAnimation();
|
||||
|
||||
overridePendingTransition(R.anim.explode, R.anim.explode);
|
||||
|
@ -510,21 +510,15 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
|
|||
|
||||
List<AccountEntity> allAccounts = accountManager.getAllAccountsOrderedByActive();
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
List<IProfile> profiles = new ArrayList<>(allAccounts.size()+1);
|
||||
for (IProfile profile: headerResult.getProfiles()) {
|
||||
if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
profiles.add(profile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (AccountEntity acc : allAccounts) {
|
||||
CharSequence emojifiedName = CustomEmojiHelper.emojifyString(acc.getDisplayName(), acc.getEmojis(), headerResult.getView());
|
||||
emojifiedName = EmojiCompat.get().process(emojifiedName);
|
||||
|
||||
profiles.add(0,
|
||||
profiles.add(
|
||||
new ProfileDrawerItem()
|
||||
.withSetSelected(acc.isActive())
|
||||
.withName(emojifiedName)
|
||||
.withIcon(acc.getProfilePictureUrl())
|
||||
.withNameShown(true)
|
||||
|
@ -532,6 +526,15 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut
|
|||
.withEmail(acc.getFullName()));
|
||||
|
||||
}
|
||||
|
||||
// reuse the already existing "add account" item
|
||||
for (IProfile profile: headerResult.getProfiles()) {
|
||||
if (profile.getIdentifier() == DRAWER_ITEM_ADD_ACCOUNT) {
|
||||
profiles.add(profile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
headerResult.clear();
|
||||
headerResult.setProfiles(profiles);
|
||||
|
||||
}
|
||||
|
|
|
@ -18,16 +18,11 @@ package com.keylesspalace.tusky.util;
|
|||
import android.content.ContentResolver;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.media.ExifInterface;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -37,7 +32,6 @@ import java.util.List;
|
|||
* aspect ratio and orientation.
|
||||
*/
|
||||
public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||
private static final String TAG = "DownsizeImageTask";
|
||||
private int sizeLimit;
|
||||
private ContentResolver contentResolver;
|
||||
private Listener listener;
|
||||
|
@ -54,83 +48,6 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
|||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Bitmap reorientBitmap(Bitmap bitmap, int orientation) {
|
||||
Matrix matrix = new Matrix();
|
||||
switch (orientation) {
|
||||
default:
|
||||
case ExifInterface.ORIENTATION_NORMAL: {
|
||||
return bitmap;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: {
|
||||
matrix.setScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_180: {
|
||||
matrix.setRotate(180);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_FLIP_VERTICAL: {
|
||||
matrix.setRotate(180);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_TRANSPOSE: {
|
||||
matrix.setRotate(90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_90: {
|
||||
matrix.setRotate(90);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_TRANSVERSE: {
|
||||
matrix.setRotate(-90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_270: {
|
||||
matrix.setRotate(-90);
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
|
||||
bitmap.getHeight(), matrix, true);
|
||||
if (!bitmap.sameAs(result)) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
return result;
|
||||
} catch (OutOfMemoryError e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getOrientation(Uri uri, ContentResolver contentResolver) {
|
||||
InputStream inputStream;
|
||||
try {
|
||||
inputStream = contentResolver.openInputStream(uri);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.d(TAG, Log.getStackTraceString(e));
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
if (inputStream == null) {
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
ExifInterface exifInterface;
|
||||
try {
|
||||
exifInterface = new ExifInterface(inputStream);
|
||||
} catch (IOException e) {
|
||||
Log.d(TAG, Log.getStackTraceString(e));
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_NORMAL);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Uri... uris) {
|
||||
resultList = new ArrayList<>();
|
||||
|
@ -147,7 +64,7 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
|||
BitmapFactory.decodeStream(inputStream, null, options);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
// Get EXIF data, for orientation info.
|
||||
int orientation = getOrientation(uri, contentResolver);
|
||||
int orientation = MediaUtils.getImageOrientation(uri, contentResolver);
|
||||
// Then use that information to determine how much to compress.
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
/* Unfortunately, there isn't a determined worst case compression ratio for image
|
||||
|
@ -176,7 +93,7 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
|||
if (scaledBitmap == null) {
|
||||
return false;
|
||||
}
|
||||
Bitmap reorientedBitmap = reorientBitmap(scaledBitmap, orientation);
|
||||
Bitmap reorientedBitmap = MediaUtils.reorientBitmap(scaledBitmap, orientation);
|
||||
if (reorientedBitmap == null) {
|
||||
scaledBitmap.recycle();
|
||||
return false;
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
|||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Matrix;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
import android.media.ThumbnailUtils;
|
||||
import android.net.Uri;
|
||||
|
@ -27,6 +28,7 @@ import android.provider.OpenableColumns;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.Px;
|
||||
import android.support.media.ExifInterface;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -111,7 +113,9 @@ public class MediaUtils {
|
|||
options.inJustDecodeBounds = false;
|
||||
try {
|
||||
stream = contentResolver.openInputStream(uri);
|
||||
return BitmapFactory.decodeStream(stream, null, options);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
|
||||
int orientation = getImageOrientation(uri, contentResolver);
|
||||
return reorientBitmap(bitmap, orientation);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(TAG, e);
|
||||
return null;
|
||||
|
@ -176,4 +180,81 @@ public class MediaUtils {
|
|||
|
||||
return inSampleSize;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Bitmap reorientBitmap(Bitmap bitmap, int orientation) {
|
||||
Matrix matrix = new Matrix();
|
||||
switch (orientation) {
|
||||
default:
|
||||
case ExifInterface.ORIENTATION_NORMAL: {
|
||||
return bitmap;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: {
|
||||
matrix.setScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_180: {
|
||||
matrix.setRotate(180);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_FLIP_VERTICAL: {
|
||||
matrix.setRotate(180);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_TRANSPOSE: {
|
||||
matrix.setRotate(90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_90: {
|
||||
matrix.setRotate(90);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_TRANSVERSE: {
|
||||
matrix.setRotate(-90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
}
|
||||
case ExifInterface.ORIENTATION_ROTATE_270: {
|
||||
matrix.setRotate(-90);
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
Bitmap result = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
|
||||
bitmap.getHeight(), matrix, true);
|
||||
if (!bitmap.sameAs(result)) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
return result;
|
||||
} catch (OutOfMemoryError e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getImageOrientation(Uri uri, ContentResolver contentResolver) {
|
||||
InputStream inputStream;
|
||||
try {
|
||||
inputStream = contentResolver.openInputStream(uri);
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(TAG, e);
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
if (inputStream == null) {
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
ExifInterface exifInterface;
|
||||
try {
|
||||
exifInterface = new ExifInterface(inputStream);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
return ExifInterface.ORIENTATION_UNDEFINED;
|
||||
}
|
||||
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
|
||||
ExifInterface.ORIENTATION_NORMAL);
|
||||
IOUtils.closeQuietly(inputStream);
|
||||
return orientation;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue