show a conflict resolution dialog if the destination file exists

This commit is contained in:
tibbi 2018-01-29 12:11:22 +01:00
parent 8d61261060
commit 52ea376602
5 changed files with 71 additions and 8 deletions

View file

@ -19,6 +19,7 @@ import android.view.WindowManager
import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.asynctasks.CopyMoveTask
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.FileConflictDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.APP_LICENSES
import com.simplemobiletools.commons.helpers.APP_NAME
@ -184,12 +185,10 @@ open class BaseSimpleActivity : AppCompatActivity() {
handleSAFDialog(destinationFolder) {
copyMoveCallback = callback
if (isCopyOperation) {
toast(R.string.copying)
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
} else {
if (isPathOnSD(source) || isPathOnSD(destination) || files.first().isDirectory || isNougatPlus()) {
handleSAFDialog(File(source)) {
toast(R.string.moving)
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
}
} else {
@ -222,8 +221,35 @@ open class BaseSimpleActivity : AppCompatActivity() {
}
private fun startCopyMove(files: ArrayList<File>, destinationFolder: File, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean) {
val pair = Pair(files, destinationFolder)
CopyMoveTask(this, isCopyOperation, copyPhotoVideoOnly, copyMoveListener).execute(pair)
checkConflict(files, destinationFolder, 0, LinkedHashMap()) {
toast(if (isCopyOperation) R.string.copying else R.string.moving)
val pair = Pair(files, destinationFolder)
CopyMoveTask(this, isCopyOperation, copyPhotoVideoOnly, it, copyMoveListener).execute(pair)
}
}
private fun checkConflict(files: ArrayList<File>, destinationFolder: File, index: Int, conflictResolutions: LinkedHashMap<String, Int>,
callback: (resolutions: LinkedHashMap<String, Int>) -> Unit) {
if (index == files.size) {
callback(conflictResolutions)
return
}
val file = files[index]
if (file.exists()) {
FileConflictDialog(this, file.name) { resolution, applyForAll ->
if (applyForAll) {
conflictResolutions.clear()
conflictResolutions[""] = resolution
checkConflict(files, destinationFolder, files.size, conflictResolutions, callback)
} else {
conflictResolutions[file.absolutePath] = resolution
checkConflict(files, destinationFolder, index + 1, conflictResolutions, callback)
}
}
} else {
checkConflict(files, destinationFolder, index + 1, conflictResolutions, callback)
}
}
fun handlePermission(permissionId: Int, callback: (granted: Boolean) -> Unit) {

View file

@ -16,7 +16,7 @@ import java.io.OutputStream
import java.lang.ref.WeakReference
import java.util.*
class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = false, val copyMediaOnly: Boolean,
class CopyMoveTask(val activity: BaseSimpleActivity, val copyOnly: Boolean = false, val copyMediaOnly: Boolean, val conflictResolutions: LinkedHashMap<String, Int>,
listener: CopyMoveListener) : AsyncTask<Pair<ArrayList<File>, File>, Void, Boolean>() {
private var mListener: WeakReference<CopyMoveListener>? = null
private var mMovedFiles: ArrayList<File> = ArrayList()

View file

@ -3,20 +3,47 @@ package com.simplemobiletools.commons.dialogs
import android.app.Activity
import android.support.v7.app.AlertDialog
import com.simplemobiletools.commons.R
import com.simplemobiletools.commons.R.id.conflict_dialog_radio_skip
import com.simplemobiletools.commons.extensions.baseConfig
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.commons.helpers.CONFLICT_OVERWRITE
import com.simplemobiletools.commons.helpers.CONFLICT_SKIP
import kotlinx.android.synthetic.main.dialog_file_conflict.view.*
class FileConflictDialog(val activity: Activity, val filename: String) {
class FileConflictDialog(val activity: Activity, val filename: String, val callback: (resolution: Int, applyForAll: Boolean) -> Unit) {
val view = activity.layoutInflater.inflate(R.layout.dialog_file_conflict, null)
init {
val view = activity.layoutInflater.inflate(R.layout.dialog_file_conflict, null).apply {
view.apply {
conflict_dialog_title.text = String.format(activity.getString(R.string.file_already_exists), filename)
conflict_dialog_apply_to_all.isChecked = activity.baseConfig.lastConflictApplyToAll
val resolutionButton = when (activity.baseConfig.lastConflictResolution) {
CONFLICT_OVERWRITE -> conflict_dialog_radio_overwrite
else -> conflict_dialog_radio_skip
}
resolutionButton.isChecked = true
}
AlertDialog.Builder(activity)
.setPositiveButton(R.string.ok, { dialog, which -> })
.setPositiveButton(R.string.ok, { dialog, which -> dialogConfirmed() })
.setNegativeButton(R.string.cancel, null)
.create().apply {
activity.setupDialogStuff(view, this)
}
}
private fun dialogConfirmed() {
val resolution = when (view.conflict_dialog_radio_group.checkedRadioButtonId) {
conflict_dialog_radio_skip -> CONFLICT_SKIP
else -> CONFLICT_OVERWRITE
}
val applyToAll = view.conflict_dialog_apply_to_all.isChecked
activity.baseConfig.apply {
lastConflictApplyToAll = applyToAll
lastConflictResolution = resolution
}
callback(resolution, applyToAll)
}
}

View file

@ -131,4 +131,12 @@ open class BaseConfig(val context: Context) {
var showInfoBubble: Boolean
get() = prefs.getBoolean(SHOW_INFO_BUBBLE, true)
set(showInfoBubble) = prefs.edit().putBoolean(SHOW_INFO_BUBBLE, showInfoBubble).apply()
var lastConflictApplyToAll: Boolean
get() = prefs.getBoolean(LAST_CONFLICT_APPLY_TO_ALL, true)
set(lastConflictApplyToAll) = prefs.edit().putBoolean(LAST_CONFLICT_APPLY_TO_ALL, lastConflictApplyToAll).apply()
var lastConflictResolution: Int
get() = prefs.getInt(LAST_CONFLICT_RESOLUTION, CONFLICT_SKIP)
set(lastConflictResolution) = prefs.edit().putInt(LAST_CONFLICT_RESOLUTION, lastConflictResolution).apply()
}

View file

@ -38,6 +38,8 @@ const val WAS_CUSTOM_THEME_SWITCH_DESCRIPTION_SHOWN = "was_custom_theme_switch_d
const val WAS_SHARED_THEME_AFTER_UPDATE_CHECKED = "was_shared_theme_after_update_checked"
const val SHOW_INFO_BUBBLE = "show_info_bubble"
const val SORTING = "sorting"
const val LAST_CONFLICT_RESOLUTION = "last_conflict_resolution"
const val LAST_CONFLICT_APPLY_TO_ALL = "last_conflict_apply_to_all"
// licenses
const val LICENSE_KOTLIN = 1