From cb3e393eb8fc90e43a6905acf3d5f00239e2f089 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 13 Mar 2024 19:19:51 +0530 Subject: [PATCH 1/4] Use primary color for folders --- .../org/fossify/filemanager/adapters/DecompressItemsAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/adapters/DecompressItemsAdapter.kt b/app/src/main/kotlin/org/fossify/filemanager/adapters/DecompressItemsAdapter.kt index df674163..b604a693 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/adapters/DecompressItemsAdapter.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/adapters/DecompressItemsAdapter.kt @@ -131,7 +131,7 @@ class DecompressItemsAdapter(activity: SimpleActivity, var listItems: MutableLis } private fun initDrawables() { - folderDrawable = resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, textColor) + folderDrawable = resources.getColoredDrawableWithColor(R.drawable.ic_folder_vector, properPrimaryColor) folderDrawable.alpha = 180 fileDrawable = resources.getDrawable(R.drawable.ic_file_generic) fileDrawables = getFilePlaceholderDrawables(activity) From 3712f9fb262d79b7dd0e4698234a02cb10e0b302 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 13 Mar 2024 19:40:50 +0530 Subject: [PATCH 2/4] Move IO operation to background thread This was causing ANRs when zip files contained more than a few entries. --- .../activities/DecompressActivity.kt | 66 ++++++++++++++----- .../main/res/layout/activity_decompress.xml | 8 +++ 2 files changed, 58 insertions(+), 16 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt index 3c2d67e3..0c1c6ef4 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt @@ -1,6 +1,5 @@ package org.fossify.filemanager.activities -import android.annotation.SuppressLint import android.net.Uri import android.os.Bundle import net.lingala.zip4j.exception.ZipException @@ -76,11 +75,6 @@ class DecompressActivity : SimpleActivity() { } } - private fun setupFilesList() { - fillAllListItems(uri!!) - updateCurrentPath("") - } - override fun onBackPressed() { if (currentPath.isEmpty()) { super.onBackPressed() @@ -90,10 +84,24 @@ class DecompressActivity : SimpleActivity() { } } + private fun setupFilesList() { + fillAllListItems(uri!!) { + updateCurrentPath("") + } + } + private fun updateCurrentPath(path: String) { currentPath = path try { val listItems = getFolderItems(currentPath) + updateAdapter(listItems = listItems) + } catch (e: Exception) { + showErrorToast(e) + } + } + + private fun updateAdapter(listItems: MutableList) { + runOnUiThread { DecompressItemsAdapter(this, listItems, binding.decompressList) { if ((it as ListItem).isDirectory) { updateCurrentPath(it.path) @@ -101,8 +109,6 @@ class DecompressActivity : SimpleActivity() { }.apply { binding.decompressList.adapter = this } - } catch (e: Exception) { - showErrorToast(e) } } @@ -183,13 +189,12 @@ class DecompressActivity : SimpleActivity() { }.sortedWith(compareBy({ !it.isDirectory }, { it.mName })).toMutableList() as ArrayList } - @SuppressLint("NewApi") - private fun fillAllListItems(uri: Uri) { + private fun fillAllListItems(uri: Uri, callback: () -> Unit) = ensureBackgroundThread { val inputStream = try { contentResolver.openInputStream(uri) } catch (e: Exception) { showErrorToast(e) - return + return@ensureBackgroundThread } val zipInputStream = ZipInputStream(BufferedInputStream(inputStream)) @@ -206,9 +211,11 @@ class DecompressActivity : SimpleActivity() { toast(getString(R.string.invalid_password)) passwordDialog?.clearPassword() } else { - askForPassword() + runOnUiThread { + askForPassword() + } } - return + return@ensureBackgroundThread } else { break } @@ -220,12 +227,39 @@ class DecompressActivity : SimpleActivity() { break } + // Show progress bar only after password dialog is dismissed. + runOnUiThread { + if (binding.progressIndicator.isGone()) { + binding.progressIndicator.show() + } + } + + if (passwordDialog != null) { + passwordDialog?.dismiss(notify = false) + passwordDialog = null + } + val lastModified = if (isOreoPlus()) zipEntry.lastModifiedTime else 0 val filename = zipEntry.fileName.removeSuffix("/") - val listItem = ListItem(filename, filename.getFilenameFromPath(), zipEntry.isDirectory, 0, 0L, lastModified, false, false) - allFiles.add(listItem) + allFiles.add( + ListItem( + mPath = filename, + mName = filename.getFilenameFromPath(), + mIsDirectory = zipEntry.isDirectory, + mChildren = 0, + mSize = 0L, + mModified = lastModified, + isSectionTitle = false, + isGridTypeDivider = false + ) + ) } - passwordDialog?.dismiss(notify = false) + + runOnUiThread { + binding.progressIndicator.hide() + } + + callback() } private fun askForPassword() { diff --git a/app/src/main/res/layout/activity_decompress.xml b/app/src/main/res/layout/activity_decompress.xml index 8a4fa560..d2ee6c96 100644 --- a/app/src/main/res/layout/activity_decompress.xml +++ b/app/src/main/res/layout/activity_decompress.xml @@ -32,4 +32,12 @@ app:layoutManager="org.fossify.commons.views.MyLinearLayoutManager" /> + + From aea5b034c38c2fcd5be13894e2346c568baf8870 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 13 Mar 2024 19:51:00 +0530 Subject: [PATCH 3/4] Minor code improvement --- .../filemanager/activities/DecompressActivity.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt index 0c1c6ef4..d0a1c7c0 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/activities/DecompressActivity.kt @@ -114,7 +114,15 @@ class DecompressActivity : SimpleActivity() { private fun decompressFiles() { val defaultFolder = getRealPathFromURI(uri!!) ?: internalStoragePath - FilePickerDialog(this, defaultFolder, false, config.showHidden, true, true, showFavoritesButton = true) { destination -> + FilePickerDialog( + activity = this, + currPath = defaultFolder, + pickFile = false, + showHidden = config.showHidden, + showFAB = true, + canAddShowHiddenButton = true, + showFavoritesButton = true + ) { destination -> handleSAFDialog(destination) { if (it) { ensureBackgroundThread { From 3c93a2d2dab5f15d85e79e1be282ca641b4cd0ed Mon Sep 17 00:00:00 2001 From: Naveen Date: Fri, 15 Mar 2024 05:16:50 +0530 Subject: [PATCH 4/4] Avoid blocking the main thread for too long It can happen when there are a lot of selected items. --- .../filemanager/adapters/ItemsAdapter.kt | 58 +++++++++++-------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt b/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt index d7816784..82f6a33f 100644 --- a/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt +++ b/app/src/main/kotlin/org/fossify/filemanager/adapters/ItemsAdapter.kt @@ -57,8 +57,14 @@ import java.util.LinkedList import java.util.Locale class ItemsAdapter( - activity: SimpleActivity, var listItems: MutableList, val listener: ItemOperationsListener?, recyclerView: MyRecyclerView, - val isPickMultipleIntent: Boolean, val swipeRefreshLayout: SwipeRefreshLayout?, canHaveIndividualViewType: Boolean = true, itemClick: (Any) -> Unit + activity: SimpleActivity, + var listItems: MutableList, + private val listener: ItemOperationsListener?, + recyclerView: MyRecyclerView, + private val isPickMultipleIntent: Boolean, + private val swipeRefreshLayout: SwipeRefreshLayout?, + canHaveIndividualViewType: Boolean = true, + itemClick: (Any) -> Unit, ) : MyRecyclerViewAdapter(activity, recyclerView, itemClick), RecyclerViewFastScroller.OnPopupTextUpdate { private lateinit var fileDrawable: Drawable @@ -401,12 +407,12 @@ class ItemsAdapter( val firstFile = files[0] val source = firstFile.getParentPath() FilePickerDialog( - activity, - activity.getDefaultCopyDestinationPath(config.shouldShowHidden(), source), - false, - config.shouldShowHidden(), - true, - true, + activity = activity, + currPath = activity.getDefaultCopyDestinationPath(config.shouldShowHidden(), source), + pickFile = false, + showHidden = config.shouldShowHidden(), + showFAB = true, + canAddShowHiddenButton = true, showFavoritesButton = true ) { config.lastCopyPath = it @@ -749,28 +755,32 @@ class ItemsAdapter( return } - activity.handleSAFDialog(SAFPath) { - if (!it) { + activity.handleSAFDialog(SAFPath) { granted -> + if (!granted) { return@handleSAFDialog } val files = ArrayList(selectedKeys.size) val positions = ArrayList() - selectedKeys.forEach { - config.removeFavorite(getItemWithKey(it)?.path ?: "") - val key = it - val position = listItems.indexOfFirst { it.path.hashCode() == key } - if (position != -1) { - positions.add(position) - files.add(listItems[position]) - } - } - positions.sortDescending() - removeSelectedItems(positions) - listener?.deleteFiles(files) - positions.forEach { - listItems.removeAt(it) + ensureBackgroundThread { + selectedKeys.forEach { key -> + config.removeFavorite(getItemWithKey(key)?.path ?: "") + val position = listItems.indexOfFirst { it.path.hashCode() == key } + if (position != -1) { + positions.add(position) + files.add(listItems[position]) + } + } + + positions.sortDescending() + activity.runOnUiThread { + removeSelectedItems(positions) + listener?.deleteFiles(files) + positions.forEach { + listItems.removeAt(it) + } + } } } }