From 95b1a7c61aea6a5866def00fc3e68a33be10e116 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Mon, 3 Sep 2018 16:24:39 +0200 Subject: [PATCH 1/3] Update bitrise badge (#833) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d4754d71..1e89f9363 100644 --- a/README.md +++ b/README.md @@ -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) From 0b3bee0d15e53de52dedce4e6627f5f7267a7673 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Mon, 3 Sep 2018 20:16:12 +0200 Subject: [PATCH 2/3] fix account switching when offline/error (#830) --- .../com/keylesspalace/tusky/MainActivity.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 3a062fcf0..dcbce5194 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -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 allAccounts = accountManager.getAllAccountsOrderedByActive(); - // reuse the already existing "add account" item List 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); } From aac63441d70e1c7782daebb18fb6d832533c8b96 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Mon, 3 Sep 2018 20:26:35 +0200 Subject: [PATCH 3/3] fix image preview rotation in ComposeActivity (#831) --- .../keylesspalace/tusky/ComposeActivity.java | 32 +++++-- .../tusky/util/DownsizeImageTask.java | 87 +------------------ .../keylesspalace/tusky/util/MediaUtils.java | 83 +++++++++++++++++- 3 files changed, 111 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 4662fbbd6..f36cff2ac 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -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() { + @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); diff --git a/app/src/main/java/com/keylesspalace/tusky/util/DownsizeImageTask.java b/app/src/main/java/com/keylesspalace/tusky/util/DownsizeImageTask.java index be0c989dd..3b9f04d08 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/DownsizeImageTask.java +++ b/app/src/main/java/com/keylesspalace/tusky/util/DownsizeImageTask.java @@ -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 { - private static final String TAG = "DownsizeImageTask"; private int sizeLimit; private ContentResolver contentResolver; private Listener listener; @@ -54,83 +48,6 @@ public class DownsizeImageTask extends AsyncTask { 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 { 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 { if (scaledBitmap == null) { return false; } - Bitmap reorientedBitmap = reorientBitmap(scaledBitmap, orientation); + Bitmap reorientedBitmap = MediaUtils.reorientBitmap(scaledBitmap, orientation); if (reorientedBitmap == null) { scaledBitmap.recycle(); return false; diff --git a/app/src/main/java/com/keylesspalace/tusky/util/MediaUtils.java b/app/src/main/java/com/keylesspalace/tusky/util/MediaUtils.java index 2e93fc925..0ad3adb19 100644 --- a/app/src/main/java/com/keylesspalace/tusky/util/MediaUtils.java +++ b/app/src/main/java/com/keylesspalace/tusky/util/MediaUtils.java @@ -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; + } }