From 428a157f7fba4ea27c45a32000b914b4ae9cc797 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 02:19:29 +0530 Subject: [PATCH 01/13] Add option to bulk resize images --- .../pro/activities/ViewPagerActivity.kt | 31 +--- .../gallery/pro/adapters/MediaAdapter.kt | 16 ++ .../pro/dialogs/ResizeMultipleImagesDialog.kt | 160 ++++++++++++++++++ .../gallery/pro/extensions/Activity.kt | 121 +++++++++++++ .../layout/dialog_resize_multiple_images.xml | 51 ++++++ app/src/main/res/menu/cab_media.xml | 5 + 6 files changed, 354 insertions(+), 30 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt create mode 100644 app/src/main/res/layout/dialog_resize_multiple_images.xml diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt index d00343110..220984953 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt @@ -16,7 +16,6 @@ import android.graphics.Bitmap import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Icon -import android.net.Uri import android.os.Build import android.os.Bundle import android.os.Handler @@ -47,7 +46,6 @@ import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.adapters.MyPagerAdapter import com.simplemobiletools.gallery.pro.asynctasks.GetMediaAsynctask import com.simplemobiletools.gallery.pro.dialogs.DeleteWithRememberDialog -import com.simplemobiletools.gallery.pro.dialogs.ResizeWithPathDialog import com.simplemobiletools.gallery.pro.dialogs.SaveAsDialog import com.simplemobiletools.gallery.pro.dialogs.SlideshowDialog import com.simplemobiletools.gallery.pro.extensions.* @@ -1050,34 +1048,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View @TargetApi(Build.VERSION_CODES.N) private fun resizeImage() { val oldPath = getCurrentPath() - val originalSize = oldPath.getImageResolution(this) ?: return - ResizeWithPathDialog(this, originalSize, oldPath) { newSize, newPath -> - ensureBackgroundThread { - try { - var oldExif: ExifInterface? = null - if (isNougatPlus()) { - val inputStream = contentResolver.openInputStream(Uri.fromFile(File(oldPath))) - oldExif = ExifInterface(inputStream!!) - } - - val newBitmap = Glide.with(applicationContext).asBitmap().load(oldPath).submit(newSize.x, newSize.y).get() - - val newFile = File(newPath) - val newFileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath()) - getFileOutputStream(newFileDirItem, true) { - if (it != null) { - saveBitmap(newFile, newBitmap, it, oldExif, File(oldPath).lastModified()) - } else { - toast(R.string.image_editing_failed) - } - } - } catch (e: OutOfMemoryError) { - toast(R.string.out_of_memory_error) - } catch (e: Exception) { - showErrorToast(e) - } - } - } + launchResizeImageDialog(oldPath) } @TargetApi(Build.VERSION_CODES.N) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index b784dc0f2..521cb6f76 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -144,6 +144,7 @@ class MediaAdapter( findItem(R.id.cab_open_with).isVisible = isOneItemSelected findItem(R.id.cab_edit).isVisible = isOneItemSelected findItem(R.id.cab_set_as).isVisible = isOneItemSelected + findItem(R.id.cab_resize).isVisible = selectedItems.all { it.isImage() } findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedKeys.isNotEmpty() findItem(R.id.cab_restore_recycle_bin_files).isVisible = selectedPaths.all { it.startsWith(activity.recycleBinPath) } findItem(R.id.cab_create_shortcut).isVisible = isOreoPlus() && isOneItemSelected @@ -179,6 +180,7 @@ class MediaAdapter( R.id.cab_open_with -> openPath() R.id.cab_fix_date_taken -> fixDateTaken() R.id.cab_set_as -> setAs() + R.id.cab_resize -> resize() R.id.cab_delete -> checkDeleteConfirmation() } } @@ -286,6 +288,20 @@ class MediaAdapter( activity.setAs(path) } + private fun resize() { + val paths = getSelectedPaths() + if (isOneItemSelected()) { + val path = paths.first() + activity.launchResizeImageDialog(path) { + finishActMode() + } + } else { + activity.launchResizeMultipleImagesDialog(paths) { + finishActMode() + } + } + } + private fun toggleFileVisibility(hide: Boolean) { ensureBackgroundThread { getSelectedItems().forEach { diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt new file mode 100644 index 000000000..e1b96f357 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -0,0 +1,160 @@ +package com.simplemobiletools.gallery.pro.dialogs + +import android.graphics.Point +import android.os.Handler +import android.os.Looper +import android.view.View +import androidx.appcompat.app.AlertDialog +import androidx.core.widget.doAfterTextChanged +import com.simplemobiletools.commons.activities.BaseSimpleActivity +import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.helpers.ensureBackgroundThread +import com.simplemobiletools.gallery.pro.R +import com.simplemobiletools.gallery.pro.extensions.config +import com.simplemobiletools.gallery.pro.extensions.ensureWriteAccess +import com.simplemobiletools.gallery.pro.extensions.fixDateTaken +import com.simplemobiletools.gallery.pro.extensions.resizeImage +import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_edit_text +import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_info +import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_input_layout +import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_progress +import java.io.File +import kotlin.math.roundToInt + +private const val DEFAULT_RESIZE_FACTOR = "75" +private const val RESIZE_FACTOR_ERROR_DELAY = 800L + +class ResizeMultipleImagesDialog( + private val activity: BaseSimpleActivity, + private val imagePaths: List, + private val imageSizes: List, + private val callback: () -> Unit +) { + + private var dialog: AlertDialog? = null + private val view = activity.layoutInflater.inflate(R.layout.dialog_resize_multiple_images, null) + private val progressView = view.resize_progress + private val resizeFactorEditText = view.resize_factor_edit_text + + init { + setupViews(view) + activity.getAlertDialogBuilder() + .setPositiveButton(R.string.ok, null) + .setNegativeButton(R.string.cancel, null) + .apply { + activity.setupDialogStuff(view, this, R.string.resize_multiple_images) { alertDialog -> + dialog = alertDialog + alertDialog.showKeyboard(resizeFactorEditText) + + val positiveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE) + val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) + positiveButton.setOnClickListener { + val resizeFactorText = resizeFactorEditText.text?.toString() + val resizeFactor = try { + resizeFactorText?.toFloat()?.div(100) + } catch (e: Exception) { + null + } + + if (resizeFactor == null) { + activity.toast(R.string.resize_factor_error) + return@setOnClickListener + } + + alertDialog.setCanceledOnTouchOutside(false) + arrayOf(view.resize_factor_input_layout, view.resize_factor_info, positiveButton, negativeButton).forEach { + it.isEnabled = false + it.alpha = 0.6f + } + resizeImages(resizeFactor) + } + } + } + } + + private fun resizeImages(factor: Float) { + progressView.show() + ensureBackgroundThread { + with(activity) { + val newSizes = imageSizes.map { + val width = (it.x * factor).roundToInt() + val height = (it.y * factor).roundToInt() + Point(width, height) + } + + val parentPath = imagePaths.first().getParentPath() + val pathsToRescan = arrayListOf() + + ensureWriteAccess(parentPath) { + for (i in imagePaths.indices) { + val path = imagePaths[i] + val size = newSizes[i] + + try { + resizeImage(path, size) { + if (it) { + pathsToRescan.add(path) + runOnUiThread { + progressView.progress = i + 1 + } + } + } + } catch (e: OutOfMemoryError) { + toast(R.string.out_of_memory_error) + } catch (e: Exception) { + showErrorToast(e) + } + } + + val failureCount = imagePaths.size - pathsToRescan.size + if (failureCount > 0) { + toast(getString(R.string.failed_to_resize_images, failureCount)) + } else { + toast(R.string.images_resized_successfully) + } + + rescanPaths(pathsToRescan) { + fixDateTaken(pathsToRescan, false) + for (path in pathsToRescan) { + val file = File(path) + val lastModified = file.lastModified() + if (config.keepLastModified && lastModified != 0L) { + File(file.absolutePath).setLastModified(lastModified) + updateLastModified(file.absolutePath, lastModified) + } + } + } + activity.runOnUiThread { + dialog?.dismiss() + callback.invoke() + } + } + } + } + } + + private fun setupViews(view: View) { + val handler = Handler(Looper.getMainLooper()) + val resizeFactorInputLayout = view.resize_factor_input_layout + view.resize_factor_edit_text.apply { + setText(DEFAULT_RESIZE_FACTOR) + doAfterTextChanged { + resizeFactorInputLayout.error = null + handler.removeCallbacksAndMessages(null) + handler.postDelayed({ + val factorText = it?.toString() + if (factorText.isNullOrEmpty() || factorText.toInt() !in 10..90) { + resizeFactorInputLayout.error = activity.getString(R.string.resize_factor_error) + } else { + resizeFactorInputLayout.error = null + } + }, RESIZE_FACTOR_ERROR_DELAY) + } + } + + progressView.apply { + max = imagePaths.size + setIndicatorColor(activity.getProperPrimaryColor()) + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index fe096ba67..a93311a08 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -8,6 +8,7 @@ import android.content.Intent import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Matrix +import android.graphics.Point import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.net.Uri @@ -39,6 +40,8 @@ import com.simplemobiletools.gallery.pro.activities.SettingsActivity import com.simplemobiletools.gallery.pro.activities.SimpleActivity import com.simplemobiletools.gallery.pro.dialogs.AllFilesPermissionDialog import com.simplemobiletools.gallery.pro.dialogs.PickDirectoryDialog +import com.simplemobiletools.gallery.pro.dialogs.ResizeMultipleImagesDialog +import com.simplemobiletools.gallery.pro.dialogs.ResizeWithPathDialog import com.simplemobiletools.gallery.pro.helpers.DIRECTORY import com.simplemobiletools.gallery.pro.helpers.RECYCLE_BIN import com.simplemobiletools.gallery.pro.models.DateTaken @@ -734,6 +737,124 @@ fun BaseSimpleActivity.copyFile(source: String, destination: String) { } } +fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { + when { + isRestrictedSAFOnlyRoot(path) -> { + handleAndroidSAFDialog(path) { + if (!it) { + return@handleAndroidSAFDialog + } + callback.invoke() + } + } + needsStupidWritePermissions(path) -> { + handleSAFDialog(path) { + if (!it) { + return@handleSAFDialog + } + callback() + } + } + isAccessibleWithSAFSdk30(path) -> { + handleSAFDialogSdk30(path) { + if (!it) { + return@handleSAFDialogSdk30 + } + callback() + } + } + else -> { + callback() + } + } +} + +@TargetApi(Build.VERSION_CODES.N) +fun BaseSimpleActivity.launchResizeMultipleImagesDialog(paths: List, callback: (() -> Unit)? = null) { + val imagePaths = mutableListOf() + val imageSizes = mutableListOf() + for (path in paths) { + val size = path.getImageResolution(this) + if (size != null) { + imagePaths.add(path) + imageSizes.add(size) + } + } + + ResizeMultipleImagesDialog(this, imagePaths, imageSizes) { + callback?.invoke() + } +} + +@TargetApi(Build.VERSION_CODES.N) +fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Unit)? = null) { + val originalSize = path.getImageResolution(this) ?: return + ResizeWithPathDialog(this, originalSize, path) { newSize, newPath -> + ensureBackgroundThread { + try { + resizeImage(newPath, newSize) { success -> + if (success) { + toast(R.string.file_saved) + + val file = File(path) + val lastModified = file.lastModified() + val paths = arrayListOf(file.absolutePath) + rescanPaths(paths) { + fixDateTaken(paths, false) + if (config.keepLastModified && lastModified != 0L) { + File(file.absolutePath).setLastModified(lastModified) + updateLastModified(file.absolutePath, lastModified) + } + } + + runOnUiThread { + callback?.invoke() + } + } else { + toast(R.string.image_editing_failed) + } + } + } catch (e: OutOfMemoryError) { + toast(R.string.out_of_memory_error) + } catch (e: Exception) { + showErrorToast(e) + } + } + } +} + +fun BaseSimpleActivity.resizeImage(path: String, size: Point, callback: (success: Boolean) -> Unit) { + var oldExif: ExifInterface? = null + if (isNougatPlus()) { + val inputStream = contentResolver.openInputStream(Uri.fromFile(File(path))) + oldExif = ExifInterface(inputStream!!) + } + + val newBitmap = Glide.with(applicationContext).asBitmap().load(path).submit(size.x, size.y).get() + + val newFile = File(path) + val newFileDirItem = FileDirItem(path, path.getFilenameFromPath()) + getFileOutputStream(newFileDirItem, true) { out -> + if (out != null) { + out.use { + try { + newBitmap.compress(newFile.absolutePath.getCompressionFormat(), 90, out) + + if (isNougatPlus()) { + val newExif = ExifInterface(newFile.absolutePath) + oldExif?.copyNonDimensionAttributesTo(newExif) + } + } catch (ignored: Exception) { + } + + callback(true) + } + } else { + callback(false) + } + } +} + fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream, degrees: Int) { val matrix = Matrix() matrix.postRotate(degrees.toFloat()) diff --git a/app/src/main/res/layout/dialog_resize_multiple_images.xml b/app/src/main/res/layout/dialog_resize_multiple_images.xml new file mode 100644 index 000000000..e5792fe47 --- /dev/null +++ b/app/src/main/res/layout/dialog_resize_multiple_images.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/menu/cab_media.xml b/app/src/main/res/menu/cab_media.xml index f861bac02..9be65e89d 100644 --- a/app/src/main/res/menu/cab_media.xml +++ b/app/src/main/res/menu/cab_media.xml @@ -83,6 +83,11 @@ android:showAsAction="never" android:title="@string/set_as" app:showAsAction="never" /> + Date: Wed, 24 May 2023 02:24:41 +0530 Subject: [PATCH 02/13] Add `rescanPathsAndUpdateLastModified` extension --- .../pro/dialogs/ResizeMultipleImagesDialog.kt | 16 ++--------- .../gallery/pro/extensions/Activity.kt | 27 ++++++++++++------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt index e1b96f357..cd75fd057 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -10,15 +10,13 @@ import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.gallery.pro.R -import com.simplemobiletools.gallery.pro.extensions.config import com.simplemobiletools.gallery.pro.extensions.ensureWriteAccess -import com.simplemobiletools.gallery.pro.extensions.fixDateTaken +import com.simplemobiletools.gallery.pro.extensions.rescanPathsAndUpdateLastModified import com.simplemobiletools.gallery.pro.extensions.resizeImage import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_edit_text import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_info import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_input_layout import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_progress -import java.io.File import kotlin.math.roundToInt private const val DEFAULT_RESIZE_FACTOR = "75" @@ -113,17 +111,7 @@ class ResizeMultipleImagesDialog( toast(R.string.images_resized_successfully) } - rescanPaths(pathsToRescan) { - fixDateTaken(pathsToRescan, false) - for (path in pathsToRescan) { - val file = File(path) - val lastModified = file.lastModified() - if (config.keepLastModified && lastModified != 0L) { - File(file.absolutePath).setLastModified(lastModified) - updateLastModified(file.absolutePath, lastModified) - } - } - } + rescanPathsAndUpdateLastModified(pathsToRescan) activity.runOnUiThread { dialog?.dismiss() callback.invoke() diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index a93311a08..09119dd97 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -747,6 +747,7 @@ fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { callback.invoke() } } + needsStupidWritePermissions(path) -> { handleSAFDialog(path) { if (!it) { @@ -755,6 +756,7 @@ fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { callback() } } + isAccessibleWithSAFSdk30(path) -> { handleSAFDialogSdk30(path) { if (!it) { @@ -763,6 +765,7 @@ fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { callback() } } + else -> { callback() } @@ -797,16 +800,8 @@ fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Un toast(R.string.file_saved) val file = File(path) - val lastModified = file.lastModified() val paths = arrayListOf(file.absolutePath) - rescanPaths(paths) { - fixDateTaken(paths, false) - if (config.keepLastModified && lastModified != 0L) { - File(file.absolutePath).setLastModified(lastModified) - updateLastModified(file.absolutePath, lastModified) - } - } - + rescanPathsAndUpdateLastModified(paths) runOnUiThread { callback?.invoke() } @@ -855,6 +850,20 @@ fun BaseSimpleActivity.resizeImage(path: String, size: Point, callback: (success } } +fun BaseSimpleActivity.rescanPathsAndUpdateLastModified(paths: ArrayList) { + rescanPaths(paths) { + fixDateTaken(paths, false) + for (path in paths) { + val file = File(path) + val lastModified = file.lastModified() + if (config.keepLastModified && lastModified != 0L) { + File(file.absolutePath).setLastModified(lastModified) + updateLastModified(file.absolutePath, lastModified) + } + } + } +} + fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream, degrees: Int) { val matrix = Matrix() matrix.postRotate(degrees.toFloat()) From 726e7c1649dce3877202a6f689fb17185a07b26c Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 02:31:14 +0530 Subject: [PATCH 03/13] Do processing on background thread --- .../gallery/pro/extensions/Activity.kt | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index 09119dd97..1fdecf9e6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -774,18 +774,22 @@ fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { @TargetApi(Build.VERSION_CODES.N) fun BaseSimpleActivity.launchResizeMultipleImagesDialog(paths: List, callback: (() -> Unit)? = null) { - val imagePaths = mutableListOf() - val imageSizes = mutableListOf() - for (path in paths) { - val size = path.getImageResolution(this) - if (size != null) { - imagePaths.add(path) - imageSizes.add(size) + ensureBackgroundThread { + val imagePaths = mutableListOf() + val imageSizes = mutableListOf() + for (path in paths) { + val size = path.getImageResolution(this) + if (size != null) { + imagePaths.add(path) + imageSizes.add(size) + } } - } - ResizeMultipleImagesDialog(this, imagePaths, imageSizes) { - callback?.invoke() + runOnUiThread { + ResizeMultipleImagesDialog(this, imagePaths, imageSizes) { + callback?.invoke() + } + } } } From 2919b365836da9ded0a4888eb2ecb534f9d567b2 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 03:23:36 +0530 Subject: [PATCH 04/13] Remove unnecessary text view and error handling --- .../pro/dialogs/ResizeMultipleImagesDialog.kt | 50 ++++--------------- .../layout/dialog_resize_multiple_images.xml | 18 ++----- 2 files changed, 14 insertions(+), 54 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt index cd75fd057..98a3f6925 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -1,11 +1,7 @@ package com.simplemobiletools.gallery.pro.dialogs import android.graphics.Point -import android.os.Handler -import android.os.Looper -import android.view.View import androidx.appcompat.app.AlertDialog -import androidx.core.widget.doAfterTextChanged import com.simplemobiletools.commons.activities.BaseSimpleActivity import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ensureBackgroundThread @@ -14,13 +10,11 @@ import com.simplemobiletools.gallery.pro.extensions.ensureWriteAccess import com.simplemobiletools.gallery.pro.extensions.rescanPathsAndUpdateLastModified import com.simplemobiletools.gallery.pro.extensions.resizeImage import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_edit_text -import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_info import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_input_layout import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_progress import kotlin.math.roundToInt private const val DEFAULT_RESIZE_FACTOR = "75" -private const val RESIZE_FACTOR_ERROR_DELAY = 800L class ResizeMultipleImagesDialog( private val activity: BaseSimpleActivity, @@ -35,7 +29,12 @@ class ResizeMultipleImagesDialog( private val resizeFactorEditText = view.resize_factor_edit_text init { - setupViews(view) + resizeFactorEditText.setText(DEFAULT_RESIZE_FACTOR) + progressView.apply { + max = imagePaths.size + setIndicatorColor(activity.getProperPrimaryColor()) + } + activity.getAlertDialogBuilder() .setPositiveButton(R.string.ok, null) .setNegativeButton(R.string.cancel, null) @@ -48,19 +47,15 @@ class ResizeMultipleImagesDialog( val negativeButton = alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE) positiveButton.setOnClickListener { val resizeFactorText = resizeFactorEditText.text?.toString() - val resizeFactor = try { - resizeFactorText?.toFloat()?.div(100) - } catch (e: Exception) { - null - } - - if (resizeFactor == null) { + if (resizeFactorText.isNullOrEmpty() || resizeFactorText.toInt() !in 10..90) { activity.toast(R.string.resize_factor_error) return@setOnClickListener } + val resizeFactor = resizeFactorText.toFloat().div(100) + alertDialog.setCanceledOnTouchOutside(false) - arrayOf(view.resize_factor_input_layout, view.resize_factor_info, positiveButton, negativeButton).forEach { + arrayOf(view.resize_factor_input_layout, positiveButton, negativeButton).forEach { it.isEnabled = false it.alpha = 0.6f } @@ -120,29 +115,4 @@ class ResizeMultipleImagesDialog( } } } - - private fun setupViews(view: View) { - val handler = Handler(Looper.getMainLooper()) - val resizeFactorInputLayout = view.resize_factor_input_layout - view.resize_factor_edit_text.apply { - setText(DEFAULT_RESIZE_FACTOR) - doAfterTextChanged { - resizeFactorInputLayout.error = null - handler.removeCallbacksAndMessages(null) - handler.postDelayed({ - val factorText = it?.toString() - if (factorText.isNullOrEmpty() || factorText.toInt() !in 10..90) { - resizeFactorInputLayout.error = activity.getString(R.string.resize_factor_error) - } else { - resizeFactorInputLayout.error = null - } - }, RESIZE_FACTOR_ERROR_DELAY) - } - } - - progressView.apply { - max = imagePaths.size - setIndicatorColor(activity.getProperPrimaryColor()) - } - } } diff --git a/app/src/main/res/layout/dialog_resize_multiple_images.xml b/app/src/main/res/layout/dialog_resize_multiple_images.xml index e5792fe47..047365e70 100644 --- a/app/src/main/res/layout/dialog_resize_multiple_images.xml +++ b/app/src/main/res/layout/dialog_resize_multiple_images.xml @@ -14,27 +14,17 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - - Date: Wed, 24 May 2023 03:48:16 +0530 Subject: [PATCH 05/13] Always do resize operation on background thread --- .../gallery/pro/extensions/Activity.kt | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index 1fdecf9e6..0d57b52e1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -823,33 +823,35 @@ fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Un } fun BaseSimpleActivity.resizeImage(path: String, size: Point, callback: (success: Boolean) -> Unit) { - var oldExif: ExifInterface? = null - if (isNougatPlus()) { - val inputStream = contentResolver.openInputStream(Uri.fromFile(File(path))) - oldExif = ExifInterface(inputStream!!) - } + ensureBackgroundThread { + var oldExif: ExifInterface? = null + if (isNougatPlus()) { + val inputStream = contentResolver.openInputStream(Uri.fromFile(File(path))) + oldExif = ExifInterface(inputStream!!) + } - val newBitmap = Glide.with(applicationContext).asBitmap().load(path).submit(size.x, size.y).get() + val newBitmap = Glide.with(applicationContext).asBitmap().load(path).submit(size.x, size.y).get() - val newFile = File(path) - val newFileDirItem = FileDirItem(path, path.getFilenameFromPath()) - getFileOutputStream(newFileDirItem, true) { out -> - if (out != null) { - out.use { - try { - newBitmap.compress(newFile.absolutePath.getCompressionFormat(), 90, out) + val newFile = File(path) + val newFileDirItem = FileDirItem(path, path.getFilenameFromPath()) + getFileOutputStream(newFileDirItem, true) { out -> + if (out != null) { + out.use { + try { + newBitmap.compress(newFile.absolutePath.getCompressionFormat(), 90, out) - if (isNougatPlus()) { - val newExif = ExifInterface(newFile.absolutePath) - oldExif?.copyNonDimensionAttributesTo(newExif) + if (isNougatPlus()) { + val newExif = ExifInterface(newFile.absolutePath) + oldExif?.copyNonDimensionAttributesTo(newExif) + } + } catch (ignored: Exception) { } - } catch (ignored: Exception) { - } - callback(true) + callback(true) + } + } else { + callback(false) } - } else { - callback(false) } } } From bdffa73d7d3712b75ea1634ef900137aea7b26a0 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 04:02:36 +0530 Subject: [PATCH 06/13] Filter out other files as needed before resizing --- .../gallery/pro/adapters/MediaAdapter.kt | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index 521cb6f76..6bdee1414 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -30,14 +30,9 @@ import com.simplemobiletools.gallery.pro.interfaces.MediaOperationsListener import com.simplemobiletools.gallery.pro.models.Medium import com.simplemobiletools.gallery.pro.models.ThumbnailItem import com.simplemobiletools.gallery.pro.models.ThumbnailSection -import kotlinx.android.synthetic.main.photo_item_grid.view.* -import kotlinx.android.synthetic.main.thumbnail_section.view.* +import kotlinx.android.synthetic.main.photo_item_grid.view.file_type +import kotlinx.android.synthetic.main.thumbnail_section.view.thumbnail_section import kotlinx.android.synthetic.main.video_item_grid.view.* -import kotlinx.android.synthetic.main.video_item_grid.view.favorite -import kotlinx.android.synthetic.main.video_item_grid.view.media_item_holder -import kotlinx.android.synthetic.main.video_item_grid.view.medium_check -import kotlinx.android.synthetic.main.video_item_grid.view.medium_name -import kotlinx.android.synthetic.main.video_item_grid.view.medium_thumbnail class MediaAdapter( activity: BaseSimpleActivity, var media: ArrayList, val listener: MediaOperationsListener?, val isAGetIntent: Boolean, @@ -144,7 +139,7 @@ class MediaAdapter( findItem(R.id.cab_open_with).isVisible = isOneItemSelected findItem(R.id.cab_edit).isVisible = isOneItemSelected findItem(R.id.cab_set_as).isVisible = isOneItemSelected - findItem(R.id.cab_resize).isVisible = selectedItems.all { it.isImage() } + findItem(R.id.cab_resize).isVisible = canResize(selectedItems) findItem(R.id.cab_confirm_selection).isVisible = isAGetIntent && allowMultiplePicks && selectedKeys.isNotEmpty() findItem(R.id.cab_restore_recycle_bin_files).isVisible = selectedPaths.all { it.startsWith(activity.recycleBinPath) } findItem(R.id.cab_create_shortcut).isVisible = isOreoPlus() && isOneItemSelected @@ -289,7 +284,7 @@ class MediaAdapter( } private fun resize() { - val paths = getSelectedPaths() + val paths = getSelectedItems().filter { it.isImage() }.map { it.path } if (isOneItemSelected()) { val path = paths.first() activity.launchResizeImageDialog(path) { @@ -302,6 +297,16 @@ class MediaAdapter( } } + private fun canResize(selectedItems: ArrayList): Boolean { + val selectionContainsImages = selectedItems.any { it.isImage() } + if (!selectionContainsImages) { + return false + } + val parentPath = selectedItems.first { it.isImage() }.path.getParentPath() + val isRestrictedDir = activity.isRestrictedWithSAFSdk30(parentPath) + return !isRestrictedDir + } + private fun toggleFileVisibility(hide: Boolean) { ensureBackgroundThread { getSelectedItems().forEach { From a1fca17516551c40a3432b7513dd358d04560562 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 04:06:45 +0530 Subject: [PATCH 07/13] Use plural string --- .../gallery/pro/dialogs/ResizeMultipleImagesDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt index 98a3f6925..3d2654a0b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -101,7 +101,7 @@ class ResizeMultipleImagesDialog( val failureCount = imagePaths.size - pathsToRescan.size if (failureCount > 0) { - toast(getString(R.string.failed_to_resize_images, failureCount)) + toast(resources.getQuantityString(R.plurals.failed_to_resize_images, failureCount, failureCount)) } else { toast(R.string.images_resized_successfully) } From 591e5f09e90570d96001823438ebbfa7bf4778ef Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 04:20:44 +0530 Subject: [PATCH 08/13] Fix `resizeImage()` threading issue --- .../pro/dialogs/ResizeMultipleImagesDialog.kt | 20 ++++----- .../gallery/pro/extensions/Activity.kt | 44 +++++++++---------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt index 3d2654a0b..df13c5626 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -67,18 +67,18 @@ class ResizeMultipleImagesDialog( private fun resizeImages(factor: Float) { progressView.show() - ensureBackgroundThread { - with(activity) { - val newSizes = imageSizes.map { - val width = (it.x * factor).roundToInt() - val height = (it.y * factor).roundToInt() - Point(width, height) - } + with(activity) { + val newSizes = imageSizes.map { + val width = (it.x * factor).roundToInt() + val height = (it.y * factor).roundToInt() + Point(width, height) + } - val parentPath = imagePaths.first().getParentPath() - val pathsToRescan = arrayListOf() + val parentPath = imagePaths.first().getParentPath() + val pathsToRescan = arrayListOf() - ensureWriteAccess(parentPath) { + ensureWriteAccess(parentPath) { + ensureBackgroundThread { for (i in imagePaths.indices) { val path = imagePaths[i] val size = newSizes[i] diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index 0d57b52e1..1fdecf9e6 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -823,35 +823,33 @@ fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Un } fun BaseSimpleActivity.resizeImage(path: String, size: Point, callback: (success: Boolean) -> Unit) { - ensureBackgroundThread { - var oldExif: ExifInterface? = null - if (isNougatPlus()) { - val inputStream = contentResolver.openInputStream(Uri.fromFile(File(path))) - oldExif = ExifInterface(inputStream!!) - } + var oldExif: ExifInterface? = null + if (isNougatPlus()) { + val inputStream = contentResolver.openInputStream(Uri.fromFile(File(path))) + oldExif = ExifInterface(inputStream!!) + } - val newBitmap = Glide.with(applicationContext).asBitmap().load(path).submit(size.x, size.y).get() + val newBitmap = Glide.with(applicationContext).asBitmap().load(path).submit(size.x, size.y).get() - val newFile = File(path) - val newFileDirItem = FileDirItem(path, path.getFilenameFromPath()) - getFileOutputStream(newFileDirItem, true) { out -> - if (out != null) { - out.use { - try { - newBitmap.compress(newFile.absolutePath.getCompressionFormat(), 90, out) + val newFile = File(path) + val newFileDirItem = FileDirItem(path, path.getFilenameFromPath()) + getFileOutputStream(newFileDirItem, true) { out -> + if (out != null) { + out.use { + try { + newBitmap.compress(newFile.absolutePath.getCompressionFormat(), 90, out) - if (isNougatPlus()) { - val newExif = ExifInterface(newFile.absolutePath) - oldExif?.copyNonDimensionAttributesTo(newExif) - } - } catch (ignored: Exception) { + if (isNougatPlus()) { + val newExif = ExifInterface(newFile.absolutePath) + oldExif?.copyNonDimensionAttributesTo(newExif) } - - callback(true) + } catch (ignored: Exception) { } - } else { - callback(false) + + callback(true) } + } else { + callback(false) } } } From 295793c77f067733951df9f79fd1d00ae65a4679 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 04:34:36 +0530 Subject: [PATCH 09/13] Remove unused code --- .../pro/activities/ViewPagerActivity.kt | 26 ------------------- .../gallery/pro/extensions/Activity.kt | 2 -- 2 files changed, 28 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt index 220984953..64365f414 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/activities/ViewPagerActivity.kt @@ -1045,37 +1045,11 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View } } - @TargetApi(Build.VERSION_CODES.N) private fun resizeImage() { val oldPath = getCurrentPath() launchResizeImageDialog(oldPath) } - @TargetApi(Build.VERSION_CODES.N) - private fun saveBitmap(file: File, bitmap: Bitmap, out: OutputStream, oldExif: ExifInterface?, lastModified: Long) { - try { - bitmap.compress(file.absolutePath.getCompressionFormat(), 90, out) - - if (isNougatPlus()) { - val newExif = ExifInterface(file.absolutePath) - oldExif?.copyNonDimensionAttributesTo(newExif) - } - } catch (e: Exception) { - } - - toast(R.string.file_saved) - val paths = arrayListOf(file.absolutePath) - rescanPaths(paths) { - fixDateTaken(paths, false) - - if (config.keepLastModified && lastModified != 0L) { - File(file.absolutePath).setLastModified(lastModified) - updateLastModified(file.absolutePath, lastModified) - } - } - out.close() - } - private fun checkDeleteConfirmation() { if (getCurrentMedium() == null) { return diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index 1fdecf9e6..ac66ecafb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -772,7 +772,6 @@ fun BaseSimpleActivity.ensureWriteAccess(path: String, callback: () -> Unit) { } } -@TargetApi(Build.VERSION_CODES.N) fun BaseSimpleActivity.launchResizeMultipleImagesDialog(paths: List, callback: (() -> Unit)? = null) { ensureBackgroundThread { val imagePaths = mutableListOf() @@ -793,7 +792,6 @@ fun BaseSimpleActivity.launchResizeMultipleImagesDialog(paths: List, cal } } -@TargetApi(Build.VERSION_CODES.N) fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Unit)? = null) { val originalSize = path.getImageResolution(this) ?: return ResizeWithPathDialog(this, originalSize, path) { newSize, newPath -> From ad10f4123f1e8c4533d11fb501d064be10bab551 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 24 May 2023 04:53:15 +0530 Subject: [PATCH 10/13] Only allow resizing multiple images with common parents Otherwise we'll have to create multiple SAF dialogs which just isn't practical/tedious for the user. Users can still resize images without common parents if they grant "All Files" access --- .../simplemobiletools/gallery/pro/adapters/MediaAdapter.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index 6bdee1414..b906e3745 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -302,9 +302,11 @@ class MediaAdapter( if (!selectionContainsImages) { return false } - val parentPath = selectedItems.first { it.isImage() }.path.getParentPath() + + val parentPath = selectedItems.first { it.isImage() }.parentPath + val isCommonParent = selectedItems.all { parentPath == it.parentPath } val isRestrictedDir = activity.isRestrictedWithSAFSdk30(parentPath) - return !isRestrictedDir + return isExternalStorageManager() || (isCommonParent && !isRestrictedDir) } private fun toggleFileVisibility(hide: Boolean) { From d9fcb1fc90638fe098489258de981a5495fc4010 Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 25 May 2023 13:39:35 +0530 Subject: [PATCH 11/13] Use the string resource! --- app/src/main/res/layout/dialog_resize_multiple_images.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/dialog_resize_multiple_images.xml b/app/src/main/res/layout/dialog_resize_multiple_images.xml index 047365e70..a9aa638fe 100644 --- a/app/src/main/res/layout/dialog_resize_multiple_images.xml +++ b/app/src/main/res/layout/dialog_resize_multiple_images.xml @@ -22,7 +22,7 @@ android:layout_marginTop="@dimen/normal_margin" android:hint="@string/resize_factor" app:errorEnabled="true" - app:helperText="Resize images to the given percentage, value must be within 10 and 90" + app:helperText="@string/resize_factor_info" app:helperTextEnabled="true" app:layout_constraintTop_toBottomOf="@id/resize_progress" app:suffixText="%"> From 799689ab7ed688b1e0375b6b18b85e012dffc56c Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 25 May 2023 14:20:37 +0530 Subject: [PATCH 12/13] Refresh items after resizing --- .../com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt index b906e3745..a19d09394 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/adapters/MediaAdapter.kt @@ -289,10 +289,12 @@ class MediaAdapter( val path = paths.first() activity.launchResizeImageDialog(path) { finishActMode() + listener?.refreshItems() } } else { activity.launchResizeMultipleImagesDialog(paths) { finishActMode() + listener?.refreshItems() } } } From 761ebee77bc926cde82283b72b036bdfd1075ba8 Mon Sep 17 00:00:00 2001 From: Naveen Date: Sat, 27 May 2023 16:44:50 +0530 Subject: [PATCH 13/13] Rescan paths after updating modified time --- .../pro/dialogs/ResizeMultipleImagesDialog.kt | 13 ++++++--- .../gallery/pro/extensions/Activity.kt | 29 ++++++++++--------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt index df13c5626..6066accde 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/dialogs/ResizeMultipleImagesDialog.kt @@ -12,6 +12,7 @@ import com.simplemobiletools.gallery.pro.extensions.resizeImage import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_edit_text import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_factor_input_layout import kotlinx.android.synthetic.main.dialog_resize_multiple_images.view.resize_progress +import java.io.File import kotlin.math.roundToInt private const val DEFAULT_RESIZE_FACTOR = "75" @@ -76,17 +77,20 @@ class ResizeMultipleImagesDialog( val parentPath = imagePaths.first().getParentPath() val pathsToRescan = arrayListOf() + val pathLastModifiedMap = mutableMapOf() ensureWriteAccess(parentPath) { ensureBackgroundThread { for (i in imagePaths.indices) { val path = imagePaths[i] val size = newSizes[i] + val lastModified = File(path).lastModified() try { resizeImage(path, size) { if (it) { pathsToRescan.add(path) + pathLastModifiedMap[path] = lastModified runOnUiThread { progressView.progress = i + 1 } @@ -106,10 +110,11 @@ class ResizeMultipleImagesDialog( toast(R.string.images_resized_successfully) } - rescanPathsAndUpdateLastModified(pathsToRescan) - activity.runOnUiThread { - dialog?.dismiss() - callback.invoke() + rescanPathsAndUpdateLastModified(pathsToRescan, pathLastModifiedMap) { + activity.runOnUiThread { + dialog?.dismiss() + callback.invoke() + } } } } diff --git a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt index ac66ecafb..c6519fcbc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/gallery/pro/extensions/Activity.kt @@ -796,16 +796,18 @@ fun BaseSimpleActivity.launchResizeImageDialog(path: String, callback: (() -> Un val originalSize = path.getImageResolution(this) ?: return ResizeWithPathDialog(this, originalSize, path) { newSize, newPath -> ensureBackgroundThread { + val file = File(newPath) + val pathLastModifiedMap = mapOf(file.absolutePath to file.lastModified()) try { resizeImage(newPath, newSize) { success -> if (success) { toast(R.string.file_saved) - val file = File(path) val paths = arrayListOf(file.absolutePath) - rescanPathsAndUpdateLastModified(paths) - runOnUiThread { - callback?.invoke() + rescanPathsAndUpdateLastModified(paths, pathLastModifiedMap) { + runOnUiThread { + callback?.invoke() + } } } else { toast(R.string.image_editing_failed) @@ -852,18 +854,17 @@ fun BaseSimpleActivity.resizeImage(path: String, size: Point, callback: (success } } -fun BaseSimpleActivity.rescanPathsAndUpdateLastModified(paths: ArrayList) { - rescanPaths(paths) { - fixDateTaken(paths, false) - for (path in paths) { - val file = File(path) - val lastModified = file.lastModified() - if (config.keepLastModified && lastModified != 0L) { - File(file.absolutePath).setLastModified(lastModified) - updateLastModified(file.absolutePath, lastModified) - } +fun BaseSimpleActivity.rescanPathsAndUpdateLastModified(paths: ArrayList, pathLastModifiedMap: Map, callback: () -> Unit) { + fixDateTaken(paths, false) + for (path in paths) { + val file = File(path) + val lastModified = pathLastModifiedMap[path] + if (config.keepLastModified && lastModified != null && lastModified != 0L) { + File(file.absolutePath).setLastModified(lastModified) + updateLastModified(file.absolutePath, lastModified) } } + rescanPaths(paths, callback) } fun saveFile(path: String, bitmap: Bitmap, out: FileOutputStream, degrees: Int) {