diff --git a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt index 84b300e..0154803 100644 --- a/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt +++ b/app-common/src/main/java/im/angry/openeuicc/ui/EuiccInfoActivity.kt @@ -1,13 +1,18 @@ package im.angry.openeuicc.ui import android.annotation.SuppressLint +import android.content.ClipData +import android.content.ClipboardManager +import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.TextView +import android.widget.Toast import androidx.activity.enableEdgeToEdge +import androidx.annotation.StringRes import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager @@ -32,6 +37,13 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { private var logicalSlotId: Int = -1 + data class Item( + @StringRes + val titleResId: Int, + val content: String?, + val copiedToastResId: Int? = null + ) + override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) @@ -41,12 +53,11 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { supportActionBar!!.setDisplayHomeAsUpEnabled(true) swipeRefresh = requireViewById(R.id.swipe_refresh) - infoList = requireViewById(R.id.recycler_view) - - infoList.layoutManager = - LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) - infoList.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL)) - infoList.adapter = EuiccInfoAdapter() + infoList = requireViewById(R.id.recycler_view).also { + it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) + it.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL)) + it.adapter = EuiccInfoAdapter() + } logicalSlotId = intent.getIntExtra("logicalSlotId", 0) @@ -81,29 +92,33 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { lifecycleScope.launch { (infoList.adapter!! as EuiccInfoAdapter).euiccInfoItems = - euiccChannelManager.withEuiccChannel(logicalSlotId, ::buildPairs).map { - Pair(getString(it.first), it.second ?: getString(R.string.unknown)) - } + euiccChannelManager.withEuiccChannel(logicalSlotId, ::buildEuiccInfoItems) swipeRefresh.isRefreshing = false } } - private fun buildPairs(channel: EuiccChannel) = buildList { - add(Pair(R.string.euicc_info_access_mode, channel.type)) + private fun buildEuiccInfoItems(channel: EuiccChannel) = buildList { + add(Item(R.string.euicc_info_access_mode, channel.type)) add( - Pair( + Item( R.string.euicc_info_removable, formatByBoolean(channel.port.card.isRemovable, YES_NO) ) ) - add(Pair(R.string.euicc_info_eid, channel.lpa.eID)) + add( + Item( + R.string.euicc_info_eid, + channel.lpa.eID, + copiedToastResId = R.string.toast_eid_copied + ) + ) channel.lpa.euiccInfo2.let { info -> - add(Pair(R.string.euicc_info_firmware_version, info?.euiccFirmwareVersion)) - add(Pair(R.string.euicc_info_globalplatform_version, info?.globalPlatformVersion)) - add(Pair(R.string.euicc_info_pp_version, info?.ppVersion)) - add(Pair(R.string.euicc_info_sas_accreditation_number, info?.sasAccreditationNumber)) - add(Pair(R.string.euicc_info_free_nvram, info?.freeNvram?.let(::formatFreeSpace))) + add(Item(R.string.euicc_info_firmware_version, info?.euiccFirmwareVersion)) + add(Item(R.string.euicc_info_globalplatform_version, info?.globalPlatformVersion)) + add(Item(R.string.euicc_info_pp_version, info?.ppVersion)) + add(Item(R.string.euicc_info_sas_accreditation_number, info?.sasAccreditationNumber)) + add(Item(R.string.euicc_info_free_nvram, info?.freeNvram?.let(::formatFreeSpace))) } channel.lpa.euiccInfo2?.euiccCiPKIdListForSigning.orEmpty().let { signers -> // SGP.28 v1.0, eSIM CI Registration Criteria (Page 5 of 9, 2019-10-24) @@ -116,7 +131,7 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { PKID_GSMA_TEST_CI.any(signers::contains) -> R.string.euicc_info_ci_gsma_test else -> R.string.euicc_info_ci_unknown } - add(Pair(R.string.euicc_info_ci_type, getString(resId))) + add(Item(R.string.euicc_info_ci_type, getString(resId))) } } @@ -129,18 +144,30 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() { } ) - inner class EuiccInfoViewHolder(root: View) : ViewHolder(root) { + inner class EuiccInfoViewHolder(private val root: View) : ViewHolder(root), View.OnClickListener { private val title: TextView = root.requireViewById(R.id.euicc_info_title) private val content: TextView = root.requireViewById(R.id.euicc_info_content) + private var copiedToastResId: Int? = null - fun bind(item: Pair) { - title.text = item.first - content.text = item.second + fun bind(item: Item) { + copiedToastResId = item.copiedToastResId + root.setOnClickListener(if (copiedToastResId != null) this else null) + title.setText(item.titleResId) + content.text = item.content ?: getString(R.string.unknown) + } + + override fun onClick(view: View) { + val label = title.text.toString() + root.context.getSystemService(ClipboardManager::class.java)!! + .setPrimaryClip(ClipData.newPlainText(label, content.text)) + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) Toast + .makeText(root.context, copiedToastResId!!, Toast.LENGTH_SHORT) + .show() } } inner class EuiccInfoAdapter : RecyclerView.Adapter() { - var euiccInfoItems: List> = listOf() + var euiccInfoItems: List = listOf() @SuppressLint("NotifyDataSetChanged") set(newVal) { field = newVal diff --git a/app-common/src/main/res/values/strings.xml b/app-common/src/main/res/values/strings.xml index 61823f7..f0501bf 100644 --- a/app-common/src/main/res/values/strings.xml +++ b/app-common/src/main/res/values/strings.xml @@ -31,6 +31,7 @@ Nickname cannot be longer than 64 characters Confirmation string mismatch ICCID copied to clipboard + EID copied to clipboard Select Slot Select