[Android] Extract media file deletion code from UI

Geoffrey Métais git at videolan.org
Fri Apr 10 13:35:08 CEST 2020


vlc-android | branch: master | Geoffrey Métais <geoffrey.metais at gmail.com> | Thu Apr  9 15:33:17 2020 +0200| [03e0f78931a4ee1bf3fce3a47a3ff3abc409bdc1] | committer: Nicolas Pomepuy

Extract media file deletion code from UI

> https://code.videolan.org/videolan/vlc-android/commit/03e0f78931a4ee1bf3fce3a47a3ff3abc409bdc1
---

 .../vlc/gui/browser/BaseBrowserFragment.kt         |  2 +-
 .../vlc/gui/browser/MediaBrowserFragment.kt        | 46 ++++++----------------
 .../src/org/videolan/vlc/gui/helpers/UiTools.kt    |  1 +
 .../src/org/videolan/vlc/media/MediaUtils.kt       | 21 ++++++++++
 4 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
index 4646410ae..a05ffa08a 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.kt
@@ -334,7 +334,7 @@ abstract class BaseBrowserFragment : MediaBrowserFragment<BrowserModel>(), IRefr
         val cancel = Runnable { viewModel.refresh() }
         val deleteAction = Runnable {
             lifecycleScope.launch {
-                deleteMedia(mw, false, cancel)
+                MediaUtils.deleteMedia(mw, cancel)
                 viewModel.remove(mw)
             }
         }
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt
index 8a96ec1e8..06e573195 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt
@@ -60,12 +60,10 @@ import org.videolan.vlc.gui.helpers.hf.StoragePermissionsDelegate.Companion.getW
 import org.videolan.vlc.gui.view.SwipeRefreshLayout
 import org.videolan.vlc.interfaces.Filterable
 import org.videolan.vlc.media.MediaUtils
-import org.videolan.vlc.util.FileUtils
 import org.videolan.vlc.util.Permissions
 import org.videolan.vlc.viewmodels.MedialibraryViewModel
 import org.videolan.vlc.viewmodels.SortableModel
 import java.lang.Runnable
-import java.util.*
 
 private const val TAG = "VLC/MediaBrowserFragment"
 private const val KEY_SELECTION = "key_selection"
@@ -184,7 +182,7 @@ abstract class MediaBrowserFragment<T : SortableModel> : Fragment(), ActionMode.
             for (item in items) {
                 if (!isStarted()) break
                 when(item) {
-                    is MediaWrapper -> if (getWritePermission(item.uri)) deleteMedia(item)
+                    is MediaWrapper -> if (getWritePermission(item.uri)) MediaUtils.deleteMedia(item)
                     is Playlist -> withContext(Dispatchers.IO) { item.delete() }
                 }
             }
