Merge pull request #2876 from fatihergin/feature/adding-skip-recycle-bin-option-for-deleting-medias-immediately

allow skipping recycle bin at deletion
This commit is contained in:
Tibor Kaputa 2023-06-18 20:12:32 +02:00 committed by GitHub
commit d4eeaf3fdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 65 additions and 29 deletions

View file

@ -92,6 +92,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
config.temporarilyShowHidden = false config.temporarilyShowHidden = false
config.temporarilyShowExcluded = false config.temporarilyShowExcluded = false
config.tempSkipDeleteConfirmation = false config.tempSkipDeleteConfirmation = false
config.tempSkipRecycleBin = false
removeTempFolder() removeTempFolder()
checkRecycleBinItems() checkRecycleBinItems()
startNewPhotoFetcher() startNewPhotoFetcher()
@ -270,6 +271,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
config.temporarilyShowHidden = false config.temporarilyShowHidden = false
config.temporarilyShowExcluded = false config.temporarilyShowExcluded = false
config.tempSkipDeleteConfirmation = false config.tempSkipDeleteConfirmation = false
config.tempSkipRecycleBin = false
}, SHOW_TEMP_HIDDEN_DURATION) }, SHOW_TEMP_HIDDEN_DURATION)
} else { } else {
mTempShowHiddenHandler.removeCallbacksAndMessages(null) mTempShowHiddenHandler.removeCallbacksAndMessages(null)
@ -282,6 +284,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
config.temporarilyShowHidden = false config.temporarilyShowHidden = false
config.temporarilyShowExcluded = false config.temporarilyShowExcluded = false
config.tempSkipDeleteConfirmation = false config.tempSkipDeleteConfirmation = false
config.tempSkipRecycleBin = false
mTempShowHiddenHandler.removeCallbacksAndMessages(null) mTempShowHiddenHandler.removeCallbacksAndMessages(null)
removeTempFolder() removeTempFolder()
unregisterFileUpdateListener() unregisterFileUpdateListener()
@ -319,6 +322,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true && intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0 -> { intent.extras?.containsKey(MediaStore.EXTRA_OUTPUT) == true && intent.flags and Intent.FLAG_GRANT_WRITE_URI_PERMISSION != 0 -> {
resultUri = fillExtraOutput(resultData) resultUri = fillExtraOutput(resultData)
} }
resultData.extras?.containsKey(PICKED_PATHS) == true -> fillPickedPaths(resultData, resultIntent) resultData.extras?.containsKey(PICKED_PATHS) == true -> fillPickedPaths(resultData, resultIntent)
else -> fillIntentPath(resultData, resultIntent) else -> fillIntentPath(resultData, resultIntent)
} }
@ -645,8 +649,9 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
showErrorToast(e) showErrorToast(e)
} }
} }
else -> { else -> {
val baseString = if (config.useRecycleBin) R.plurals.moving_items_into_bin else R.plurals.delete_items val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin) R.plurals.moving_items_into_bin else R.plurals.delete_items
val deletingItems = resources.getQuantityString(baseString, fileDirItems.size, fileDirItems.size) val deletingItems = resources.getQuantityString(baseString, fileDirItems.size, fileDirItems.size)
toast(deletingItems) toast(deletingItems)
} }
@ -667,7 +672,7 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
}?.mapTo(itemsToDelete) { it.toFileDirItem(applicationContext) } }?.mapTo(itemsToDelete) { it.toFileDirItem(applicationContext) }
} }
if (config.useRecycleBin) { if (config.useRecycleBin && !config.tempSkipRecycleBin) {
val pathsToDelete = ArrayList<String>() val pathsToDelete = ArrayList<String>()
itemsToDelete.mapTo(pathsToDelete) { it.path } itemsToDelete.mapTo(pathsToDelete) { it.path }

View file

@ -208,6 +208,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
mTempShowHiddenHandler.postDelayed({ mTempShowHiddenHandler.postDelayed({
config.temporarilyShowHidden = false config.temporarilyShowHidden = false
config.tempSkipDeleteConfirmation = false config.tempSkipDeleteConfirmation = false
config.tempSkipRecycleBin = false
}, SHOW_TEMP_HIDDEN_DURATION) }, SHOW_TEMP_HIDDEN_DURATION)
} else { } else {
mTempShowHiddenHandler.removeCallbacksAndMessages(null) mTempShowHiddenHandler.removeCallbacksAndMessages(null)
@ -219,6 +220,7 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
if (config.showAll && !isChangingConfigurations) { if (config.showAll && !isChangingConfigurations) {
config.temporarilyShowHidden = false config.temporarilyShowHidden = false
config.tempSkipDeleteConfirmation = false config.tempSkipDeleteConfirmation = false
config.tempSkipRecycleBin = false
unregisterFileUpdateListener() unregisterFileUpdateListener()
GalleryDatabase.destroyInstance() GalleryDatabase.destroyInstance()
} }
@ -885,13 +887,13 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
} }
override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>) { override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>, skipRecycleBin: Boolean) {
val filtered = fileDirItems.filter { !getIsPathDirectory(it.path) && it.path.isMediaFile() } as ArrayList val filtered = fileDirItems.filter { !getIsPathDirectory(it.path) && it.path.isMediaFile() } as ArrayList
if (filtered.isEmpty()) { if (filtered.isEmpty()) {
return return
} }
if (config.useRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) { if (config.useRecycleBin && !skipRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) {
val movingItems = resources.getQuantityString(R.plurals.moving_items_into_bin, filtered.size, filtered.size) val movingItems = resources.getQuantityString(R.plurals.moving_items_into_bin, filtered.size, filtered.size)
toast(movingItems) toast(movingItems)

View file

@ -237,13 +237,13 @@ class SearchActivity : SimpleActivity(), MediaOperationsListener {
startAsyncTask(true) startAsyncTask(true)
} }
override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>) { override fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>, skipRecycleBin: Boolean) {
val filtered = fileDirItems.filter { File(it.path).isFile && it.path.isMediaFile() } as ArrayList val filtered = fileDirItems.filter { File(it.path).isFile && it.path.isMediaFile() } as ArrayList
if (filtered.isEmpty()) { if (filtered.isEmpty()) {
return return
} }
if (config.useRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) { if (config.useRecycleBin && !skipRecycleBin && !filtered.first().path.startsWith(recycleBinPath)) {
val movingItems = resources.getQuantityString(R.plurals.moving_items_into_bin, filtered.size, filtered.size) val movingItems = resources.getQuantityString(R.plurals.moving_items_into_bin, filtered.size, filtered.size)
toast(movingItems) toast(movingItems)

View file

@ -3,7 +3,6 @@ package com.simplemobiletools.gallery.pro.activities
import android.animation.Animator import android.animation.Animator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity import android.app.Activity
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
@ -16,7 +15,6 @@ import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Icon import android.graphics.drawable.Icon
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.provider.MediaStore.Images import android.provider.MediaStore.Images
@ -58,7 +56,6 @@ import com.simplemobiletools.gallery.pro.models.ThumbnailItem
import kotlinx.android.synthetic.main.activity_medium.* import kotlinx.android.synthetic.main.activity_medium.*
import kotlinx.android.synthetic.main.bottom_actions.* import kotlinx.android.synthetic.main.bottom_actions.*
import java.io.File import java.io.File
import java.io.OutputStream
import kotlin.math.min import kotlin.math.min
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@ -1058,10 +1055,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
handleMediaManagementPrompt { handleMediaManagementPrompt {
if (config.isDeletePasswordProtectionOn) { if (config.isDeletePasswordProtectionOn) {
handleDeletePasswordProtection { handleDeletePasswordProtection {
deleteConfirmed() deleteConfirmed(config.tempSkipRecycleBin)
} }
} else if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) { } else if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) {
deleteConfirmed() deleteConfirmed(config.tempSkipRecycleBin)
} else { } else {
askConfirmDelete() askConfirmDelete()
} }
@ -1074,20 +1071,25 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
val filename = "\"${getCurrentPath().getFilenameFromPath()}\"" val filename = "\"${getCurrentPath().getFilenameFromPath()}\""
val filenameAndSize = "$filename ($size)" val filenameAndSize = "$filename ($size)"
val baseString = if (config.useRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) { val baseString = if (config.useRecycleBin && !config.tempSkipRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) {
R.string.move_to_recycle_bin_confirmation R.string.move_to_recycle_bin_confirmation
} else { } else {
R.string.deletion_confirmation R.string.deletion_confirmation
} }
val message = String.format(resources.getString(baseString), filenameAndSize) val message = String.format(resources.getString(baseString), filenameAndSize)
DeleteWithRememberDialog(this, message) { DeleteWithRememberDialog(this, message, config.useRecycleBin) { remember, skipRecycleBin ->
config.tempSkipDeleteConfirmation = it config.tempSkipDeleteConfirmation = remember
deleteConfirmed()
if (remember) {
config.tempSkipRecycleBin = skipRecycleBin
}
deleteConfirmed(skipRecycleBin)
} }
} }
private fun deleteConfirmed() { private fun deleteConfirmed(skipRecycleBin: Boolean) {
val currentMedium = getCurrentMedium() val currentMedium = getCurrentMedium()
val path = currentMedium?.path ?: return val path = currentMedium?.path ?: return
if (getIsPathDirectory(path) || !path.isMediaFile()) { if (getIsPathDirectory(path) || !path.isMediaFile()) {
@ -1095,7 +1097,7 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
} }
val fileDirItem = currentMedium.toFileDirItem() val fileDirItem = currentMedium.toFileDirItem()
if (config.useRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) { if (config.useRecycleBin && !skipRecycleBin && !getCurrentMedium()!!.getIsInRecycleBin()) {
checkManageMediaOrHandleSAFDialogSdk30(fileDirItem.path) { checkManageMediaOrHandleSAFDialogSdk30(fileDirItem.path) {
if (!it) { if (!it) {
return@checkManageMediaOrHandleSAFDialogSdk30 return@checkManageMediaOrHandleSAFDialogSdk30

View file

@ -601,7 +601,7 @@ class DirectoryAdapter(
} }
val fileDirItem = getFirstSelectedItem() ?: return val fileDirItem = getFirstSelectedItem() ?: return
val baseString = if (!config.useRecycleBin || (isOneItemSelected() && fileDirItem.areFavorites())) { val baseString = if (!config.useRecycleBin || config.tempSkipRecycleBin || (isOneItemSelected() && fileDirItem.areFavorites())) {
R.string.deletion_confirmation R.string.deletion_confirmation
} else { } else {
R.string.move_to_recycle_bin_confirmation R.string.move_to_recycle_bin_confirmation

View file

@ -474,10 +474,10 @@ class MediaAdapter(
activity.handleMediaManagementPrompt { activity.handleMediaManagementPrompt {
if (config.isDeletePasswordProtectionOn) { if (config.isDeletePasswordProtectionOn) {
activity.handleDeletePasswordProtection { activity.handleDeletePasswordProtection {
deleteFiles() deleteFiles(config.tempSkipRecycleBin)
} }
} else if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) { } else if (config.tempSkipDeleteConfirmation || config.skipDeleteConfirmation) {
deleteFiles() deleteFiles(config.tempSkipRecycleBin)
} else { } else {
askConfirmDelete() askConfirmDelete()
} }
@ -505,15 +505,22 @@ class MediaAdapter(
} }
val isRecycleBin = firstPath.startsWith(activity.recycleBinPath) val isRecycleBin = firstPath.startsWith(activity.recycleBinPath)
val baseString = if (config.useRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation val baseString =
if (config.useRecycleBin && !config.tempSkipRecycleBin && !isRecycleBin) R.string.move_to_recycle_bin_confirmation else R.string.deletion_confirmation
val question = String.format(resources.getString(baseString), itemsAndSize) val question = String.format(resources.getString(baseString), itemsAndSize)
DeleteWithRememberDialog(activity, question) {
config.tempSkipDeleteConfirmation = it DeleteWithRememberDialog(activity, question, config.useRecycleBin) { remember, skipRecycleBin ->
deleteFiles() config.tempSkipDeleteConfirmation = remember
if (remember) {
config.tempSkipRecycleBin = skipRecycleBin
}
deleteFiles(skipRecycleBin)
} }
} }
private fun deleteFiles() { private fun deleteFiles(skipRecycleBin: Boolean) {
if (selectedKeys.isEmpty()) { if (selectedKeys.isEmpty()) {
return return
} }
@ -542,7 +549,7 @@ class MediaAdapter(
} }
media.removeAll(removeMedia) media.removeAll(removeMedia)
listener?.tryDeleteFiles(fileDirItems) listener?.tryDeleteFiles(fileDirItems, skipRecycleBin)
listener?.updateMediaGridDecoration(media) listener?.updateMediaGridDecoration(media)
removeSelectedItems(positions) removeSelectedItems(positions)
currentMediaHash = media.hashCode() currentMediaHash = media.hashCode()

View file

@ -2,17 +2,25 @@ package com.simplemobiletools.gallery.pro.dialogs
import android.app.Activity import android.app.Activity
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.gallery.pro.R import com.simplemobiletools.gallery.pro.R
import kotlinx.android.synthetic.main.dialog_delete_with_remember.view.* import kotlinx.android.synthetic.main.dialog_delete_with_remember.view.*
class DeleteWithRememberDialog(val activity: Activity, val message: String, val callback: (remember: Boolean) -> Unit) { class DeleteWithRememberDialog(
private val activity: Activity,
private val message: String,
private val showSkipRecycleBinOption: Boolean,
private val callback: (remember: Boolean, skipRecycleBin: Boolean) -> Unit
) {
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_with_remember, null)!! val view = activity.layoutInflater.inflate(R.layout.dialog_delete_with_remember, null)!!
init { init {
view.delete_remember_title.text = message view.delete_remember_title.text = message
view.skip_the_recycle_bin_checkbox.beGoneIf(!showSkipRecycleBinOption)
activity.getAlertDialogBuilder() activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { dialog, which -> dialogConfirmed() } .setPositiveButton(R.string.yes) { dialog, which -> dialogConfirmed() }
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
@ -25,6 +33,6 @@ class DeleteWithRememberDialog(val activity: Activity, val message: String, val
private fun dialogConfirmed() { private fun dialogConfirmed() {
dialog?.dismiss() dialog?.dismiss()
callback(view.delete_remember_checkbox.isChecked) callback(view.delete_remember_checkbox.isChecked, view.skip_the_recycle_bin_checkbox.isChecked)
} }
} }

View file

@ -367,6 +367,10 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getBoolean(TEMP_SKIP_DELETE_CONFIRMATION, false) get() = prefs.getBoolean(TEMP_SKIP_DELETE_CONFIRMATION, false)
set(tempSkipDeleteConfirmation) = prefs.edit().putBoolean(TEMP_SKIP_DELETE_CONFIRMATION, tempSkipDeleteConfirmation).apply() set(tempSkipDeleteConfirmation) = prefs.edit().putBoolean(TEMP_SKIP_DELETE_CONFIRMATION, tempSkipDeleteConfirmation).apply()
var tempSkipRecycleBin: Boolean
get() = prefs.getBoolean(TEMP_SKIP_RECYCLE_BIN, false)
set(tempSkipRecycleBin) = prefs.edit().putBoolean(TEMP_SKIP_RECYCLE_BIN, tempSkipRecycleBin).apply()
var wereFavoritesPinned: Boolean var wereFavoritesPinned: Boolean
get() = prefs.getBoolean(WERE_FAVORITES_PINNED, false) get() = prefs.getBoolean(WERE_FAVORITES_PINNED, false)
set(wereFavoritesPinned) = prefs.edit().putBoolean(WERE_FAVORITES_PINNED, wereFavoritesPinned).apply() set(wereFavoritesPinned) = prefs.edit().putBoolean(WERE_FAVORITES_PINNED, wereFavoritesPinned).apply()

View file

@ -57,6 +57,7 @@ const val ALLOW_INSTANT_CHANGE = "allow_instant_change"
const val WAS_NEW_APP_SHOWN = "was_new_app_shown_clock" const val WAS_NEW_APP_SHOWN = "was_new_app_shown_clock"
const val LAST_FILEPICKER_PATH = "last_filepicker_path" const val LAST_FILEPICKER_PATH = "last_filepicker_path"
const val TEMP_SKIP_DELETE_CONFIRMATION = "temp_skip_delete_confirmation" const val TEMP_SKIP_DELETE_CONFIRMATION = "temp_skip_delete_confirmation"
const val TEMP_SKIP_RECYCLE_BIN = "temp_skip_recycle_bin"
const val BOTTOM_ACTIONS = "bottom_actions" const val BOTTOM_ACTIONS = "bottom_actions"
const val LAST_VIDEO_POSITION_PREFIX = "last_video_position_" const val LAST_VIDEO_POSITION_PREFIX = "last_video_position_"
const val VISIBLE_BOTTOM_ACTIONS = "visible_bottom_actions" const val VISIBLE_BOTTOM_ACTIONS = "visible_bottom_actions"

View file

@ -6,7 +6,7 @@ import com.simplemobiletools.gallery.pro.models.ThumbnailItem
interface MediaOperationsListener { interface MediaOperationsListener {
fun refreshItems() fun refreshItems()
fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>) fun tryDeleteFiles(fileDirItems: ArrayList<FileDirItem>, skipRecycleBin: Boolean)
fun selectedPaths(paths: ArrayList<String>) fun selectedPaths(paths: ArrayList<String>)

View file

@ -23,4 +23,11 @@
android:layout_below="@+id/delete_remember_title" android:layout_below="@+id/delete_remember_title"
android:text="@string/do_not_ask_again" /> android:text="@string/do_not_ask_again" />
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/skip_the_recycle_bin_checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/delete_remember_checkbox"
android:text="@string/skip_the_recycle_bin" />
</RelativeLayout> </RelativeLayout>