Browse Source

ui: Add option to skip safeguard for removable eSIMs

Peter Cai 1 year ago
parent
commit
b16a72f43a

+ 13 - 2
app-common/src/main/java/im/angry/openeuicc/ui/EuiccManagementFragment.kt

@@ -29,7 +29,9 @@ import im.angry.openeuicc.core.EuiccChannelManager
 import im.angry.openeuicc.util.*
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
@@ -52,6 +54,10 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
     // e.g. after a failed enable / disable operation
     private var invalid = false
 
+    // Subscribe to settings we care about outside of coroutine contexts while initializing
+    // This gives us access to the "latest" state without having to launch coroutines
+    private lateinit var disableSafeguardFlow: StateFlow<Boolean>
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setHasOptionsMenu(true)
@@ -115,6 +121,11 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
         swipeRefresh.isRefreshing = true
 
         lifecycleScope.launch {
+            if (!this@EuiccManagementFragment::disableSafeguardFlow.isInitialized) {
+                disableSafeguardFlow =
+                    preferenceRepository.disableSafeguardFlow.stateIn(lifecycleScope)
+            }
+
             val profiles = withContext(Dispatchers.IO) {
                 euiccChannelManager.notifyEuiccProfilesChanged(channel.logicalSlotId)
                 channel.lpa.profiles
@@ -219,8 +230,8 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
 
             // We hide the disable option by default to avoid "bricking" some cards that won't get
             // recognized again by the phone's modem. However we don't have that worry if we are
-            // accessing it through a USB card reader
-            if (isUsb) {
+            // accessing it through a USB card reader, or when the user explicitly opted in
+            if (isUsb || disableSafeguardFlow.value) {
                 popup.menu.findItem(R.id.disable).isVisible = true
             }
         }

+ 3 - 0
app-common/src/main/java/im/angry/openeuicc/ui/SettingsFragment.kt

@@ -41,6 +41,9 @@ class SettingsFragment: PreferenceFragmentCompat() {
 
         findPreference<CheckBoxPreference>("pref_notifications_switch")
             ?.bindBooleanFlow(preferenceRepository.notificationSwitchFlow, PreferenceKeys.NOTIFICATION_SWITCH)
+
+        findPreference<CheckBoxPreference>("pref_advanced_disable_safeguard_removable_esim")
+            ?.bindBooleanFlow(preferenceRepository.disableSafeguardFlow, PreferenceKeys.DISABLE_SAFEGUARD_REMOVABLE_ESIM)
     }
 
     private fun CheckBoxPreference.bindBooleanFlow(flow: Flow<Boolean>, key: Preferences.Key<Boolean>) {

+ 5 - 0
app-common/src/main/java/im/angry/openeuicc/util/PreferenceUtils.kt

@@ -23,6 +23,7 @@ object PreferenceKeys {
     val NOTIFICATION_DOWNLOAD = booleanPreferencesKey("notification_download")
     val NOTIFICATION_DELETE = booleanPreferencesKey("notification_delete")
     val NOTIFICATION_SWITCH = booleanPreferencesKey("notification_switch")
+    val DISABLE_SAFEGUARD_REMOVABLE_ESIM = booleanPreferencesKey("disable_safeguard_removable_esim")
 }
 
 class PreferenceRepository(context: Context) {
@@ -39,6 +40,10 @@ class PreferenceRepository(context: Context) {
     val notificationSwitchFlow: Flow<Boolean> =
         dataStore.data.map { it[PreferenceKeys.NOTIFICATION_SWITCH] ?: false }
 
+    // ---- Advanced ----
+    val disableSafeguardFlow: Flow<Boolean> =
+        dataStore.data.map { it[PreferenceKeys.DISABLE_SAFEGUARD_REMOVABLE_ESIM] ?: false }
+
     suspend fun <T> updatePreference(key: Preferences.Key<T>, value: T) {
         dataStore.edit {
             it[key] = value

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

@@ -70,6 +70,8 @@
     <string name="pref_notifications_switch">Switching</string>
     <string name="pref_notifications_switch_desc">Send notifications for <i>switching</i> profiles\nNote that this type of notification is unreliable.</string>
     <string name="pref_advanced">Advanced</string>
+    <string name="pref_advanced_disable_safeguard_removable_esim">Disable Safeguards for Removable eSIMs</string>
+    <string name="pref_advanced_disable_safeguard_removable_esim_desc">By default, this app prevents you from disabling the active profile on a removable eSIM inserted in the device, because doing so may render it inaccessible.\nCheck this box to <i>remove</i> this safeguard.</string>
     <string name="pref_advanced_logs">Logs</string>
     <string name="pref_advanced_logs_desc">View recent debug logs of the application</string>
     <string name="pref_info">Info</string>

+ 6 - 0
app-common/src/main/res/xml/pref_settings.xml

@@ -24,6 +24,12 @@
     <PreferenceCategory
         app:title="@string/pref_advanced"
         app:iconSpaceReserved="false">
+        <CheckBoxPreference
+            app:key="pref_advanced_disable_safeguard_removable_esim"
+            app:iconSpaceReserved="false"
+            app:title="@string/pref_advanced_disable_safeguard_removable_esim"
+            app:summary="@string/pref_advanced_disable_safeguard_removable_esim_desc" />
+
         <Preference
             app:key="pref_advanced_logs"
             app:iconSpaceReserved="false"