refactor: EuiccChannelFragmentUtils #164
3 changed files with 77 additions and 68 deletions
|
@ -20,14 +20,11 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
|
||||||
private const val FIELD_ICCID = "iccid"
|
private const val FIELD_ICCID = "iccid"
|
||||||
private const val FIELD_NAME = "name"
|
private const val FIELD_NAME = "name"
|
||||||
|
|
||||||
fun newInstance(slotId: Int, portId: Int, iccid: String, name: String): ProfileDeleteFragment {
|
fun newInstance(slotId: Int, portId: Int, iccid: String, name: String) =
|
||||||
val instance = newInstanceEuicc(ProfileDeleteFragment::class.java, slotId, portId)
|
newInstanceEuicc(ProfileDeleteFragment::class.java, slotId, portId) {
|
||||||
instance.requireArguments().apply {
|
|
||||||
putString(FIELD_ICCID, iccid)
|
putString(FIELD_ICCID, iccid)
|
||||||
putString(FIELD_NAME, name)
|
putString(FIELD_NAME, name)
|
||||||
}
|
}
|
||||||
return instance
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val iccid by lazy {
|
private val iccid by lazy {
|
||||||
|
@ -91,19 +88,12 @@ class ProfileDeleteFragment : DialogFragment(), EuiccChannelFragmentMarker {
|
||||||
requireParentFragment().lifecycleScope.launch {
|
requireParentFragment().lifecycleScope.launch {
|
||||||
ensureEuiccChannelManager()
|
ensureEuiccChannelManager()
|
||||||
euiccChannelManagerService.waitForForegroundTask()
|
euiccChannelManagerService.waitForForegroundTask()
|
||||||
euiccChannelManagerService.launchProfileDeleteTask(slotId, portId, iccid).onStart {
|
euiccChannelManagerService.launchProfileDeleteTask(slotId, portId, iccid)
|
||||||
if (parentFragment is EuiccProfilesChangedListener) {
|
.onStart {
|
||||||
// Trigger a refresh in the parent fragment -- it should wait until
|
parentFragment?.notifyEuiccProfilesChanged()
|
||||||
// any foreground task is completed before actually doing a refresh
|
runCatching(::dismiss)
|
||||||
(parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged()
|
|
||||||
}
|
}
|
||||||
|
.waitDone()
|
||||||
try {
|
|
||||||
dismiss()
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
}.waitDone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
@ -18,15 +19,15 @@ import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
|
|
||||||
class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragmentMarker {
|
class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragmentMarker {
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val FIELD_ICCID = "iccid"
|
||||||
|
private const val FIELD_CURRENT_NAME = "currentName"
|
||||||
|
|
||||||
const val TAG = "ProfileRenameFragment"
|
const val TAG = "ProfileRenameFragment"
|
||||||
|
|
||||||
fun newInstance(slotId: Int, portId: Int, iccid: String, currentName: String): ProfileRenameFragment {
|
fun newInstance(slotId: Int, portId: Int, iccid: String, currentName: String) =
|
||||||
val instance = newInstanceEuicc(ProfileRenameFragment::class.java, slotId, portId)
|
newInstanceEuicc(ProfileRenameFragment::class.java, slotId, portId) {
|
||||||
instance.requireArguments().apply {
|
putString(FIELD_ICCID, iccid)
|
||||||
putString("iccid", iccid)
|
putString(FIELD_CURRENT_NAME, currentName)
|
||||||
putString("currentName", currentName)
|
|
||||||
}
|
|
||||||
return instance
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +37,14 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
|
|
||||||
private var renaming = false
|
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(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
|
@ -54,7 +63,7 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
profileRenameNewName.editText!!.setText(requireArguments().getString("currentName"))
|
profileRenameNewName.editText!!.setText(currentName)
|
||||||
toolbar.apply {
|
toolbar.apply {
|
||||||
setTitle(R.string.rename)
|
setTitle(R.string.rename)
|
||||||
setNavigationOnClickListener {
|
setNavigationOnClickListener {
|
||||||
|
@ -78,12 +87,8 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showErrorAndCancel(errorStrRes: Int) {
|
private fun showErrorAndCancel(@StringRes resId: Int) {
|
||||||
Toast.makeText(
|
Toast.makeText(requireContext(), resId, Toast.LENGTH_LONG).show()
|
||||||
requireContext(),
|
|
||||||
errorStrRes,
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
|
|
||||||
renaming = false
|
renaming = false
|
||||||
progress.visibility = View.GONE
|
progress.visibility = View.GONE
|
||||||
|
@ -94,17 +99,15 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
progress.isIndeterminate = true
|
progress.isIndeterminate = true
|
||||||
progress.visibility = View.VISIBLE
|
progress.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
val newName = profileRenameNewName.editText!!.text.toString().trim()
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
ensureEuiccChannelManager()
|
ensureEuiccChannelManager()
|
||||||
euiccChannelManagerService.waitForForegroundTask()
|
euiccChannelManagerService.waitForForegroundTask()
|
||||||
val res = euiccChannelManagerService.launchProfileRenameTask(
|
val response = euiccChannelManagerService
|
||||||
slotId,
|
.launchProfileRenameTask(slotId, portId, iccid, newName).waitDone()
|
||||||
portId,
|
|
||||||
requireArguments().getString("iccid")!!,
|
|
||||||
profileRenameNewName.editText!!.text.toString().trim()
|
|
||||||
).waitDone()
|
|
||||||
|
|
||||||
when (res) {
|
when (response) {
|
||||||
is LocalProfileAssistant.ProfileNameTooLongException -> {
|
is LocalProfileAssistant.ProfileNameTooLongException -> {
|
||||||
showErrorAndCancel(R.string.profile_rename_too_long)
|
showErrorAndCancel(R.string.profile_rename_too_long)
|
||||||
}
|
}
|
||||||
|
@ -118,15 +121,9 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
if (parentFragment is EuiccProfilesChangedListener) {
|
parentFragment?.notifyEuiccProfilesChanged()
|
||||||
(parentFragment as EuiccProfilesChangedListener).onEuiccProfilesChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
runCatching(::dismiss)
|
||||||
dismiss()
|
|
||||||
} catch (e: IllegalStateException) {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,43 +7,65 @@ import im.angry.openeuicc.core.EuiccChannelManager
|
||||||
import im.angry.openeuicc.service.EuiccChannelManagerService
|
import im.angry.openeuicc.service.EuiccChannelManagerService
|
||||||
import im.angry.openeuicc.ui.BaseEuiccAccessActivity
|
import im.angry.openeuicc.ui.BaseEuiccAccessActivity
|
||||||
|
|
||||||
|
private const val FIELD_SLOT_ID = "slotId"
|
||||||
|
private const val FIELD_PORT_ID = "portId"
|
||||||
|
|
||||||
interface EuiccChannelFragmentMarker : OpenEuiccContextMarker
|
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"
|
// 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
|
// in the definition of an interface, so the only way is to limit where the extension functions
|
||||||
// can be applied.
|
// can be applied.
|
||||||
fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: Bundle.() -> Unit = {}): T where T: Fragment, T: EuiccChannelFragmentMarker {
|
fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: BundleSetter = {}): T
|
||||||
val instance = clazz.newInstance()
|
where T : Fragment, T : EuiccChannelFragmentMarker =
|
||||||
instance.arguments = Bundle().apply {
|
clazz.getDeclaredConstructor().newInstance().apply {
|
||||||
putInt("slotId", slotId)
|
arguments = Bundle()
|
||||||
putInt("portId", portId)
|
arguments!!.putInt(FIELD_SLOT_ID, slotId)
|
||||||
addArguments()
|
arguments!!.putInt(FIELD_PORT_ID, portId)
|
||||||
}
|
arguments!!.addArguments()
|
||||||
return instance
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenient methods to avoid using `channel` for these
|
// Convenient methods to avoid using `channel` for these
|
||||||
// `channel` requires that the channel actually exists in EuiccChannelManager, which is
|
// `channel` requires that the channel actually exists in EuiccChannelManager, which is
|
||||||
// not always the case during operations such as switching
|
// not always the case during operations such as switching
|
||||||
val <T> T.slotId: Int where T: Fragment, T: EuiccChannelFragmentMarker
|
val <T> T.slotId: Int
|
||||||
get() = requireArguments().getInt("slotId")
|
where T : Fragment, T : EuiccChannelFragmentMarker
|
||||||
val <T> T.portId: Int where T: Fragment, T: EuiccChannelFragmentMarker
|
get() = requireArguments().getInt(FIELD_SLOT_ID)
|
||||||
get() = requireArguments().getInt("portId")
|
val <T> T.portId: Int
|
||||||
val <T> T.isUsb: Boolean where T: Fragment, T: EuiccChannelFragmentMarker
|
where T : Fragment, T : EuiccChannelFragmentMarker
|
||||||
get() = requireArguments().getInt("slotId") == EuiccChannelManager.USB_CHANNEL_ID
|
get() = requireArguments().getInt(FIELD_PORT_ID)
|
||||||
|
val <T> T.isUsb: Boolean
|
||||||
|
where T : Fragment, T : EuiccChannelFragmentMarker
|
||||||
|
get() = slotId == EuiccChannelManager.USB_CHANNEL_ID
|
||||||
|
|
||||||
val <T> T.euiccChannelManager: EuiccChannelManager where T: Fragment, T: OpenEuiccContextMarker
|
private fun <T> T.requireEuiccActivity(): BaseEuiccAccessActivity
|
||||||
get() = (requireActivity() as BaseEuiccAccessActivity).euiccChannelManager
|
where T : Fragment, T : OpenEuiccContextMarker =
|
||||||
val <T> T.euiccChannelManagerService: EuiccChannelManagerService where T: Fragment, T: OpenEuiccContextMarker
|
requireActivity() as BaseEuiccAccessActivity
|
||||||
get() = (requireActivity() as BaseEuiccAccessActivity).euiccChannelManagerService
|
|
||||||
|
|
||||||
suspend fun <T, R> T.withEuiccChannel(fn: suspend (EuiccChannel) -> R): R where T : Fragment, T : EuiccChannelFragmentMarker {
|
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()
|
ensureEuiccChannelManager()
|
||||||
return euiccChannelManager.withEuiccChannel(slotId, portId, fn)
|
return euiccChannelManager.withEuiccChannel(slotId, portId, fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun <T> T.ensureEuiccChannelManager() where T : Fragment, T : OpenEuiccContextMarker =
|
suspend fun <T> T.ensureEuiccChannelManager() where T : Fragment, T : OpenEuiccContextMarker =
|
||||||
(requireActivity() as BaseEuiccAccessActivity).euiccChannelManagerLoaded.await()
|
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 {
|
interface EuiccProfilesChangedListener {
|
||||||
fun onEuiccProfilesChanged()
|
fun onEuiccProfilesChanged()
|
||||||
|
|
Loading…
Add table
Reference in a new issue