浏览代码

refactor: EuiccChannelFragmentUtils (#164)

Reviewed-on: https://gitea.angry.im/PeterCxy/OpenEUICC/pulls/164
Co-authored-by: septs <github@septs.pw>
Co-committed-by: septs <github@septs.pw>
septs 11 月之前
父节点
当前提交
2eabf719d0

+ 7 - 17
app-common/src/main/java/im/angry/openeuicc/ui/ProfileDeleteFragment.kt

@@ -20,13 +20,10 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
         private const val FIELD_ICCID = "iccid"
         private const val FIELD_NAME = "name"
 
-        fun newInstance(slotId: Int, portId: Int, iccid: String, name: String): ProfileDeleteFragment {
-            val instance = newInstanceEuicc(ProfileDeleteFragment::class.java, slotId, portId)
-            instance.requireArguments().apply {
+        fun newInstance(slotId: Int, portId: Int, iccid: String, name: String) =
+            newInstanceEuicc(ProfileDeleteFragment::class.java, slotId, portId) {
                 putString(FIELD_ICCID, iccid)
                 putString(FIELD_NAME, name)
-            }
-            return instance
         }
     }
 
@@ -91,19 +88,12 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
         requireParentFragment().lifecycleScope.launch {
             ensureEuiccChannelManager()
             euiccChannelManagerService.waitForForegroundTask()
-            euiccChannelManagerService.launchProfileDeleteTask(slotId, portId, 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()
-                }
-
-                try {
-                    dismiss()
-                } catch (e: IllegalStateException) {
-                    // Ignored
+            euiccChannelManagerService.launchProfileDeleteTask(slotId, portId, iccid)
+                .onStart {
+                    parentFragment?.notifyEuiccProfilesChanged()
+                    runCatching(::dismiss)
                 }
-            }.waitDone()
+                .waitDone()
         }
     }
 }

+ 28 - 31
app-common/src/main/java/im/angry/openeuicc/ui/ProfileRenameFragment.kt

@@ -7,6 +7,7 @@ import android.view.View
 import android.view.ViewGroup
 import android.widget.ProgressBar
 import android.widget.Toast
+import androidx.annotation.StringRes
 import androidx.appcompat.widget.Toolbar
 import androidx.lifecycle.lifecycleScope
 import com.google.android.material.textfield.TextInputLayout
