Don't cancel file operations when changing configuration

This commit is contained in:
Matéo Duparc 2022-06-29 14:47:50 +02:00
parent e01932acda
commit 8709abd7d7
Signed by untrusted user: hardcoresushi
GPG Key ID: AFE384344A45E13A
4 changed files with 12 additions and 13 deletions

View File

@ -21,9 +21,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager 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.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import sushi.hardcore.droidfs.BaseActivity import sushi.hardcore.droidfs.BaseActivity
import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.ConstValues.isAudio import sushi.hardcore.droidfs.ConstValues.isAudio
@ -60,6 +58,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
explorerViewModel.currentDirectoryPath = value explorerViewModel.currentDirectoryPath = value
} }
protected lateinit var fileOperationService: FileOperationService protected lateinit var fileOperationService: FileOperationService
protected val taskScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
protected lateinit var explorerElements: MutableList<ExplorerElement> protected lateinit var explorerElements: MutableList<ExplorerElement>
protected lateinit var explorerAdapter: ExplorerElementAdapter protected lateinit var explorerAdapter: ExplorerElementAdapter
private var isCreating = true private var isCreating = true
@ -464,7 +463,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
if (items.size > 0) { if (items.size > 0) {
checkPathOverwrite(items, currentDirectoryPath) { checkedItems -> checkPathOverwrite(items, currentDirectoryPath) { checkedItems ->
checkedItems?.let { checkedItems?.let {
lifecycleScope.launch { taskScope.launch {
val taskResult = fileOperationService.importFilesFromUris(checkedItems.map { it.dstPath!! }, uris) val taskResult = fileOperationService.importFilesFromUris(checkedItems.map { it.dstPath!! }, uris)
if (taskResult.cancelled) { if (taskResult.cancelled) {
setCurrentPath(currentDirectoryPath) setCurrentPath(currentDirectoryPath)
@ -593,6 +592,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
} }
protected open fun closeVolumeOnDestroy() { protected open fun closeVolumeOnDestroy() {
taskScope.cancel()
if (!encryptedVolume.isClosed()) { if (!encryptedVolume.isClosed()) {
encryptedVolume.close() encryptedVolume.close()
} }

View File

@ -8,7 +8,6 @@ import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import sushi.hardcore.droidfs.CameraActivity import sushi.hardcore.droidfs.CameraActivity
import sushi.hardcore.droidfs.MainActivity import sushi.hardcore.droidfs.MainActivity
@ -64,7 +63,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (items == null) { if (items == null) {
remoteEncryptedVolume.close() remoteEncryptedVolume.close()
} else { } else {
lifecycleScope.launch { taskScope.launch {
val failedItem = fileOperationService.copyElements(items, remoteEncryptedVolume) val failedItem = fileOperationService.copyElements(items, remoteEncryptedVolume)
if (failedItem == null) { if (failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.success_import, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.success_import, Toast.LENGTH_SHORT).show()
@ -95,7 +94,7 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
private val pickExportDirectory = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri -> private val pickExportDirectory = registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri ->
if (uri != null) { if (uri != null) {
lifecycleScope.launch { taskScope.launch {
val result = fileOperationService.exportFiles(uri, explorerAdapter.selectedItems.map { i -> explorerElements[i] }) val result = fileOperationService.exportFiles(uri, explorerAdapter.selectedItems.map { i -> explorerElements[i] })
if (!result.cancelled) { if (!result.cancelled) {
if (result.failedItem == null) { if (result.failedItem == null) {
@ -118,7 +117,7 @@ class ExplorerActivity : BaseExplorerActivity() {
val operation = OperationFile(PathUtils.pathJoin(currentDirectoryPath, tree.name!!), Stat.S_IFDIR) val operation = OperationFile(PathUtils.pathJoin(currentDirectoryPath, tree.name!!), Stat.S_IFDIR)
checkPathOverwrite(arrayListOf(operation), currentDirectoryPath) { checkedOperation -> checkPathOverwrite(arrayListOf(operation), currentDirectoryPath) { checkedOperation ->
checkedOperation?.let { checkedOperation?.let {
lifecycleScope.launch { taskScope.launch {
val result = fileOperationService.importDirectory(checkedOperation[0].dstPath!!, tree) val result = fileOperationService.importDirectory(checkedOperation[0].dstPath!!, tree)
if (result.taskResult.cancelled) { if (result.taskResult.cancelled) {
setCurrentPath(currentDirectoryPath) setCurrentPath(currentDirectoryPath)
@ -140,7 +139,7 @@ class ExplorerActivity : BaseExplorerActivity() {
${getString(R.string.ask_for_wipe)} ${getString(R.string.ask_for_wipe)}
""".trimIndent()) """.trimIndent())
.setPositiveButton(R.string.yes) { _, _ -> .setPositiveButton(R.string.yes) { _, _ ->
lifecycleScope.launch { taskScope.launch {
val errorMsg = fileOperationService.wipeUris(urisToWipe, rootFile) val errorMsg = fileOperationService.wipeUris(urisToWipe, rootFile)
if (errorMsg == null) { if (errorMsg == null) {
Toast.makeText(this@ExplorerActivity, R.string.wipe_successful, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.wipe_successful, Toast.LENGTH_SHORT).show()
@ -320,7 +319,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (currentItemAction == ItemsActions.COPY){ if (currentItemAction == ItemsActions.COPY){
checkPathOverwrite(itemsToProcess, currentDirectoryPath){ items -> checkPathOverwrite(itemsToProcess, currentDirectoryPath){ items ->
items?.let { items?.let {
lifecycleScope.launch { taskScope.launch {
val failedItem = fileOperationService.copyElements(it.toMutableList() as ArrayList<OperationFile>) val failedItem = fileOperationService.copyElements(it.toMutableList() as ArrayList<OperationFile>)
if (!isFinishing) { if (!isFinishing) {
if (failedItem == null) { if (failedItem == null) {
@ -351,7 +350,7 @@ class ExplorerActivity : BaseExplorerActivity() {
toMove, toMove,
toClean, toClean,
) { ) {
lifecycleScope.launch { taskScope.launch {
val failedItem = fileOperationService.moveElements(toMove, toClean) val failedItem = fileOperationService.moveElements(toMove, toClean)
if (failedItem == null) { if (failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.move_success, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.move_success, Toast.LENGTH_SHORT).show()

View File

@ -83,7 +83,7 @@ class ExplorerActivityPick : BaseExplorerActivity() {
override fun closeVolumeOnDestroy() { override fun closeVolumeOnDestroy() {
if (!isFinishingIntentionally && !usf_keep_open){ if (!isFinishingIntentionally && !usf_keep_open){
intent.getParcelableExtra<EncryptedVolume>("destinationVolume")?.let { it.close() } intent.getParcelableExtra<EncryptedVolume>("destinationVolume")?.close()
super.closeVolumeOnDestroy() super.closeVolumeOnDestroy()
} }
} }

View File

@ -110,7 +110,7 @@ class FileOperationService : Service() {
tasks[notificationId]?.cancel() tasks[notificationId]?.cancel()
} }
open class TaskResult<T>(val cancelled: Boolean, val failedItem: T?) class TaskResult<T>(val cancelled: Boolean, val failedItem: T?)
private suspend fun <T> waitForTask(notification: FileOperationNotification, task: Deferred<T>): TaskResult<T> { private suspend fun <T> waitForTask(notification: FileOperationNotification, task: Deferred<T>): TaskResult<T> {
tasks[notification.notificationId] = task tasks[notification.notificationId] = task