show a conflict resolution dialog if the destination file exists
This commit is contained in:
parent
8d61261060
commit
52ea376602
5 changed files with 71 additions and 8 deletions
|
@ -19,6 +19,7 @@ import android.view.WindowManager
|
||||||
import com.simplemobiletools.commons.R
|
import com.simplemobiletools.commons.R
|
||||||
import com.simplemobiletools.commons.asynctasks.CopyMoveTask
|
import com.simplemobiletools.commons.asynctasks.CopyMoveTask
|
||||||
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
|
import com.simplemobiletools.commons.dialogs.FileConflictDialog
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.APP_LICENSES
|
import com.simplemobiletools.commons.helpers.APP_LICENSES
|
||||||
import com.simplemobiletools.commons.helpers.APP_NAME
|
import com.simplemobiletools.commons.helpers.APP_NAME
|
||||||
|
@ -184,12 +185,10 @@ open class BaseSimpleActivity : AppCompatActivity() {
|
||||||
handleSAFDialog(destinationFolder) {
|
handleSAFDialog(destinationFolder) {
|
||||||
copyMoveCallback = callback
|
copyMoveCallback = callback
|
||||||
if (isCopyOperation) {
|
if (isCopyOperation) {
|
||||||
toast(R.string.copying)
|
|
||||||
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
|
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
|
||||||
} else {
|
} else {
|
||||||
if (isPathOnSD(source) || isPathOnSD(destination) || files.first().isDirectory || isNougatPlus()) {
|
if (isPathOnSD(source) || isPathOnSD(destination) || files.first().isDirectory || isNougatPlus()) {
|
||||||
handleSAFDialog(File(source)) {
|
handleSAFDialog(File(source)) {
|
||||||
toast(R.string.moving)
|
|
||||||
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
|
startCopyMove(files, destinationFolder, isCopyOperation, copyPhotoVideoOnly)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,8 +221,35 @@ open class BaseSimpleActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startCopyMove(files: ArrayList<File>, destinationFolder: File, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean) {
|
private fun startCopyMove(files: ArrayList<File>, destinationFolder: File, isCopyOperation: Boolean, copyPhotoVideoOnly: Boolean) {
|
||||||
val pair = Pair(files, destinationFolder)
|
checkConflict(files, destinationFolder, 0, LinkedHashMap()) {
|
||||||
CopyMoveTask(this, isCopyOperation, copyPhotoVideoOnly, copyMoveListener).execute(pair)
|
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) {
|
fun handlePermission(permissionId: Int, callback: (granted: Boolean) -> Unit) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.io.OutputStream
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.*
|
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>() {
|
listener: CopyMoveListener) : AsyncTask<Pair<ArrayList<File>, File>, Void, Boolean>() {
|
||||||
private var mListener: WeakReference<CopyMoveListener>? = null
|
private var mListener: WeakReference<CopyMoveListener>? = null
|
||||||
private var mMovedFiles: ArrayList<File> = ArrayList()
|
private var mMovedFiles: ArrayList<File> = ArrayList()
|
||||||
|
|
|
@ -3,20 +3,47 @@ package com.simplemobiletools.commons.dialogs
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.support.v7.app.AlertDialog
|
import android.support.v7.app.AlertDialog
|
||||||
import com.simplemobiletools.commons.R
|
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.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.*
|
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 {
|
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_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)
|
AlertDialog.Builder(activity)
|
||||||
.setPositiveButton(R.string.ok, { dialog, which -> })
|
.setPositiveButton(R.string.ok, { dialog, which -> dialogConfirmed() })
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.create().apply {
|
.create().apply {
|
||||||
activity.setupDialogStuff(view, this)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,4 +131,12 @@ open class BaseConfig(val context: Context) {
|
||||||
var showInfoBubble: Boolean
|
var showInfoBubble: Boolean
|
||||||
get() = prefs.getBoolean(SHOW_INFO_BUBBLE, true)
|
get() = prefs.getBoolean(SHOW_INFO_BUBBLE, true)
|
||||||
set(showInfoBubble) = prefs.edit().putBoolean(SHOW_INFO_BUBBLE, showInfoBubble).apply()
|
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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 WAS_SHARED_THEME_AFTER_UPDATE_CHECKED = "was_shared_theme_after_update_checked"
|
||||||
const val SHOW_INFO_BUBBLE = "show_info_bubble"
|
const val SHOW_INFO_BUBBLE = "show_info_bubble"
|
||||||
const val SORTING = "sorting"
|
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
|
// licenses
|
||||||
const val LICENSE_KOTLIN = 1
|
const val LICENSE_KOTLIN = 1
|
||||||
|
|
Loading…
Reference in a new issue