Compare commits
3 commits
4fb59a4b01
...
c4b513fc0a
Author | SHA1 | Date | |
---|---|---|---|
c4b513fc0a | |||
6458f54db2 | |||
87f36f4166 |
6 changed files with 81 additions and 16 deletions
|
@ -109,7 +109,10 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
|
||||||
fab.setOnClickListener {
|
fab.setOnClickListener {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
if (preferenceRepository.experimentalDownloadWizardFlow.first()) {
|
if (preferenceRepository.experimentalDownloadWizardFlow.first()) {
|
||||||
startActivity(Intent(requireContext(), DownloadWizardActivity::class.java))
|
Intent(requireContext(), DownloadWizardActivity::class.java).apply {
|
||||||
|
putExtra("selectedLogicalSlot", logicalSlotId)
|
||||||
|
startActivity(this)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ProfileDownloadFragment.newInstance(slotId, portId)
|
ProfileDownloadFragment.newInstance(slotId, portId)
|
||||||
.show(childFragmentManager, ProfileDownloadFragment.TAG)
|
.show(childFragmentManager, ProfileDownloadFragment.TAG)
|
||||||
|
|
|
@ -15,6 +15,12 @@ import im.angry.openeuicc.ui.BaseEuiccAccessActivity
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
|
|
||||||
class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
|
data class DownloadWizardState(
|
||||||
|
var selectedLogicalSlot: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
private lateinit var state: DownloadWizardState
|
||||||
|
|
||||||
private lateinit var progressBar: ProgressBar
|
private lateinit var progressBar: ProgressBar
|
||||||
private lateinit var nextButton: Button
|
private lateinit var nextButton: Button
|
||||||
private lateinit var prevButton: Button
|
private lateinit var prevButton: Button
|
||||||
|
@ -31,6 +37,10 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
state = DownloadWizardState(
|
||||||
|
intent.getIntExtra("selectedLogicalSlot", 0)
|
||||||
|
)
|
||||||
|
|
||||||
progressBar = requireViewById(R.id.progress)
|
progressBar = requireViewById(R.id.progress)
|
||||||
nextButton = requireViewById(R.id.download_wizard_next)
|
nextButton = requireViewById(R.id.download_wizard_next)
|
||||||
prevButton = requireViewById(R.id.download_wizard_back)
|
prevButton = requireViewById(R.id.download_wizard_back)
|
||||||
|
@ -89,10 +99,13 @@ class DownloadWizardActivity: BaseEuiccAccessActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class DownloadWizardStepFragment : Fragment(), OpenEuiccContextMarker {
|
abstract class DownloadWizardStepFragment : Fragment(), OpenEuiccContextMarker {
|
||||||
|
protected val state: DownloadWizardState
|
||||||
|
get() = (requireActivity() as DownloadWizardActivity).state
|
||||||
|
|
||||||
abstract val hasNext: Boolean
|
abstract val hasNext: Boolean
|
||||||
abstract val hasPrev: Boolean
|
abstract val hasPrev: Boolean
|
||||||
abstract fun createNextFragment(): DownloadWizardStepFragment
|
abstract fun createNextFragment(): DownloadWizardStepFragment?
|
||||||
abstract fun createPrevFragment(): DownloadWizardStepFragment
|
abstract fun createPrevFragment(): DownloadWizardStepFragment?
|
||||||
|
|
||||||
protected fun hideProgressBar() {
|
protected fun hideProgressBar() {
|
||||||
(requireActivity() as DownloadWizardActivity).progressBar.visibility = View.GONE
|
(requireActivity() as DownloadWizardActivity).progressBar.visibility = View.GONE
|
||||||
|
|
|
@ -22,6 +22,9 @@ import net.typeblog.lpac_jni.LocalProfileInfo
|
||||||
class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardStepFragment() {
|
class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardStepFragment() {
|
||||||
private data class SlotInfo(
|
private data class SlotInfo(
|
||||||
val logicalSlotId: Int,
|
val logicalSlotId: Int,
|
||||||
|
val isRemovable: Boolean,
|
||||||
|
val hasMultiplePorts: Boolean,
|
||||||
|
val portId: Int,
|
||||||
val eID: String,
|
val eID: String,
|
||||||
val enabledProfileName: String?
|
val enabledProfileName: String?
|
||||||
)
|
)
|
||||||
|
@ -31,17 +34,15 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
|
||||||
private val adapter = SlotInfoAdapter()
|
private val adapter = SlotInfoAdapter()
|
||||||
|
|
||||||
override val hasNext: Boolean
|
override val hasNext: Boolean
|
||||||
get() = loaded
|
get() = loaded && adapter.slots.isNotEmpty()
|
||||||
override val hasPrev: Boolean
|
override val hasPrev: Boolean
|
||||||
get() = false
|
get() = true
|
||||||
|
|
||||||
override fun createNextFragment(): DownloadWizardActivity.DownloadWizardStepFragment {
|
override fun createNextFragment(): DownloadWizardActivity.DownloadWizardStepFragment? {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createPrevFragment(): DownloadWizardActivity.DownloadWizardStepFragment {
|
override fun createPrevFragment(): DownloadWizardActivity.DownloadWizardStepFragment? = null
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
|
@ -66,25 +67,42 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private suspend fun init() {
|
private suspend fun init() {
|
||||||
|
ensureEuiccChannelManager()
|
||||||
showProgressBar(-1)
|
showProgressBar(-1)
|
||||||
val slots = euiccChannelManager.flowEuiccPorts().map { (slotId, portId) ->
|
val slots = euiccChannelManager.flowEuiccPorts().map { (slotId, portId) ->
|
||||||
euiccChannelManager.withEuiccChannel(slotId, portId) { channel ->
|
euiccChannelManager.withEuiccChannel(slotId, portId) { channel ->
|
||||||
SlotInfo(
|
SlotInfo(
|
||||||
channel.logicalSlotId,
|
channel.logicalSlotId,
|
||||||
|
channel.port.card.isRemovable,
|
||||||
|
channel.port.card.ports.size > 1,
|
||||||
|
channel.portId,
|
||||||
channel.lpa.eID,
|
channel.lpa.eID,
|
||||||
channel.lpa.profiles.find { it.state == LocalProfileInfo.State.Enabled }?.displayName
|
channel.lpa.profiles.find { it.state == LocalProfileInfo.State.Enabled }?.displayName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.toList()
|
}.toList()
|
||||||
adapter.slots = slots
|
adapter.slots = slots
|
||||||
|
|
||||||
|
// Ensure we always have a selected slot by default
|
||||||
|
val selectedIdx = slots.indexOfFirst { it.logicalSlotId == state.selectedLogicalSlot }
|
||||||
|
adapter.currentSelectedIdx = if (selectedIdx > 0) {
|
||||||
|
selectedIdx
|
||||||
|
} else {
|
||||||
|
if (slots.isNotEmpty()) {
|
||||||
|
state.selectedLogicalSlot = slots[0].logicalSlotId
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
adapter.notifyDataSetChanged()
|
adapter.notifyDataSetChanged()
|
||||||
hideProgressBar()
|
hideProgressBar()
|
||||||
loaded = true
|
loaded = true
|
||||||
refreshButtons()
|
refreshButtons()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SlotItemHolder(val adapter: SlotInfoAdapter, val root: View) : ViewHolder(root) {
|
private inner class SlotItemHolder(val root: View) : ViewHolder(root) {
|
||||||
private val title = root.requireViewById<TextView>(R.id.slot_item_title)
|
private val title = root.requireViewById<TextView>(R.id.slot_item_title)
|
||||||
|
private val type = root.requireViewById<TextView>(R.id.slot_item_type)
|
||||||
private val eID = root.requireViewById<TextView>(R.id.slot_item_eid)
|
private val eID = root.requireViewById<TextView>(R.id.slot_item_eid)
|
||||||
private val activeProfile = root.requireViewById<TextView>(R.id.slot_item_active_profile)
|
private val activeProfile = root.requireViewById<TextView>(R.id.slot_item_active_profile)
|
||||||
private val checkBox = root.requireViewById<CheckBox>(R.id.slot_checkbox)
|
private val checkBox = root.requireViewById<CheckBox>(R.id.slot_checkbox)
|
||||||
|
@ -104,10 +122,24 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
|
||||||
adapter.currentSelectedIdx = curIdx
|
adapter.currentSelectedIdx = curIdx
|
||||||
adapter.notifyItemChanged(lastIdx)
|
adapter.notifyItemChanged(lastIdx)
|
||||||
adapter.notifyItemChanged(curIdx)
|
adapter.notifyItemChanged(curIdx)
|
||||||
|
// Selected index isn't logical slot ID directly, needs a conversion
|
||||||
|
state.selectedLogicalSlot = adapter.slots[adapter.currentSelectedIdx].logicalSlotId
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bind(item: SlotInfo, idx: Int) {
|
fun bind(item: SlotInfo, idx: Int) {
|
||||||
curIdx = idx
|
curIdx = idx
|
||||||
|
|
||||||
|
type.text = if (item.isRemovable) {
|
||||||
|
root.context.getString(R.string.download_wizard_slot_type_removable)
|
||||||
|
} else if (!item.hasMultiplePorts) {
|
||||||
|
root.context.getString(R.string.download_wizard_slot_type_internal)
|
||||||
|
} else {
|
||||||
|
root.context.getString(
|
||||||
|
R.string.download_wizard_slot_type_internal_port,
|
||||||
|
item.portId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
title.text = root.context.getString(R.string.download_wizard_slot_title, item.logicalSlotId)
|
title.text = root.context.getString(R.string.download_wizard_slot_title, item.logicalSlotId)
|
||||||
eID.text = item.eID
|
eID.text = item.eID
|
||||||
activeProfile.text = item.enabledProfileName ?: root.context.getString(R.string.unknown)
|
activeProfile.text = item.enabledProfileName ?: root.context.getString(R.string.unknown)
|
||||||
|
@ -115,13 +147,13 @@ class DownloadWizardSlotSelectFragment : DownloadWizardActivity.DownloadWizardSt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SlotInfoAdapter : RecyclerView.Adapter<SlotItemHolder>() {
|
private inner class SlotInfoAdapter : RecyclerView.Adapter<SlotItemHolder>() {
|
||||||
var slots: List<SlotInfo> = listOf()
|
var slots: List<SlotInfo> = listOf()
|
||||||
var currentSelectedIdx = 0
|
var currentSelectedIdx = -1
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SlotItemHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SlotItemHolder {
|
||||||
val root = LayoutInflater.from(parent.context).inflate(R.layout.download_slot_item, parent, false)
|
val root = LayoutInflater.from(parent.context).inflate(R.layout.download_slot_item, parent, false)
|
||||||
return SlotItemHolder(this, root)
|
return SlotItemHolder(root)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = slots.size
|
override fun getItemCount(): Int = slots.size
|
||||||
|
|
|
@ -19,6 +19,20 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/slot_item_type_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minWidth="100dp"
|
||||||
|
android:text="@string/download_wizard_slot_type"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/slot_item_type"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/slot_item_eid_label"
|
android:id="@+id/slot_item_eid_label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -54,7 +68,7 @@
|
||||||
android:layout_marginStart="10sp"
|
android:layout_marginStart="10sp"
|
||||||
android:layout_marginTop="20sp"
|
android:layout_marginTop="20sp"
|
||||||
android:layout_marginEnd="10sp"
|
android:layout_marginEnd="10sp"
|
||||||
app:constraint_referenced_ids="slot_item_eid_label,slot_item_eid,slot_item_active_profile_label,slot_item_active_profile"
|
app:constraint_referenced_ids="slot_item_type_label,slot_item_type,slot_item_eid_label,slot_item_eid,slot_item_active_profile_label,slot_item_active_profile"
|
||||||
app:flow_wrapMode="aligned"
|
app:flow_wrapMode="aligned"
|
||||||
app:flow_horizontalAlign="start"
|
app:flow_horizontalAlign="start"
|
||||||
app:flow_horizontalBias="1"
|
app:flow_horizontalBias="1"
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constrainedHeight="true"
|
app:layout_constrainedHeight="true" />
|
||||||
app:layout_constraintHeight_max="300dp" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -63,6 +63,10 @@
|
||||||
<string name="download_wizard_next">Next</string>
|
<string name="download_wizard_next">Next</string>
|
||||||
<string name="download_wizard_slot_select">Confirm the eSIM slot:</string>
|
<string name="download_wizard_slot_select">Confirm the eSIM slot:</string>
|
||||||
<string name="download_wizard_slot_title">Logical slot %d</string>
|
<string name="download_wizard_slot_title">Logical slot %d</string>
|
||||||
|
<string name="download_wizard_slot_type">Type:</string>
|
||||||
|
<string name="download_wizard_slot_type_removable">Removable</string>
|
||||||
|
<string name="download_wizard_slot_type_internal">Internal</string>
|
||||||
|
<string name="download_wizard_slot_type_internal_port">Internal, port %d</string>
|
||||||
<string name="download_wizard_slot_eid">eID:</string>
|
<string name="download_wizard_slot_eid">eID:</string>
|
||||||
<string name="download_wizard_slot_active_profile">Active Profile:</string>
|
<string name="download_wizard_slot_active_profile">Active Profile:</string>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue