Compare commits

..

No commits in common. "63ee8be79bb43950105368d2d3d2e1537f4f8953" and "4c221f74ff30414f347c97c64f95fe2f47f2ad99" have entirely different histories.

12 changed files with 50 additions and 116 deletions

View file

@ -8,6 +8,30 @@
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app-unpriv.androidTest">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app-unpriv.main">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app-unpriv.unitTest">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app.unitTest">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app.androidTest">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="app.main">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="workspace.OpenEUICC.app-unpriv">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
<SelectionState runConfigName="workspace.OpenEUICC.app">
<option name="selectionMode" value="DROPDOWN" />
</SelectionState>
</selectionStates>
</component>
</project>

View file

@ -17,6 +17,6 @@ open class UnprivilegedUiComponentFactory : DefaultUiComponentFactory() {
override fun createSettingsFragment(): Fragment =
UnprivilegedSettingsFragment()
open fun createQuickCompatibilityFragment(): Fragment =
open fun createQuickAvailabilityFragment(): Fragment =
QuickCompatibilityFragment()
}

View file

@ -1,5 +1,6 @@
package im.angry.openeuicc.ui
import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
@ -13,12 +14,12 @@ class QuickCompatibilityActivity : AppCompatActivity(), OpenEuiccContextMarker {
enableEdgeToEdge()
setContentView(R.layout.activity_quick_compatibility)
val quickCompatibilityFragment =
val quickAvailabilityFragment =
(appContainer.uiComponentFactory as UnprivilegedUiComponentFactory)
.createQuickCompatibilityFragment()
.createQuickAvailabilityFragment()
supportFragmentManager.beginTransaction()
.replace(R.id.quick_compatibility_container, quickCompatibilityFragment)
.replace(R.id.quick_availability_container, quickAvailabilityFragment)
.commit()
}
}

View file