@@ -18,16 +19,16 @@ import net.typeblog.lpac_jni.LocalProfileAssistant
 
 class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragmentMarker {
     companion object {
+        private const val FIELD_ICCID = "iccid"
+        private const val FIELD_CURRENT_NAME = "currentName"
+
         const val TAG = "ProfileRenameFragment"
 
-        fun newInstance(slotId: Int, portId: Int, iccid: String, currentName: String): ProfileRenameFragment {
-            val instance = newInstanceEuicc(ProfileRenameFragment::class.java, slotId, portId)
-            instance.requireArguments().apply {
-                putString("iccid", iccid)
-                putString("currentName", currentName)
+        fun newInstance(slotId: Int, portId: Int, iccid: String, currentName: String) =
+            newInstanceEuicc(ProfileRenameFragment::class.java, slotId, portId) {
+                putString(FIELD_ICCID, iccid)
+                putString(FIELD_CURRENT_NAME, currentName)
             }
-            return instance
-        }
     }
 
     private lateinit var toolbar: Toolbar
@@ -36,6 +37,14 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
 
     private var renaming = false
 
+    private val iccid: String by lazy {
+        requireArguments().getString(FIELD_ICCID)!!
+    }
+
+    private val currentName: String by lazy {
+        requireArguments().getString(FIELD_CURRENT_NAME)!!
+    }
+
     override fun onCreateView(
         inflater: LayoutInflater,
         container: ViewGroup?,
@@ -54,7 +63,7 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
-        profileRenameNewName.editText!!.setText(requireArguments().getString("currentName"))
+        profileRenameNewName.editText!!.setText(currentName)
         toolbar.apply {
             setTitle(R.string.rename)
             setNavigationOnClickListener {
@@ -78,12 +87,8 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
         }
     }
 
-    private fun showErrorAndCancel(errorStrRes: Int) {
-        Toast.makeText(
-            requireContext(),
-            errorStrRes,
-            Toast.LENGTH_LONG
-        ).show()
+    private fun showErrorAndCancel(@StringRes resId: Int) {
+        Toast.makeText(requireContext(), resId, Toast.LENGTH_LONG).show()
 
         renaming = false
         progress.visibility = View.GONE
@@ -94,17 +99,15 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
         progress.isIndeterminate = true
         progress.visibility = View.VISIBLE
 
+        val newName = profileRenameNewName.editText!!.text.toString().trim()
+
         lifecycleScope.launch {
             ensureEuiccChannelManager()
             euiccChannelManagerService.waitForForegroundTask()
-            val res = euiccChannelManagerService.launchProfileRenameTask(
-                slotId,
-                portId,
-                requireArguments().getString("iccid")!!,
-                profileRenameNewName.editText!!.text.toString().trim()
-            ).waitDone()
-
-            when (res) {
+            val response = euiccChannelManagerService
+                .launchProfileRenameTask(slotId, portId, iccid, newName).waitDone()
+
+            when (response) {
                 is LocalProfileAssistant.ProfileNameTooLongException -> {
                     showErrorAndCancel(R.string.profile_rename_too_long)
                 }
@@ -118,15 +121,9 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
                 }
 
                 else -> {
-                    if (parentFragment is EuiccProfilesChangedListener) {
-                        (parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged()
-                    }
-
-                    try {
-                        dismiss()
-                    } catch (e: IllegalStateException) {
-                        // Ignored
-                    }
+                    parentFragment?.notifyEuiccProfilesChanged()
+
+                    runCatching(::dismiss)
                 }
             }
         }

+ 46 - 24
app-common/src/main/java/im/angry/openeuicc/util/EuiccChannelFragmentUtils.kt

@@ -7,43 +7,65 @@ import im.angry.openeuicc.core.EuiccChannelManager
 import im.angry.openeuicc.service.EuiccChannelManagerService
 import im.angry.openeuicc.ui.BaseEuiccAccessActivity
 
-interface EuiccChannelFragmentMarker: OpenEuiccContextMarker
+private const val FIELD_SLOT_ID = "slotId"
+private const val FIELD_PORT_ID = "portId"
+
+interface EuiccChannelFragmentMarker : OpenEuiccContextMarker
+
+private typealias BundleSetter = Bundle.() -> Unit
 
 // We must use extension functions because there is no way to add bounds to the type of "self"
 // in the definition of an interface, so the only way is to limit where the extension functions
 // can be applied.
-fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: Bundle.() -> Unit = {}): T where T: Fragment, T: EuiccChannelFragmentMarker {
-    val instance = clazz.newInstance()
-    instance.arguments = Bundle().apply {
-        putInt("slotId", slotId)
-        putInt("portId", portId)
-        addArguments()
+fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: BundleSetter = {}): T
+        where T : Fragment, T : EuiccChannelFragmentMarker =
+    clazz.getDeclaredConstructor().newInstance().apply {
+        arguments = Bundle()
+        arguments!!.putInt(FIELD_SLOT_ID, slotId)
+        arguments!!.putInt(FIELD_PORT_ID, portId)
+        arguments!!.addArguments()
     }
-    return instance
-}
 
 // Convenient methods to avoid using `channel` for these
 // `channel` requires that the channel actually exists in EuiccChannelManager, which is
 // not always the case during operations such as switching
-val <T> T.slotId: Int where T: Fragment, T: EuiccChannelFragmentMarker
-    get() = requireArguments().getInt("slotId")
-val <T> T.portId: Int where T: Fragment, T: EuiccChannelFragmentMarker
-    get() = requireArguments().getInt("portId")
-val <T> T.isUsb: Boolean where T: Fragment, T: EuiccChannelFragmentMarker
-    get() = requireArguments().getInt("slotId") == EuiccChannelManager.USB_CHANNEL_ID
-
-val <T> T.euiccChannelManager: EuiccChannelManager where T: Fragment, T: OpenEuiccContextMarker
-    get() = (requireActivity() as BaseEuiccAccessActivity).euiccChannelManager
-val <T> T.euiccChannelManagerService: EuiccChannelManagerService where T: Fragment, T: OpenEuiccContextMarker
-    get() = (requireActivity() as BaseEuiccAccessActivity).euiccChannelManagerService
-
-suspend fun <T, R> T.withEuiccChannel(fn: suspend (EuiccChannel) -> R): R where T : Fragment, T : EuiccChannelFragmentMarker {
+val <T> T.slotId: Int
+        where T : Fragment, T : EuiccChannelFragmentMarker
+    get() = requireArguments().getInt(FIELD_SLOT_ID)
+val <T> T.portId: Int
+        where T : Fragment, T : EuiccChannelFragmentMarker
+    get() = requireArguments().getInt(FIELD_PORT_ID)
+val <T> T.isUsb: Boolean
+        where T : Fragment, T : EuiccChannelFragmentMarker
+    get() = slotId == EuiccChannelManager.USB_CHANNEL_ID
+
+private fun <T> T.requireEuiccActivity(): BaseEuiccAccessActivity
+        where T : Fragment, T : OpenEuiccContextMarker =
+    requireActivity() as BaseEuiccAccessActivity
+
+val <T> T.euiccChannelManager: EuiccChannelManager
+        where T : Fragment, T : OpenEuiccContextMarker
+    get() = requireEuiccActivity().euiccChannelManager
+
+val <T> T.euiccChannelManagerService: EuiccChannelManagerService
+        where T : Fragment, T : OpenEuiccContextMarker
+    get() = requireEuiccActivity().euiccChannelManagerService
+
+suspend fun <T, R> T.withEuiccChannel(fn: suspend (EuiccChannel) -> R): R
+        where T : Fragment, T : EuiccChannelFragmentMarker {
     ensureEuiccChannelManager()
     return euiccChannelManager.withEuiccChannel(slotId, portId, fn)
 }
 
-suspend fun <T> T.ensureEuiccChannelManager() where T: Fragment, T: OpenEuiccContextMarker =
-    (requireActivity() as BaseEuiccAccessActivity).euiccChannelManagerLoaded.await()
+suspend fun <T> T.ensureEuiccChannelManager() where T : Fragment, T : OpenEuiccContextMarker =
+    requireEuiccActivity().euiccChannelManagerLoaded.await()
+
+fun <T> T.notifyEuiccProfilesChanged() where T : Fragment {
+    if (this !is EuiccProfilesChangedListener) return
+    // Trigger a refresh in the parent fragment -- it should wait until
+    // any foreground task is completed before actually doing a refresh
+    this.onEuiccProfilesChanged()
+}
 
 interface EuiccProfilesChangedListener {
     fun onEuiccProfilesChanged()