forked from hardcoresushi/DroidFS
Directory loading indicator
This commit is contained in:
parent
f4e47c1827
commit
b4635dc2e0
@ -11,10 +11,12 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -23,10 +25,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.yield
|
||||||
import sushi.hardcore.droidfs.BaseActivity
|
import sushi.hardcore.droidfs.BaseActivity
|
||||||
import sushi.hardcore.droidfs.Constants
|
import sushi.hardcore.droidfs.Constants
|
||||||
import sushi.hardcore.droidfs.EncryptedFileProvider
|
import sushi.hardcore.droidfs.EncryptedFileProvider
|
||||||
@ -69,6 +74,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
}
|
}
|
||||||
protected lateinit var fileOperationService: FileOperationService
|
protected lateinit var fileOperationService: FileOperationService
|
||||||
protected val activityScope = MainScope()
|
protected val activityScope = MainScope()
|
||||||
|
private var directoryLoadingTask: Job? = null
|
||||||
protected lateinit var explorerElements: MutableList<ExplorerElement>
|
protected lateinit var explorerElements: MutableList<ExplorerElement>
|
||||||
protected lateinit var explorerAdapter: ExplorerElementAdapter
|
protected lateinit var explorerAdapter: ExplorerElementAdapter
|
||||||
protected lateinit var app: VolumeManagerApp
|
protected lateinit var app: VolumeManagerApp
|
||||||
@ -79,6 +85,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
private lateinit var titleText: TextView
|
private lateinit var titleText: TextView
|
||||||
private lateinit var recycler_view_explorer: RecyclerView
|
private lateinit var recycler_view_explorer: RecyclerView
|
||||||
private lateinit var refresher: SwipeRefreshLayout
|
private lateinit var refresher: SwipeRefreshLayout
|
||||||
|
private lateinit var loader: ProgressBar
|
||||||
private lateinit var textDirEmpty: TextView
|
private lateinit var textDirEmpty: TextView
|
||||||
private lateinit var currentPathText: TextView
|
private lateinit var currentPathText: TextView
|
||||||
private lateinit var numberOfFilesText: TextView
|
private lateinit var numberOfFilesText: TextView
|
||||||
@ -101,6 +108,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
init()
|
init()
|
||||||
recycler_view_explorer = findViewById(R.id.recycler_view_explorer)
|
recycler_view_explorer = findViewById(R.id.recycler_view_explorer)
|
||||||
refresher = findViewById(R.id.refresher)
|
refresher = findViewById(R.id.refresher)
|
||||||
|
loader = findViewById(R.id.loader)
|
||||||
textDirEmpty = findViewById(R.id.text_dir_empty)
|
textDirEmpty = findViewById(R.id.text_dir_empty)
|
||||||
currentPathText = findViewById(R.id.current_path_text)
|
currentPathText = findViewById(R.id.current_path_text)
|
||||||
numberOfFilesText = findViewById(R.id.number_of_files_text)
|
numberOfFilesText = findViewById(R.id.number_of_files_text)
|
||||||
@ -312,17 +320,15 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun displayExplorerElements() {
|
private fun displayExplorerElements() {
|
||||||
synchronized(this) {
|
|
||||||
ExplorerElement.sortBy(sortOrderValues[currentSortOrderIndex], foldersFirst, explorerElements)
|
ExplorerElement.sortBy(sortOrderValues[currentSortOrderIndex], foldersFirst, explorerElements)
|
||||||
}
|
|
||||||
unselectAll(false)
|
unselectAll(false)
|
||||||
|
loader.isVisible = false
|
||||||
|
recycler_view_explorer.isVisible = true
|
||||||
explorerAdapter.explorerElements = explorerElements
|
explorerAdapter.explorerElements = explorerElements
|
||||||
val sharedPrefsEditor = sharedPrefs.edit()
|
|
||||||
sharedPrefsEditor.putString(Constants.SORT_ORDER_KEY, sortOrderValues[currentSortOrderIndex])
|
|
||||||
sharedPrefsEditor.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recursiveSetSize(directory: ExplorerElement) {
|
private suspend fun recursiveSetSize(directory: ExplorerElement) {
|
||||||
|
yield()
|
||||||
for (child in encryptedVolume.readDir(directory.fullPath) ?: return) {
|
for (child in encryptedVolume.readDir(directory.fullPath) ?: return) {
|
||||||
if (child.isDirectory) {
|
if (child.isDirectory) {
|
||||||
recursiveSetSize(child)
|
recursiveSetSize(child)
|
||||||
@ -346,26 +352,25 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setCurrentPath(path: String, onDisplayed: (() -> Unit)? = null) {
|
protected fun setCurrentPath(path: String, onDisplayed: (() -> Unit)? = null) = lifecycleScope.launch {
|
||||||
synchronized(this) {
|
directoryLoadingTask?.cancelAndJoin()
|
||||||
explorerElements = encryptedVolume.readDir(path) ?: return
|
recycler_view_explorer.isVisible = false
|
||||||
|
loader.isVisible = true
|
||||||
|
explorerElements = encryptedVolume.readDir(path) ?: return@launch
|
||||||
if (path != "/") {
|
if (path != "/") {
|
||||||
explorerElements.add(
|
explorerElements.add(
|
||||||
0,
|
0,
|
||||||
ExplorerElement("..", Stat.parentFolderStat(), parentPath = currentDirectoryPath)
|
ExplorerElement("..", Stat.parentFolderStat(), parentPath = currentDirectoryPath)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
textDirEmpty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.GONE
|
textDirEmpty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.GONE
|
||||||
currentDirectoryPath = path
|
currentDirectoryPath = path
|
||||||
currentPathText.text = getString(R.string.location, currentDirectoryPath)
|
currentPathText.text = getString(R.string.location, currentDirectoryPath)
|
||||||
displayNumberOfElements(numberOfFilesText, R.string.one_file, R.string.multiple_files, explorerElements.count { it.isRegularFile })
|
displayNumberOfElements(numberOfFilesText, R.string.one_file, R.string.multiple_files, explorerElements.count { it.isRegularFile })
|
||||||
displayNumberOfElements(numberOfFoldersText, R.string.one_folder, R.string.multiple_folders, explorerElements.count { it.isDirectory })
|
displayNumberOfElements(numberOfFoldersText, R.string.one_folder, R.string.multiple_folders, explorerElements.count { it.isDirectory })
|
||||||
if (mapFolders) {
|
if (mapFolders) {
|
||||||
lifecycleScope.launch {
|
|
||||||
var totalSize: Long = 0
|
var totalSize: Long = 0
|
||||||
withContext(Dispatchers.IO) {
|
directoryLoadingTask = launch(Dispatchers.IO) {
|
||||||
synchronized(this@BaseExplorerActivity) {
|
|
||||||
for (element in explorerElements) {
|
for (element in explorerElements) {
|
||||||
if (element.isDirectory) {
|
if (element.isDirectory) {
|
||||||
recursiveSetSize(element)
|
recursiveSetSize(element)
|
||||||
@ -373,11 +378,10 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
totalSize += element.stat.size
|
totalSize += element.stat.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
directoryLoadingTask!!.join()
|
||||||
displayExplorerElements()
|
displayExplorerElements()
|
||||||
totalSizeText.text = getString(R.string.total_size, PathUtils.formatSize(totalSize))
|
totalSizeText.text = getString(R.string.total_size, PathUtils.formatSize(totalSize))
|
||||||
onDisplayed?.invoke()
|
onDisplayed?.invoke()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
displayExplorerElements()
|
displayExplorerElements()
|
||||||
totalSizeText.text = getString(
|
totalSizeText.text = getString(
|
||||||
@ -607,7 +611,13 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
|
|||||||
.setTitle(R.string.sort_order)
|
.setTitle(R.string.sort_order)
|
||||||
.setSingleChoiceItems(sortOrderEntries, currentSortOrderIndex) { dialog, which ->
|
.setSingleChoiceItems(sortOrderEntries, currentSortOrderIndex) { dialog, which ->
|
||||||
currentSortOrderIndex = which
|
currentSortOrderIndex = which
|
||||||
|
// displayExplorerElements must not be called if directoryLoadingTask is active
|
||||||
|
if (directoryLoadingTask?.isActive != true) {
|
||||||
displayExplorerElements()
|
displayExplorerElements()
|
||||||
|
}
|
||||||
|
val sharedPrefsEditor = sharedPrefs.edit()
|
||||||
|
sharedPrefsEditor.putString(Constants.SORT_ORDER_KEY, sortOrderValues[currentSortOrderIndex])
|
||||||
|
sharedPrefsEditor.apply()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
@ -10,6 +10,12 @@
|
|||||||
android:text="@string/dir_empty"
|
android:text="@string/dir_empty"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/loader"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"/>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/refresher"
|
android:id="@+id/refresher"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Loading…
Reference in New Issue
Block a user