@ -9,7 +9,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CheckBox
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
@ -33,29 +32,20 @@ open class QuickCompatibilityFragment : Fragment(), UnprivilegedEuiccContextMark
data class CompatibilityResult(
val compatibility: Compatibility,
val slotsOmapi: List<String> = emptyList(),
val slotsIsdr: List<String> = emptyList()
val slots: List<String> = emptyList()
)
}
private val conclusion: TextView by lazy {
requireView().requireViewById(R.id.quick_compatibility_conclusion)
requireView().requireViewById(R.id.quick_availability_conclusion)
}
private val resultSlots: TextView by lazy {
requireView().requireViewById(R.id.quick_compatibility_result_slots)
}
private val resultSlotsIsdr: TextView by lazy {
requireView().requireViewById(R.id.quick_compatibility_result_slots_isdr)
requireView().requireViewById(R.id.quick_availability_result_slots)
}
private val resultNotes: TextView by lazy {
requireView().requireViewById(R.id.quick_compatibility_result_notes)
}
private val skipCheckBox: CheckBox by lazy {
requireView().requireViewById(R.id.quick_compatibility_skip)
requireView().requireViewById(R.id.quick_availability_result_notes)
}
override fun onCreateView(
@ -63,19 +53,10 @@ open class QuickCompatibilityFragment : Fragment(), UnprivilegedEuiccContextMark
container: ViewGroup?,
savedInstanceState: Bundle?
): View = inflater.inflate(R.layout.fragment_quick_compatibility, container, false).apply {
requireViewById<TextView>(R.id.quick_compatibility_device_information)
requireViewById<TextView>(R.id.quick_availability_device_information)
.text = formatDeviceInformation()
requireViewById<Button>(R.id.quick_compatibility_button_continue)
requireViewById<Button>(R.id.quick_availability_button_continue)
.setOnClickListener { onContinueToApp() }
// Can't use the lazy field yet
requireViewById<CheckBox>(R.id.quick_compatibility_skip).setOnCheckedChangeListener { compoundButton, b ->
if (compoundButton.isVisible) {
runBlocking {
preferenceRepository.skipQuickCompatibilityFlow
.updatePreference(b)
}
}
}
}
override fun onStart() {
@ -94,31 +75,19 @@ open class QuickCompatibilityFragment : Fragment(), UnprivilegedEuiccContextMark
private fun onCompatibilityUpdate(result: CompatibilityResult) {
conclusion.text = formatConclusion(result)
if (result.compatibility == Compatibility.COMPATIBLE) {
// Don't show the message again, ever, if the result is compatible
runBlocking {
preferenceRepository.skipQuickCompatibilityFlow
preferenceRepository.skipQuickAvailabilityFlow
.updatePreference(true)
}
resultSlots.isVisible = true
resultSlots.text = getString(
R.string.quick_compatibility_result_slots,
ListFormatter.getInstance().format(result.slotsOmapi)
)
resultSlotsIsdr.isVisible = true
resultSlotsIsdr.text =
getString(
R.string.quick_compatibility_result_slots_isdr,
if (result.slotsIsdr.isEmpty()) {
getString(R.string.quick_compatibility_unknown)
} else {
ListFormatter.getInstance().format(result.slotsIsdr)
}
ListFormatter.getInstance().format(result.slots)
)
resultNotes.isVisible = true
} else {
resultNotes.isVisible = true
resultNotes.text = getString(R.string.quick_compatibility_result_notes_incompatible)
skipCheckBox.isVisible = true
}
}
@ -127,9 +96,7 @@ open class QuickCompatibilityFragment : Fragment(), UnprivilegedEuiccContextMark
if (!service.isConnected) {
return CompatibilityResult(Compatibility.NOT_COMPATIBLE)
}
val readers = service.readers.filter(Reader::isSIM)
val omapiSlots = readers.mapNotNull(Reader::slotIndex)
val slots = readers.mapNotNull { reader ->
val slots = service.readers.filter { it.isSIM }.mapNotNull { reader ->
try {
// Note: we ONLY check the default ISD-R AID, because this test is for the _device_,
// NOT the eUICC. We don't care what AID a potential eUICC might use, all we need to
@ -145,15 +112,10 @@ open class QuickCompatibilityFragment : Fragment(), UnprivilegedEuiccContextMark
null
}
}
if (omapiSlots.isEmpty()) {
if (slots.isEmpty()) {
return CompatibilityResult(Compatibility.NOT_COMPATIBLE)
}
val formatChannelName = appContainer.customizableTextProvider::formatInternalChannelName
return CompatibilityResult(
Compatibility.COMPATIBLE,
slotsOmapi = omapiSlots.map(formatChannelName),
slotsIsdr = slots.map(formatChannelName),
)
return CompatibilityResult(Compatibility.COMPATIBLE, slots = slots.map { "SIM$it" })
}
open fun formatConclusion(result: CompatibilityResult): String {

View file

@ -12,7 +12,7 @@ import kotlinx.coroutines.runBlocking
class UnprivilegedMainActivity : MainActivity(), UnprivilegedEuiccContextMarker {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (runBlocking { !preferenceRepository.skipQuickCompatibilityFlow.first() }) {
if (runBlocking { !preferenceRepository.skipQuickAvailabilityFlow.first() }) {
startActivity(Intent(this, QuickCompatibilityActivity::class.java))
}
}

View file

@ -5,10 +5,10 @@ import androidx.datastore.preferences.core.booleanPreferencesKey
internal object UnprivilegedPreferenceKeys {
// ---- Miscellaneous ----
val SKIP_QUICK_COMPATIBILITY = booleanPreferencesKey("skip_quick_compatibility")
val SKIP_QUICK_AVAILABILITY = booleanPreferencesKey("skip_quick_availability")
}
class UnprivilegedPreferenceRepository(context: Context) : PreferenceRepository(context) {
// ---- Miscellaneous ----
val skipQuickCompatibilityFlow = bindFlow(UnprivilegedPreferenceKeys.SKIP_QUICK_COMPATIBILITY, false)
val skipQuickAvailabilityFlow = bindFlow(UnprivilegedPreferenceKeys.SKIP_QUICK_AVAILABILITY, false)
}

View file

@ -5,7 +5,7 @@
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/quick_compatibility_container"
android:id="@+id/quick_availability_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -8,7 +8,7 @@
android:textAlignment="center">
<TextView
android:id="@+id/quick_compatibility_conclusion"
android:id="@+id/quick_availability_conclusion"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
@ -17,7 +17,7 @@
android:textStyle="bold" />
<TextView
android:id="@+id/quick_compatibility_device_information"
android:id="@+id/quick_availability_device_information"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="monospace"
@ -25,38 +25,23 @@
android:textAlignment="center" />
<TextView
android:id="@+id/quick_compatibility_result_slots"
android:id="@+id/quick_availability_result_slots"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:visibility="gone" />
<TextView
android:id="@+id/quick_compatibility_result_slots_isdr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:visibility="gone" />
<TextView
android:id="@+id/quick_compatibility_result_notes"
android:id="@+id/quick_availability_result_notes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/quick_compatibility_result_notes"
android:visibility="gone" />
<CheckBox
android:id="@+id/quick_compatibility_skip"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/quick_compatibility_skip" />
<Button
android:id="@+id/quick_compatibility_button_continue"
android:id="@+id/quick_availability_button_continue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/quick_compatibility_button_continue" />
</LinearLayout>

View file

@ -6,15 +6,4 @@
<!-- Toast -->
<string name="toast_ara_m_copied">ARA-M SHA-1 をクリップボードにコピーしました</string>
<string name="toast_prompt_to_enable_sim_toolkit">「%s」アプリを有効化してください</string>
<string name="quick_compatibility">互換性のチェック</string>
<string name="quick_compatibility_compatible">お使いのスマートフォンは %s 対応 SIM カードを管理できます</string>
<string name="quick_compatibility_not_compatible">お使いのスマートフォンは %s と互換性がありません</string>
<string name="quick_compatibility_not_compatible_but_usb">お使いのスマートフォンは %s と完全な互換性がありません。ただし、USBスマートカードリーダーを使用する場合、ほぼすべての機能を利用できます。</string>
<string name="quick_compatibility_result_slots">アクセス可能なスロット: %s</string>
<string name="quick_compatibility_result_slots_isdr">ISD-R アクセス: %s</string>
<string name="quick_compatibility_result_notes">注: これらの結果は参考用です。以上に記載されていない SIM スロットでも、SIM カードを挿入すれば利用できる可能性があります。</string>
<string name="quick_compatibility_result_notes_incompatible">注:現在 SIM カードが挿入されていない場合は、SIM カードを挿入してから再度互換性チェックをお試しください。どの SIM カードでも構いません。</string>
<string name="quick_compatibility_button_continue">つづく</string>
<string name="quick_compatibility_skip">このメッセージを再度表示しない</string>
<string name="quick_compatibility_unknown">不明</string>
</resources>

View file

@ -2,16 +2,4 @@
<string name="compatibility_check">兼容性检查</string>
<string name="open_sim_toolkit">打开 SIM 卡应用程序</string>
<string name="toast_ara_m_copied">ARA-M SHA-1 已拷贝到剪贴板</string>
<string name="toast_prompt_to_enable_sim_toolkit">请启用您的“%s”应用程序</string>
<string name="quick_compatibility">简易兼容性检测</string>
<string name="quick_compatibility_compatible">您的手机可以管理兼容 %s 的卡片</string>
<string name="quick_compatibility_not_compatible">您的手机与 %s 不兼容</string>
<string name="quick_compatibility_not_compatible_but_usb">您的手机与 %s 不完全兼容,但可以使用 USB 读卡器获得几乎全部功能</string>
<string name="quick_compatibility_result_slots">可读取的卡槽: %s</string>
<string name="quick_compatibility_result_slots_isdr">ISD-R 访问: %s</string>
<string name="quick_compatibility_result_notes">注意:以上结果仅供参考。即使某些卡槽没有被列举出来,插卡后也可能可用。</string>
<string name="quick_compatibility_result_notes_incompatible">注意:如果您目前没有插卡,请插任意 SIM 卡后重试兼容性检测。</string>
<string name="quick_compatibility_button_continue">继续</string>
<string name="quick_compatibility_skip">不再显示此消息</string>
<string name="quick_compatibility_unknown">未知</string>
</resources>

View file

@ -2,16 +2,4 @@
<string name="compatibility_check">相容性檢查</string>
<string name="open_sim_toolkit">啟動 SIM 卡應用程式</string>
<string name="toast_ara_m_copied">ARA-M SHA-1 已複製到剪貼簿</string>
<string name="toast_prompt_to_enable_sim_toolkit">請啟用您的“%s”應用程式</string>
<string name="quick_compatibility">簡易相容性檢測</string>
<string name="quick_compatibility_compatible">您的手機可以管理相容 %s 的卡片</string>
<string name="quick_compatibility_not_compatible">您的手機與 %s 不相容</string>
<string name="quick_compatibility_not_compatible_but_usb">您的手機與 %s 不完全相容,但可以使用 USB 讀卡機獲得幾乎全部功能</string>
<string name="quick_compatibility_result_slots">可讀取的卡槽: %s</string>
<string name="quick_compatibility_result_slots_isdr">ISD-R 訪問: %s</string>
<string name="quick_compatibility_result_notes">注意:以上結果僅供參考。即使某些卡槽沒有被列舉出來,插卡後也可能可用。</string>
<string name="quick_compatibility_result_notes_incompatible">注意:如果您目前沒有插卡,請插任何 SIM 卡後重試相容性檢測。</string>
<string name="quick_compatibility_button_continue">繼續</string>
<string name="quick_compatibility_skip">不再顯示此訊息</string>
<string name="quick_compatibility_unknown">未知</string>
</resources>

View file

@ -16,11 +16,8 @@
<string name="quick_compatibility_compatible">Your smartphone can manage %s-compatible cards</string>
<string name="quick_compatibility_not_compatible">Your smartphone is not compatible with %s</string>
<string name="quick_compatibility_not_compatible_but_usb">Your smartphone is not fully compatible with %s. However, you can still use a USB smart card reader for near-full functionality.</string>
<string name="quick_compatibility_result_slots">Accessible slots: %s</string>
<string name="quick_compatibility_result_slots_isdr">ISD-R access: %s</string>
<string name="quick_compatibility_result_slots">SIM card slots accessible: %s</string>
<string name="quick_compatibility_result_notes">Note: these results are for reference only. Even if a SIM slot is not listed above, it <i>may</i> be compatible as well once a SIM card is inserted.</string>
<string name="quick_compatibility_result_notes_incompatible">Note: if you currently do not have any SIM card inserted, try the compatibility check again after inserting one. Any SIM card will do.</string>
<string name="quick_compatibility_button_continue">Continue</string>
<string name="quick_compatibility_skip">Don\'t show this message again</string>
<string name="quick_compatibility_unknown">Unknown</string>
</resources>