瀏覽代碼

Move profile deletion to new flow

Peter Cai 1 年之前
父節點
當前提交
31c06470c6

+ 23 - 1
app-common/src/main/java/im/angry/openeuicc/service/EuiccChannelManagerService.kt

@@ -133,11 +133,14 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
      * Launch a potentially blocking foreground task in this service's lifecycle context.
      * This function does not block, but returns a Flow that emits ForegroundTaskState
      * updates associated with this task. The last update the returned flow will emit is
-     * always ForegroundTaskState.Done.
+     * always ForegroundTaskState.Done. The returned flow MUST be started in order for the
+     * foreground task to run.
      *
      * The task closure is expected to update foregroundTaskState whenever appropriate.
      * If a foreground task is already running, this function returns null.
      *
+     * To wait for foreground tasks to be available, use waitForForegroundTask().
+     *
      * The function will set the state back to Idle once it sees ForegroundTaskState.Done.
      */
     private fun launchForegroundTask(
@@ -262,4 +265,23 @@ class EuiccChannelManagerService : LifecycleService(), OpenEuiccContextMarker {
                 throw RuntimeException("Profile not renamed")
             }
         }
+
+    fun launchProfileDeleteTask(
+        slotId: Int,
+        portId: Int,
+        iccid: String
+    ): Flow<ForegroundTaskState>? =
+        launchForegroundTask(
+            getString(R.string.task_profile_delete),
+            R.drawable.ic_task_delete
+        ) {
+            euiccChannelManager.beginTrackedOperationBlocking(slotId, portId) {
+                euiccChannelManager.findEuiccChannelByPort(
+                    slotId,
+                    portId
+                )!!.lpa.deleteProfile(iccid)
+
+                preferenceRepository.notificationDeleteFlow.first()
+            }
+        }
 }

+ 15 - 16
app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt

@@ -3,16 +3,15 @@ package im.angry.openeuicc.ui
 import android.app.Dialog
 import android.os.Bundle
 import android.text.Editable
-import android.util.Log
 import android.widget.EditText
 import androidx.appcompat.app.AlertDialog
 import androidx.fragment.app.DialogFragment
 import androidx.lifecycle.lifecycleScope
 import im.angry.openeuicc.common.R
 import im.angry.openeuicc.util.*
-import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.launch
-import java.lang.Exception
 
 class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
     companion object {
@@ -67,23 +66,23 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
         alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false
         alertDialog.getButton(AlertDialog.BUTTON_NEGATIVE).isEnabled = false
 
-        lifecycleScope.launch {
-            try {
-                doDelete()
-            } catch (e: Exception) {
-                Log.d(ProfileDownloadFragment.TAG, "Error deleting profile")
-                Log.d(ProfileDownloadFragment.TAG, Log.getStackTraceString(e))
-            } finally {
+        requireParentFragment().lifecycleScope.launch {
+            ensureEuiccChannelManager()
+            euiccChannelManagerService.waitForForegroundTask()
+
+            euiccChannelManagerService.launchProfileDeleteTask(
+                slotId,
+                portId,
+                requireArguments().getString("iccid")!!
+            )!!.onStart {
                 if (parentFragment is EuiccProfilesChangedListener) {
+                    // Trigger a refresh in the parent fragment -- it should wait until
+                    // any foreground task is completed before actually doing a refresh
                     (parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged()
                 }
+
                 dismiss()
-            }
+            }.collect()
         }
     }
-
-    private suspend fun doDelete() = beginTrackedOperation {
-        channel.lpa.deleteProfile(requireArguments().getString("iccid")!!)
-        preferenceRepository.notificationDeleteFlow.first()
-    }
 }

+ 5 - 0
app-common/src/main/res/drawable/ic_task_delete.xml

@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+      
+    <path android:fillColor="@android:color/white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
+    
+</vector>

+ 1 - 0
app-common/src/main/res/values/strings.xml

@@ -36,6 +36,7 @@
     <string name="task_notification">Long-running Tasks</string>
     <string name="task_profile_download">Downloading eSIM profile</string>
     <string name="task_profile_rename">Renaming eSIM profile</string>
+    <string name="task_profile_delete">Deleting eSIM profile</string>
 
     <string name="profile_download">New eSIM</string>
     <string name="profile_download_server">Server (RSP / SM-DP+)</string>