EuiccManagementFragment.kt 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package im.angry.openeuicc.ui
  2. import android.annotation.SuppressLint
  3. import android.os.Bundle
  4. import android.text.method.PasswordTransformationMethod
  5. import android.view.LayoutInflater
  6. import android.view.View
  7. import android.view.ViewGroup
  8. import androidx.fragment.app.Fragment
  9. import androidx.lifecycle.lifecycleScope
  10. import androidx.recyclerview.widget.LinearLayoutManager
  11. import androidx.recyclerview.widget.RecyclerView
  12. import im.angry.openeuicc.R
  13. import im.angry.openeuicc.core.EuiccChannel
  14. import im.angry.openeuicc.databinding.EuiccProfileBinding
  15. import im.angry.openeuicc.databinding.FragmentEuiccBinding
  16. import kotlinx.coroutines.Dispatchers
  17. import kotlinx.coroutines.launch
  18. import kotlinx.coroutines.withContext
  19. class EuiccManagementFragment(private val channel: EuiccChannel) : Fragment() {
  20. private var _binding: FragmentEuiccBinding? = null
  21. private val binding get() = _binding!!
  22. private val adapter = EuiccProfileAdapter(listOf())
  23. override fun onCreateView(
  24. inflater: LayoutInflater,
  25. container: ViewGroup?,
  26. savedInstanceState: Bundle?
  27. ): View {
  28. _binding = FragmentEuiccBinding.inflate(inflater, container, false)
  29. return binding.root
  30. }
  31. override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  32. super.onViewCreated(view, savedInstanceState)
  33. binding.swipeRefresh.setOnRefreshListener { refresh() }
  34. binding.profileList.adapter = adapter
  35. binding.profileList.layoutManager =
  36. LinearLayoutManager(view.context, LinearLayoutManager.VERTICAL, false)
  37. binding.fab.setOnClickListener {
  38. ProfileDownloadFragment(channel).show(childFragmentManager, ProfileDownloadFragment.TAG)
  39. }
  40. }
  41. override fun onStart() {
  42. super.onStart()
  43. refresh()
  44. }
  45. @SuppressLint("NotifyDataSetChanged")
  46. private fun refresh() {
  47. binding.swipeRefresh.isRefreshing = true
  48. lifecycleScope.launch {
  49. val profiles = withContext(Dispatchers.IO) {
  50. channel.lpa.profiles
  51. }
  52. withContext(Dispatchers.Main) {
  53. adapter.profiles = profiles
  54. adapter.notifyDataSetChanged()
  55. binding.swipeRefresh.isRefreshing = false
  56. }
  57. }
  58. }
  59. }
  60. class EuiccProfileAdapter(var profiles: List<Map<String, String>>) :
  61. RecyclerView.Adapter<EuiccProfileAdapter.ViewHolder>() {
  62. data class ViewHolder(val binding: EuiccProfileBinding) : RecyclerView.ViewHolder(binding.root) {
  63. init {
  64. binding.iccid.setOnClickListener {
  65. if (binding.iccid.transformationMethod == null) {
  66. binding.iccid.transformationMethod = PasswordTransformationMethod.getInstance()
  67. } else {
  68. binding.iccid.transformationMethod = null
  69. }
  70. }
  71. }
  72. }
  73. override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
  74. val binding =
  75. EuiccProfileBinding.inflate(LayoutInflater.from(parent.context), parent, false)
  76. return ViewHolder(binding)
  77. }
  78. override fun onBindViewHolder(holder: ViewHolder, position: Int) {
  79. // TODO: The library is not exposing the nicknames. Expose them so that we can do something here.
  80. holder.binding.name.text = profiles[position]["NAME"]
  81. holder.binding.state.setText(
  82. if (profiles[position]["STATE"]?.lowercase() == "enabled") {
  83. R.string.enabled
  84. } else {
  85. R.string.disabled
  86. }
  87. )
  88. holder.binding.provider.text = profiles[position]["PROVIDER_NAME"]
  89. holder.binding.iccid.text = profiles[position]["ICCID"]
  90. holder.binding.iccid.transformationMethod = PasswordTransformationMethod.getInstance()
  91. }
  92. override fun getItemCount(): Int = profiles.size
  93. }