@@ -194,46 +192,24 @@ abstract class MediaBrowserFragment<T : SortableModel> : Fragment(), ActionMode.
 
     protected open fun removeItem(item: MediaLibraryItem): Boolean {
         val view = view ?: return false
-        when (item.itemType) {
-            MediaLibraryItem.TYPE_PLAYLIST -> snackerConfirm(view, getString(R.string.confirm_delete_playlist, item.title), Runnable { MediaUtils.deletePlaylist(item as Playlist) })
-            MediaLibraryItem.TYPE_MEDIA -> {
+        when (item) {
+            is Playlist -> lifecycleScope.snackerConfirm(view, getString(R.string.confirm_delete_playlist, item.title)) { MediaUtils.deletePlaylist(item) }
+            is MediaWrapper -> {
                 val deleteAction = Runnable {
-                    if (isStarted()) lifecycleScope.launch { deleteMedia(item, false, null) }
+                    if (isStarted()) lifecycleScope.launch {
+                        if (!MediaUtils.deleteMedia(item, null)) onDeleteFailed(item)
+                    }
                 }
-                val resid = if ((item as MediaWrapper).type == MediaWrapper.TYPE_DIR) R.string.confirm_delete_folder else R.string.confirm_delete
-                snackerConfirm(view, getString(resid, item.getTitle()), Runnable { if (Permissions.checkWritePermission(requireActivity(), item, deleteAction)) deleteAction.run() })
+                val resid = if (item.type == MediaWrapper.TYPE_DIR) R.string.confirm_delete_folder else R.string.confirm_delete
+                lifecycleScope.snackerConfirm(view, getString(resid, item.getTitle())) { if (Permissions.checkWritePermission(requireActivity(), item, deleteAction)) deleteAction.run() }
             }
             else -> return false
         }
         return true
     }
 
-    protected suspend fun deleteMedia(mw: MediaLibraryItem, refresh: Boolean = false, failCB: Runnable? = null) = withContext(Dispatchers.IO) {
-        val foldersToReload = LinkedList<String>()
-        val mediaPaths = LinkedList<String>()
-        for (media in mw.tracks) {
-            val path = media.uri.path
-            val parentPath = FileUtils.getParent(path)
-            if (FileUtils.deleteFile(media.uri)) parentPath?.let {
-                if (media.id > 0L && !foldersToReload.contains(it)) {
-                    foldersToReload.add(it)
-                }
-                mediaPaths.add(media.location)
-            } else
-                onDeleteFailed(media)
-        }
-        for (folder in foldersToReload) mediaLibrary.reload(folder)
-        if (isStarted()) launch {
-            if (mediaPaths.isEmpty()) {
-                failCB?.run()
-                return at launch
-            }
-            if (refresh) onRefresh()
-        }
-    }
-
-    private fun onDeleteFailed(media: MediaWrapper) {
-        if (isAdded) view?.let { UiTools.snacker(it, getString(R.string.msg_delete_failed, media.title)) }
+    private fun onDeleteFailed(item: MediaLibraryItem) {
+        if (isAdded) view?.let { UiTools.snacker(it, getString(R.string.msg_delete_failed, item.title)) }
     }
 
     protected fun showInfoDialog(item: MediaLibraryItem) {
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
index 358cc73b1..116e8b2ed 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt
@@ -219,6 +219,7 @@ object UiTools {
             snack.view.elevation = view.resources.getDimensionPixelSize(R.dimen.audio_player_elevation).toFloat()
         snack.show()
     }
+
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     fun CoroutineScope.snackerConfirm(view: View, message: String, action: suspend() -> Unit) {
         val snack = Snackbar.make(view, message, Snackbar.LENGTH_LONG)
diff --git a/application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt b/application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt
index ac5cb4636..766b848ed 100644
--- a/application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt
+++ b/application/vlc-android/src/org/videolan/vlc/media/MediaUtils.kt
@@ -73,6 +73,27 @@ object MediaUtils {
         else Permissions.askWriteStoragePermission(activity, false, callBack)
     }
 
+    suspend fun deleteMedia(mw: MediaLibraryItem, failCB: Runnable? = null) = withContext(Dispatchers.IO) {
+        val foldersToReload = LinkedList<String>()
+        val mediaPaths = LinkedList<String>()
+        for (media in mw.tracks) {
+            val path = media.uri.path
+            val parentPath = FileUtils.getParent(path)
+            if (FileUtils.deleteFile(media.uri)) parentPath?.let {
+                if (media.id > 0L && !foldersToReload.contains(it)) {
+                    foldersToReload.add(it)
+                }
+                mediaPaths.add(media.location)
+            }
+        }
+        val mediaLibrary = Medialibrary.getInstance()
+        for (folder in foldersToReload) mediaLibrary.reload(folder)
+        if (mediaPaths.isEmpty()) {
+            failCB?.run()
+            false
+        } else true
+    }
+
     fun loadlastPlaylist(context: Context?, type: Int) {
         if (context == null) return
         SuspendDialogCallback(context) { service -> service.loadLastPlaylist(type) }



More information about the Android mailing list