浏览代码

ui: Copyable eid string

peter: redid parts of EuiccInfoViewHolder to remove the need for root
context (we can get it from activity directly).

Co-Authored-By: septs <github@septs.pw>

commit 2a6eb746bff034ed6032b8eac7462963bb39bcf1
Author: septs <github@septs.pw>
Date:   Sat Dec 14 11:26:42 2024 +0800

    feat: hide copied toast in android 13 or higher

commit d5bfd090b7b2e2c74c2cef698a43fc3607db260c
Merge: 0b2a498 aed2479
Author: septs <github@septs.pw>
Date:   Sat Dec 14 03:58:59 2024 +0800

    Merge branch 'master' into copyable-eid-string

commit 0b2a4988f2a2c2c7131a06867fc6bf622b281828
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:35:27 2024 +0800

    refactor: eid copied toast

commit ce854575aae304de68bddc0490998af5729632ab
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:27:18 2024 +0800

    revert: EuiccManagementFragment

commit 41229cac5727001ecb21992f5005b5b96b1d9557
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:27:10 2024 +0800

    revert: EuiccManagementFragment

commit 1f2b2d73ddfdc690442c0167e7f2f1748a78c921
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:25:01 2024 +0800

    feat: add euiccinfo activity specific strings

commit ca76ac841eab489ff1f825fef2f2aecd1ae88bb1
Merge: 110d490 55d96c6
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:23:34 2024 +0800

    Merge branch 'master' into copyable-eid-string

commit 110d49005a0cba26ee72eedfda0fc9e38a501d2a
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:23:21 2024 +0800

    revert: common strings

commit dc12e8d4107b9c80a1ca2bee0c5897f3e7d8dfa4
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:22:47 2024 +0800

    revert: unpriv strings

commit ccba9be141c533145464da3dbbc88afa16fac1fd
Merge: 34c5e41 0687354
Author: septs <github@septs.pw>
Date:   Fri Dec 13 12:15:42 2024 +0800

    Merge branch 'master' of ssh://gitea-ssh.angry.im:2222/PeterCxy/OpenEUICC into copyable-eid-string

commit 34c5e41dde663026b72b2c80301bfde2d14c0964
Author: septs <github@septs.pw>
Date:   Thu Dec 12 11:45:59 2024 +0800

    chore: simplify clickable

commit 4f1ed329f12b590691d273ac2150cb81ded11521
Author: septs <github@septs.pw>
Date:   Thu Dec 12 11:37:15 2024 +0800

    feat: copyable eid string
Peter Cai 1 年之前
父节点
当前提交
55c99831f3

+ 57 - 23
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<RecyclerView>(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)))
         }
     }
 
@@ -132,15 +147,34 @@ class EuiccInfoActivity : BaseEuiccAccessActivity() {
     inner class EuiccInfoViewHolder(root: View) : ViewHolder(root) {
         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
+
+        init {
+            root.setOnClickListener {
+                if (copiedToastResId != null) {
+                    val label = title.text.toString()
+                    getSystemService(ClipboardManager::class.java)!!
+                        .setPrimaryClip(ClipData.newPlainText(label, content.text))
+                    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2) {
+                        Toast.makeText(
+                            this@EuiccInfoActivity,
+                            copiedToastResId!!,
+                            Toast.LENGTH_SHORT
+                        ).show()
+                    }
+                }
+            }
+        }
 
-        fun bind(item: Pair<String, String>) {
-            title.text = item.first
-            content.text = item.second
+        fun bind(item: Item) {
+            copiedToastResId = item.copiedToastResId
+            title.setText(item.titleResId)
+            content.text = item.content ?: getString(R.string.unknown)
         }
     }
 
     inner class EuiccInfoAdapter : RecyclerView.Adapter<EuiccInfoViewHolder>() {
-        var euiccInfoItems: List<Pair<String, String>> = listOf()
+        var euiccInfoItems: List<Item> = listOf()
             @SuppressLint("NotifyDataSetChanged")
             set(newVal) {
                 field = newVal

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

@@ -31,6 +31,7 @@
     <string name="toast_profile_name_too_long">Nickname cannot be longer than 64 characters</string>
     <string name="toast_profile_delete_confirm_text_mismatched">Confirmation string mismatch</string>
     <string name="toast_iccid_copied">ICCID copied to clipboard</string>
+    <string name="toast_eid_copied">EID copied to clipboard</string>
 
     <string name="slot_select">Select Slot</string>
     <string name="slot_select_select">Select</string>