Skip to content

Commit 055007a

Browse files
committed
fix #164, show a conflict dialog when decompressing destination already exists
1 parent 803b30c commit 055007a

File tree

5 files changed

+97
-34
lines changed

5 files changed

+97
-34
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ ext {
4545
}
4646

4747
dependencies {
48-
implementation 'com.simplemobiletools:commons:3.12.3'
48+
implementation 'com.simplemobiletools:commons:3.12.5'
4949

5050
implementation files('../libs/RootTools.jar')
5151

app/src/main/kotlin/com/simplemobiletools/filemanager/adapters/ItemsAdapter.kt

Lines changed: 93 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import com.simplemobiletools.commons.dialogs.FilePickerDialog
1818
import com.simplemobiletools.commons.dialogs.PropertiesDialog
1919
import com.simplemobiletools.commons.dialogs.RenameItemDialog
2020
import com.simplemobiletools.commons.extensions.*
21+
import com.simplemobiletools.commons.helpers.CONFLICT_OVERWRITE
22+
import com.simplemobiletools.commons.helpers.CONFLICT_SKIP
2123
import com.simplemobiletools.commons.models.FileDirItem
2224
import com.simplemobiletools.commons.views.FastScroller
2325
import com.simplemobiletools.commons.views.MyRecyclerView
@@ -235,7 +237,7 @@ class ItemsAdapter(activity: SimpleActivity, var fileDirItems: MutableList<FileD
235237
activity.toast(R.string.compressing)
236238
val paths = selectedPositions.map { fileDirItems[it].path }
237239
Thread {
238-
if (zipPaths(paths, it)) {
240+
if (compressPaths(paths, it)) {
239241
activity.runOnUiThread {
240242
activity.toast(R.string.compression_successful)
241243
listener?.refreshItems()
@@ -257,10 +259,9 @@ class ItemsAdapter(activity: SimpleActivity, var fileDirItems: MutableList<FileD
257259
}
258260

259261
activity.handleSAFDialog(firstPath) {
260-
activity.toast(R.string.decompressing)
261262
val paths = selectedPositions.map { fileDirItems[it].path }.filter { it.isZipFile() }
262-
Thread {
263-
if (unzipPaths(paths)) {
263+
tryDecompressingPaths(paths) {
264+
if (it) {
264265
activity.toast(R.string.decompression_successful)
265266
activity.runOnUiThread {
266267
listener?.refreshItems()
@@ -269,43 +270,105 @@ class ItemsAdapter(activity: SimpleActivity, var fileDirItems: MutableList<FileD
269270
} else {
270271
activity.toast(R.string.decompressing_failed)
271272
}
272-
}.start()
273+
}
274+
}
275+
}
276+
277+
private fun tryDecompressingPaths(sourcePaths: List<String>, callback: (success: Boolean) -> Unit) {
278+
sourcePaths.forEach {
279+
try {
280+
val zipFile = ZipFile(it)
281+
val entries = zipFile.entries()
282+
val fileDirItems = ArrayList<FileDirItem>()
283+
while (entries.hasMoreElements()) {
284+
val entry = entries.nextElement()
285+
val currPath = if (entry.isDirectory) it else "${it.getParentPath()}${entry.name}"
286+
val fileDirItem = FileDirItem(currPath, entry.name, entry.isDirectory, 0, entry.size)
287+
fileDirItems.add(fileDirItem)
288+
}
289+
290+
val destinationFileDirItem = FileDirItem(fileDirItems.first().getParentPath().trimEnd('/'))
291+
activity.checkConflicts(fileDirItems, destinationFileDirItem, 0, LinkedHashMap()) {
292+
Thread {
293+
decompressPaths(sourcePaths, it, callback)
294+
}.start()
295+
}
296+
} catch (exception: Exception) {
297+
activity.showErrorToast(exception)
298+
}
273299
}
274300
}
275301

276-
private fun unzipPaths(sourcePaths: List<String>): Boolean {
277-
sourcePaths.map { File(it) }
278-
.forEach {
279-
try {
280-
val zipFile = ZipFile(it)
281-
val entries = zipFile.entries()
282-
while (entries.hasMoreElements()) {
283-
val entry = entries.nextElement()
284-
val file = File(it.parent, entry.name)
285-
if (entry.isDirectory) {
286-
if (!activity.createDirectorySync(file.absolutePath)) {
287-
val error = String.format(activity.getString(R.string.could_not_create_file), file.absolutePath)
288-
activity.showErrorToast(error)
289-
return false
302+
private fun decompressPaths(paths: List<String>, conflictResolutions: LinkedHashMap<String, Int>, callback: (success: Boolean) -> Unit) {
303+
paths.forEach {
304+
try {
305+
val zipFile = ZipFile(it)
306+
val entries = zipFile.entries()
307+
while (entries.hasMoreElements()) {
308+
val entry = entries.nextElement()
309+
val newPath = "${it.getParentPath()}${entry.name}"
310+
311+
val resolution = getConflictResolution(conflictResolutions, newPath)
312+
val doesPathExist = activity.getDoesFilePathExist(newPath)
313+
if (doesPathExist && resolution == CONFLICT_OVERWRITE) {
314+
val fileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), entry.isDirectory)
315+
if (activity.getIsPathDirectory(it)) {
316+
activity.deleteFolderBg(fileDirItem, false) {
317+
if (it) {
318+
extractEntry(newPath, entry, zipFile)
319+
} else {
320+
callback(false)
290321
}
291-
} else {
292-
val ins = zipFile.getInputStream(entry)
293-
ins.use {
294-
val fos = activity.getFileOutputStreamSync(file.absolutePath, file.getMimeType())
295-
if (fos != null)
296-
ins.copyTo(fos)
322+
}
323+
} else {
324+
activity.deleteFileBg(fileDirItem, false) {
325+
if (it) {
326+
extractEntry(newPath, entry, zipFile)
327+
} else {
328+
callback(false)
297329
}
298330
}
299331
}
300-
} catch (exception: Exception) {
301-
activity.showErrorToast(exception)
302-
return false
332+
} else if (!doesPathExist) {
333+
extractEntry(newPath, entry, zipFile)
303334
}
304335
}
305-
return true
336+
callback(true)
337+
} catch (e: Exception) {
338+
activity.showErrorToast(e)
339+
callback(false)
340+
}
341+
}
342+
}
343+
344+
private fun extractEntry(newPath: String, entry: ZipEntry, zipFile: ZipFile) {
345+
if (entry.isDirectory) {
346+
if (!activity.createDirectorySync(newPath)) {
347+
val error = String.format(activity.getString(R.string.could_not_create_file), newPath)
348+
activity.showErrorToast(error)
349+
}
350+
} else {
351+
val ins = zipFile.getInputStream(entry)
352+
ins.use {
353+
val fos = activity.getFileOutputStreamSync(newPath, newPath.getMimeType())
354+
if (fos != null) {
355+
ins.copyTo(fos)
356+
}
357+
}
358+
}
359+
}
360+
361+
private fun getConflictResolution(conflictResolutions: LinkedHashMap<String, Int>, path: String): Int {
362+
return if (conflictResolutions.size == 1 && conflictResolutions.containsKey("")) {
363+
conflictResolutions[""]!!
364+
} else if (conflictResolutions.containsKey(path)) {
365+
conflictResolutions[path]!!
366+
} else {
367+
CONFLICT_SKIP
368+
}
306369
}
307370

308-
private fun zipPaths(sourcePaths: List<String>, targetPath: String): Boolean {
371+
private fun compressPaths(sourcePaths: List<String>, targetPath: String): Boolean {
309372
val queue = LinkedList<File>()
310373
val fos = activity.getFileOutputStreamSync(targetPath, "application/zip") ?: return false
311374

app/src/main/kotlin/com/simplemobiletools/filemanager/dialogs/CompressAsDialog.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class CompressAsDialog(val activity: BaseSimpleActivity, val path: String, val c
4343
name.isEmpty() -> activity.toast(R.string.empty_name)
4444
name.isAValidFilename() -> {
4545
val newPath = "$realPath/$name.zip"
46-
if (activity.doesFilePathExist(newPath)) {
46+
if (activity.getDoesFilePathExist(newPath)) {
4747
activity.toast(R.string.name_taken)
4848
return@OnClickListener
4949
}

app/src/main/kotlin/com/simplemobiletools/filemanager/dialogs/CreateNewItemDialog.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class CreateNewItemDialog(val activity: BaseSimpleActivity, val path: String, va
2626
activity.toast(R.string.empty_name)
2727
} else if (name.isAValidFilename()) {
2828
val newPath = "$path/$name"
29-
if (activity.doesFilePathExist(newPath)) {
29+
if (activity.getDoesFilePathExist(newPath)) {
3030
activity.toast(R.string.name_taken)
3131
return@OnClickListener
3232
}

app/src/main/kotlin/com/simplemobiletools/filemanager/dialogs/SaveAsDialog.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ class SaveAsDialog(val activity: BaseSimpleActivity, var path: String, val callb
6666
return@setOnClickListener
6767
}
6868

69-
if (activity.doesFilePathExist(newPath)) {
69+
if (activity.getDoesFilePathExist(newPath)) {
7070
val title = String.format(activity.getString(R.string.file_already_exists_overwrite), newFilename)
7171
ConfirmationDialog(activity, title) {
7272
callback(newPath)

0 commit comments

Comments
 (0)