mirror of
https://github.com/SimpleMobileTools/Simple-File-Manager.git
synced 2025-06-05 22:09:15 +02:00
handle compress/decompress
This commit is contained in:
@ -41,6 +41,7 @@ import com.simplemobiletools.filemanager.pro.helpers.*
|
|||||||
import com.simplemobiletools.filemanager.pro.interfaces.ItemOperationsListener
|
import com.simplemobiletools.filemanager.pro.interfaces.ItemOperationsListener
|
||||||
import com.simplemobiletools.filemanager.pro.models.ListItem
|
import com.simplemobiletools.filemanager.pro.models.ListItem
|
||||||
import com.stericson.RootTools.RootTools
|
import com.stericson.RootTools.RootTools
|
||||||
|
import java.io.BufferedInputStream
|
||||||
import kotlinx.android.synthetic.main.item_file_dir_grid.view.*
|
import kotlinx.android.synthetic.main.item_file_dir_grid.view.*
|
||||||
import kotlinx.android.synthetic.main.item_file_dir_list.view.*
|
import kotlinx.android.synthetic.main.item_file_dir_list.view.*
|
||||||
import kotlinx.android.synthetic.main.item_file_dir_list.view.item_frame
|
import kotlinx.android.synthetic.main.item_file_dir_list.view.item_frame
|
||||||
@ -50,13 +51,18 @@ import kotlinx.android.synthetic.main.item_section.view.*
|
|||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URLEncoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipFile
|
import java.util.zip.ZipFile
|
||||||
|
import java.util.zip.ZipInputStream
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem>, val listener: ItemOperationsListener?, recyclerView: MyRecyclerView,
|
class ItemsAdapter(
|
||||||
val isPickMultipleIntent: Boolean, fastScroller: FastScroller?, val swipeRefreshLayout: SwipeRefreshLayout, itemClick: (Any) -> Unit) :
|
activity: SimpleActivity, var listItems: MutableList<ListItem>, val listener: ItemOperationsListener?, recyclerView: MyRecyclerView,
|
||||||
|
val isPickMultipleIntent: Boolean, fastScroller: FastScroller?, val swipeRefreshLayout: SwipeRefreshLayout, itemClick: (Any) -> Unit
|
||||||
|
) :
|
||||||
MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
MyRecyclerViewAdapter(activity, recyclerView, fastScroller, itemClick) {
|
||||||
|
|
||||||
private val TYPE_FILE_DIR = 1
|
private val TYPE_FILE_DIR = 1
|
||||||
@ -329,7 +335,7 @@ class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem
|
|||||||
val shouldShowHidden = activity.config.shouldShowHidden
|
val shouldShowHidden = activity.config.shouldShowHidden
|
||||||
when {
|
when {
|
||||||
activity.isRestrictedAndroidDir(path) -> {
|
activity.isRestrictedAndroidDir(path) -> {
|
||||||
activity.getStorageItemsWithTreeUri(path, shouldShowHidden, false){ files->
|
activity.getStorageItemsWithTreeUri(path, shouldShowHidden, false) { files ->
|
||||||
files.forEach {
|
files.forEach {
|
||||||
addFileUris(activity.getPrimaryAndroidSAFUri(it.path).toString(), paths)
|
addFileUris(activity.getPrimaryAndroidSAFUri(it.path).toString(), paths)
|
||||||
}
|
}
|
||||||
@ -463,22 +469,27 @@ class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem
|
|||||||
|
|
||||||
CompressAsDialog(activity, firstPath) {
|
CompressAsDialog(activity, firstPath) {
|
||||||
val destination = it
|
val destination = it
|
||||||
activity.handleSAFDialog(firstPath) {
|
activity.handlePrimarySAFDialog(firstPath) { granted ->
|
||||||
if (!it) {
|
if (!granted) {
|
||||||
return@handleSAFDialog
|
return@handlePrimarySAFDialog
|
||||||
}
|
}
|
||||||
|
activity.handleSAFDialog(firstPath) {
|
||||||
|
if (!it) {
|
||||||
|
return@handleSAFDialog
|
||||||
|
}
|
||||||
|
|
||||||
activity.toast(R.string.compressing)
|
activity.toast(R.string.compressing)
|
||||||
val paths = getSelectedFileDirItems().map { it.path }
|
val paths = getSelectedFileDirItems().map { it.path }
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
if (compressPaths(paths, destination)) {
|
if (compressPaths(paths, destination)) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
activity.toast(R.string.compression_successful)
|
activity.toast(R.string.compression_successful)
|
||||||
listener?.refreshItems()
|
listener?.refreshItems()
|
||||||
finishActMode()
|
finishActMode()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
activity.toast(R.string.compressing_failed)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
activity.toast(R.string.compressing_failed)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,88 +524,94 @@ class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun tryDecompressingPaths(sourcePaths: List<String>, callback: (success: Boolean) -> Unit) {
|
private fun tryDecompressingPaths(sourcePaths: List<String>, callback: (success: Boolean) -> Unit) {
|
||||||
sourcePaths.forEach {
|
sourcePaths.forEach { path ->
|
||||||
try {
|
val zipInputStream = ZipInputStream(BufferedInputStream(activity.getFileInputStreamSync(path)))
|
||||||
val zipFile = ZipFile(it)
|
zipInputStream.use {
|
||||||
val entries = zipFile.entries()
|
try {
|
||||||
val fileDirItems = ArrayList<FileDirItem>()
|
val fileDirItems = ArrayList<FileDirItem>()
|
||||||
while (entries.hasMoreElements()) {
|
var entry = zipInputStream.nextEntry
|
||||||
val entry = entries.nextElement()
|
while (entry != null) {
|
||||||
val currPath = if (entry.isDirectory) it else "${it.getParentPath().trimEnd('/')}/${entry.name}"
|
val currPath = if (entry.isDirectory) path else "${path.getParentPath().trimEnd('/')}/${entry.name}"
|
||||||
val fileDirItem = FileDirItem(currPath, entry.name, entry.isDirectory, 0, entry.size)
|
val fileDirItem = FileDirItem(currPath, entry.name, entry.isDirectory, 0, entry.size)
|
||||||
fileDirItems.add(fileDirItem)
|
fileDirItems.add(fileDirItem)
|
||||||
}
|
zipInputStream.closeEntry()
|
||||||
|
entry = zipInputStream.nextEntry
|
||||||
val destinationPath = fileDirItems.first().getParentPath().trimEnd('/')
|
|
||||||
activity.checkConflicts(fileDirItems, destinationPath, 0, LinkedHashMap()) {
|
|
||||||
ensureBackgroundThread {
|
|
||||||
decompressPaths(sourcePaths, it, callback)
|
|
||||||
}
|
}
|
||||||
|
zipInputStream.closeEntry()
|
||||||
|
val destinationPath = fileDirItems.first().getParentPath().trimEnd('/')
|
||||||
|
activity.checkConflicts(fileDirItems, destinationPath, 0, LinkedHashMap()) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
decompressPaths(sourcePaths, it, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
exception.printStackTrace()
|
||||||
|
activity.showErrorToast(exception)
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
|
||||||
activity.showErrorToast(exception)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun decompressPaths(paths: List<String>, conflictResolutions: LinkedHashMap<String, Int>, callback: (success: Boolean) -> Unit) {
|
private fun decompressPaths(paths: List<String>, conflictResolutions: LinkedHashMap<String, Int>, callback: (success: Boolean) -> Unit) {
|
||||||
paths.forEach {
|
paths.forEach { path ->
|
||||||
try {
|
val zipInputStream = ZipInputStream(BufferedInputStream(activity.getFileInputStreamSync(path)))
|
||||||
val zipFile = ZipFile(it)
|
zipInputStream.use {
|
||||||
val entries = zipFile.entries()
|
try {
|
||||||
val zipFileName = it.getFilenameFromPath()
|
var entry = zipInputStream.nextEntry
|
||||||
val newFolderName = zipFileName.subSequence(0, zipFileName.length - 4)
|
val zipFileName = path.getFilenameFromPath()
|
||||||
while (entries.hasMoreElements()) {
|
val newFolderName = zipFileName.subSequence(0, zipFileName.length - 4)
|
||||||
val entry = entries.nextElement()
|
while (entry != null) {
|
||||||
val parentPath = it.getParentPath()
|
val parentPath = path.getParentPath()
|
||||||
val newPath = "$parentPath/$newFolderName/${entry.name.trimEnd('/')}"
|
val newPath = "$parentPath/$newFolderName/${entry.name.trimEnd('/')}"
|
||||||
|
|
||||||
val resolution = getConflictResolution(conflictResolutions, newPath)
|
val resolution = getConflictResolution(conflictResolutions, newPath)
|
||||||
val doesPathExist = activity.getDoesFilePathExist(newPath)
|
val doesPathExist = activity.getDoesFilePathExist(newPath)
|
||||||
if (doesPathExist && resolution == CONFLICT_OVERWRITE) {
|
if (doesPathExist && resolution == CONFLICT_OVERWRITE) {
|
||||||
val fileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), entry.isDirectory)
|
val fileDirItem = FileDirItem(newPath, newPath.getFilenameFromPath(), entry.isDirectory)
|
||||||
if (activity.getIsPathDirectory(it)) {
|
if (activity.getIsPathDirectory(path)) {
|
||||||
activity.deleteFolderBg(fileDirItem, false) {
|
activity.deleteFolderBg(fileDirItem, false) {
|
||||||
if (it) {
|
if (it) {
|
||||||
extractEntry(newPath, entry, zipFile)
|
extractEntry(newPath, entry, zipInputStream)
|
||||||
} else {
|
} else {
|
||||||
callback(false)
|
callback(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activity.deleteFileBg(fileDirItem, false) {
|
activity.deleteFileBg(fileDirItem, false) {
|
||||||
if (it) {
|
if (it) {
|
||||||
extractEntry(newPath, entry, zipFile)
|
extractEntry(newPath, entry, zipInputStream)
|
||||||
} else {
|
} else {
|
||||||
callback(false)
|
callback(false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (!doesPathExist) {
|
||||||
|
extractEntry(newPath, entry, zipInputStream)
|
||||||
}
|
}
|
||||||
} else if (!doesPathExist) {
|
|
||||||
extractEntry(newPath, entry, zipFile)
|
zipInputStream.closeEntry()
|
||||||
|
entry = zipInputStream.nextEntry
|
||||||
}
|
}
|
||||||
|
callback(true)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
activity.showErrorToast(e)
|
||||||
|
callback(false)
|
||||||
}
|
}
|
||||||
callback(true)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
activity.showErrorToast(e)
|
|
||||||
callback(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractEntry(newPath: String, entry: ZipEntry, zipFile: ZipFile) {
|
private fun extractEntry(newPath: String, entry: ZipEntry, zipInputStream: ZipInputStream) {
|
||||||
if (entry.isDirectory) {
|
if (entry.isDirectory) {
|
||||||
if (!activity.createDirectorySync(newPath) && !activity.getDoesFilePathExist(newPath)) {
|
if (!activity.createDirectorySync(newPath) && !activity.getDoesFilePathExist(newPath)) {
|
||||||
val error = String.format(activity.getString(R.string.could_not_create_file), newPath)
|
val error = String.format(activity.getString(R.string.could_not_create_file), newPath)
|
||||||
activity.showErrorToast(error)
|
activity.showErrorToast(error)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val ins = zipFile.getInputStream(entry)
|
val fos = activity.getFileOutputStreamSync(newPath, newPath.getMimeType())
|
||||||
ins.use {
|
if (fos != null) {
|
||||||
val fos = activity.getFileOutputStreamSync(newPath, newPath.getMimeType())
|
zipInputStream.copyTo(fos)
|
||||||
if (fos != null) {
|
|
||||||
ins.copyTo(fos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -610,48 +627,68 @@ class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun compressPaths(sourcePaths: List<String>, targetPath: String): Boolean {
|
private fun compressPaths(sourcePaths: List<String>, targetPath: String): Boolean {
|
||||||
val queue = LinkedList<File>()
|
val queue = LinkedList<String>()
|
||||||
val fos = activity.getFileOutputStreamSync(targetPath, "application/zip") ?: return false
|
val fos = activity.getFileOutputStreamSync(targetPath, "application/zip") ?: return false
|
||||||
|
|
||||||
val zout = ZipOutputStream(fos)
|
val zout = ZipOutputStream(fos)
|
||||||
var res: Closeable = fos
|
var res: Closeable = fos
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sourcePaths.forEach {
|
sourcePaths.forEach { currentPath ->
|
||||||
var name: String
|
var name: String
|
||||||
var mainFile = File(it)
|
var mainFilePath = currentPath
|
||||||
val base = mainFile.parentFile.toURI()
|
val base = "${mainFilePath.getParentPath()}/"
|
||||||
res = zout
|
res = zout
|
||||||
queue.push(mainFile)
|
queue.push(mainFilePath)
|
||||||
if (activity.getIsPathDirectory(mainFile.absolutePath)) {
|
if (activity.getIsPathDirectory(mainFilePath)) {
|
||||||
name = "${mainFile.name.trimEnd('/')}/"
|
name = "${mainFilePath.getFilenameFromPath()}/"
|
||||||
zout.putNextEntry(ZipEntry(name))
|
zout.putNextEntry(ZipEntry(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!queue.isEmpty()) {
|
while (!queue.isEmpty()) {
|
||||||
mainFile = queue.pop()
|
mainFilePath = queue.pop()
|
||||||
if (activity.getIsPathDirectory(mainFile.absolutePath)) {
|
if (activity.getIsPathDirectory(mainFilePath)) {
|
||||||
for (file in mainFile.listFiles()) {
|
if (activity.isRestrictedAndroidDir(mainFilePath)) {
|
||||||
name = base.relativize(file.toURI()).path
|
activity.getStorageItemsWithTreeUri(mainFilePath, true) { files ->
|
||||||
if (activity.getIsPathDirectory(file.absolutePath)) {
|
for (file in files) {
|
||||||
queue.push(file)
|
name = file.path.relativizeWith(base)
|
||||||
name = "${name.trimEnd('/')}/"
|
if (activity.getIsPathDirectory(file.path)) {
|
||||||
zout.putNextEntry(ZipEntry(name))
|
queue.push(file.path)
|
||||||
} else {
|
name = "${name.trimEnd('/')}/"
|
||||||
zout.putNextEntry(ZipEntry(name))
|
zout.putNextEntry(ZipEntry(name))
|
||||||
FileInputStream(file).copyTo(zout)
|
} else {
|
||||||
zout.closeEntry()
|
zout.putNextEntry(ZipEntry(name))
|
||||||
|
activity.getFileInputStreamSync(file.path)!!.copyTo(zout)
|
||||||
|
zout.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val mainFile = File(mainFilePath)
|
||||||
|
for (file in mainFile.listFiles()) {
|
||||||
|
name = file.path.relativizeWith(base)
|
||||||
|
if (activity.getIsPathDirectory(file.absolutePath)) {
|
||||||
|
queue.push(file.absolutePath)
|
||||||
|
name = "${name.trimEnd('/')}/"
|
||||||
|
zout.putNextEntry(ZipEntry(name))
|
||||||
|
} else {
|
||||||
|
zout.putNextEntry(ZipEntry(name))
|
||||||
|
activity.getFileInputStreamSync(file.path)!!.copyTo(zout)
|
||||||
|
zout.closeEntry()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
name = if (base.path == it) it.getFilenameFromPath() else base.relativize(mainFile.toURI()).path
|
name = if (base == currentPath) currentPath.getFilenameFromPath() else mainFilePath.relativizeWith(base)
|
||||||
zout.putNextEntry(ZipEntry(name))
|
zout.putNextEntry(ZipEntry(name))
|
||||||
FileInputStream(mainFile).copyTo(zout)
|
activity.getFileInputStreamSync(mainFilePath)!!.copyTo(zout)
|
||||||
zout.closeEntry()
|
zout.closeEntry()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
|
exception.printStackTrace()
|
||||||
activity.showErrorToast(exception)
|
activity.showErrorToast(exception)
|
||||||
return false
|
return false
|
||||||
} finally {
|
} finally {
|
||||||
@ -835,7 +872,8 @@ class ItemsAdapter(activity: SimpleActivity, var listItems: MutableList<ListItem
|
|||||||
return activity.resources.getQuantityString(R.plurals.items, children, children)
|
return activity.resources.getQuantityString(R.plurals.items, children, children)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOTGPublicPath(itemToLoad: String) = "${baseConfig.OTGTreeUri}/document/${baseConfig.OTGPartition}%3A${itemToLoad.substring(baseConfig.OTGPath.length).replace("/", "%2F")}"
|
private fun getOTGPublicPath(itemToLoad: String) =
|
||||||
|
"${baseConfig.OTGTreeUri}/document/${baseConfig.OTGPartition}%3A${itemToLoad.substring(baseConfig.OTGPath.length).replace("/", "%2F")}"
|
||||||
|
|
||||||
private fun getImagePathToLoad(path: String): Any {
|
private fun getImagePathToLoad(path: String): Any {
|
||||||
var itemToLoad = if (path.endsWith(".apk", true)) {
|
var itemToLoad = if (path.endsWith(".apk", true)) {
|
||||||
|
Reference in New Issue
Block a user