Fix app crash if Bluetooth adapter is null and we can't retrieve the list of bonded devices in settings.

This commit is contained in:
darken
2022-09-24 15:49:56 +02:00
parent b488a1be16
commit cf72e28727
11 changed files with 71 additions and 44 deletions
@@ -10,9 +10,7 @@ import androidx.annotation.MenuRes
import androidx.annotation.XmlRes
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.preference.PreferenceFragmentCompat
import androidx.viewbinding.ViewBinding
import eu.darken.capod.common.preferences.Settings
import eu.darken.capod.main.ui.settings.SettingsFragment
@@ -69,17 +67,4 @@ abstract class PreferenceFragment2
}
}
}
inline fun <T> LiveData<T>.observe2(
crossinline callback: (T) -> Unit
) {
observe(viewLifecycleOwner) { callback.invoke(it) }
}
inline fun <T, reified VB : ViewBinding?> LiveData<T>.observe2(
ui: VB,
crossinline callback: VB.(T) -> Unit
) {
observe(viewLifecycleOwner) { callback.invoke(ui, it) }
}
}
@@ -0,0 +1,35 @@
package eu.darken.capod.common.uix
import android.os.Bundle
import android.view.View
import androidx.lifecycle.LiveData
import androidx.viewbinding.ViewBinding
import eu.darken.capod.common.error.asErrorDialogBuilder
abstract class PreferenceFragment3 : PreferenceFragment2() {
abstract val vm: ViewModel3
var onErrorEvent: ((Throwable) -> Boolean)? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
vm.errorEvents.observe2 {
val showDialog = onErrorEvent?.invoke(it) ?: true
if (showDialog) it.asErrorDialogBuilder(requireContext()).show()
}
}
inline fun <T> LiveData<T>.observe2(
crossinline callback: (T) -> Unit
) {
observe(viewLifecycleOwner) { callback.invoke(it) }
}
inline fun <T, reified VB : ViewBinding?> LiveData<T>.observe2(
ui: VB,
crossinline callback: VB.(T) -> Unit
) {
observe(viewLifecycleOwner) { callback.invoke(ui, it) }
}
}
@@ -10,7 +10,7 @@ import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.R
import eu.darken.capod.common.bluetooth.ScannerMode
import eu.darken.capod.common.preferences.PercentSliderPreference
import eu.darken.capod.common.uix.PreferenceFragment2
import eu.darken.capod.common.uix.PreferenceFragment3
import eu.darken.capod.common.upgrade.UpgradeRepo
import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.main.core.MonitorMode
@@ -19,9 +19,9 @@ import javax.inject.Inject
@Keep
@AndroidEntryPoint
class GeneralSettingsFragment : PreferenceFragment2() {
class GeneralSettingsFragment : PreferenceFragment3() {
private val vm: GeneralSettingsFragmentVM by viewModels()
override val vm: GeneralSettingsFragmentVM by viewModels()
@Inject lateinit var generalSettings: GeneralSettings
@Inject lateinit var upgradeRepo: UpgradeRepo
@@ -6,7 +6,7 @@ import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.coroutine.DispatcherProvider
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.uix.ViewModel3
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
@HiltViewModel
@@ -16,9 +16,9 @@ class GeneralSettingsFragmentVM @Inject constructor(
private val bluetoothManager: BluetoothManager2,
) : ViewModel3(dispatcherProvider) {
val bondedDevices = flow {
emit(bluetoothManager.bondedDevices().toList())
}.asLiveData2()
val bondedDevices = bluetoothManager.bondedDevices()
.map { it.toList() }
.asLiveData2()
companion object {
private val TAG = logTag("Settings", "General", "VM")
@@ -9,14 +9,14 @@ import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.R
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.observe2
import eu.darken.capod.common.uix.PreferenceFragment2
import eu.darken.capod.common.uix.PreferenceFragment3
import javax.inject.Inject
@Keep
@AndroidEntryPoint
class DebugSettingsFragment : PreferenceFragment2() {
class DebugSettingsFragment : PreferenceFragment3() {
private val vm: DebugSettingsFragmentVM by viewModels()
override val vm: DebugSettingsFragmentVM by viewModels()
@Inject lateinit var debugSettings: DebugSettings
@@ -10,15 +10,15 @@ import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.R
import eu.darken.capod.common.ClipboardHelper
import eu.darken.capod.common.observe2
import eu.darken.capod.common.uix.PreferenceFragment2
import eu.darken.capod.common.uix.PreferenceFragment3
import eu.darken.capod.main.core.GeneralSettings
import javax.inject.Inject
@Keep
@AndroidEntryPoint
class SupportFragment : PreferenceFragment2() {
class SupportFragment : PreferenceFragment3() {
private val vm: SupportFragmentVM by viewModels()
override val vm: SupportFragmentVM by viewModels()
override val preferenceFile: Int = R.xml.preferences_support
@Inject lateinit var generalSettings: GeneralSettings
@@ -1,5 +1,6 @@
package eu.darken.capod.reaction.ui
import android.bluetooth.BluetoothDevice
import android.os.Bundle
import android.view.View
import androidx.annotation.Keep
@@ -10,7 +11,7 @@ import androidx.preference.ListPreference
import androidx.preference.Preference
import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.R
import eu.darken.capod.common.uix.PreferenceFragment2
import eu.darken.capod.common.uix.PreferenceFragment3
import eu.darken.capod.common.upgrade.UpgradeRepo
import eu.darken.capod.main.core.GeneralSettings
import eu.darken.capod.main.core.MonitorMode
@@ -21,9 +22,9 @@ import javax.inject.Inject
@Keep
@AndroidEntryPoint
class ReactionSettingsFragment : PreferenceFragment2() {
class ReactionSettingsFragment : PreferenceFragment3() {
private val vm: ReactionSettingsFragmentVM by viewModels()
override val vm: ReactionSettingsFragmentVM by viewModels()
@Inject lateinit var generalSettings: GeneralSettings
@Inject lateinit var reactionSettings: ReactionSettings
@@ -35,6 +36,7 @@ class ReactionSettingsFragment : PreferenceFragment2() {
override val preferenceFile: Int = R.xml.preferences_reactions
private var isPro: Boolean = false
private var bondedDevices: List<BluetoothDevice> = emptyList()
private val autoConnectConditionPref by lazy { findPreference<ListPreference>(settings.autoConnectCondition.key)!! }
override fun onPreferencesCreated() {
@@ -66,10 +68,9 @@ class ReactionSettingsFragment : PreferenceFragment2() {
preference.isChecked = false
return true
} else if (generalSettings.mainDeviceAddress.value == null) {
val devices = vm.bondedDevices
DeviceSelectionDialogFactory(requireContext()).create(
devices = devices,
current = devices.firstOrNull { it.address == generalSettings.mainDeviceAddress.value }
devices = bondedDevices,
current = bondedDevices.firstOrNull { it.address == generalSettings.mainDeviceAddress.value }
) { selected ->
generalSettings.mainDeviceAddress.value = selected?.address
if (selected != null) preference.isChecked = true
@@ -95,6 +96,8 @@ class ReactionSettingsFragment : PreferenceFragment2() {
vm.isPro.observe2 { isPro = it }
vm.bondedDevices.observe2 { bondedDevices = it }
super.onViewCreated(view, savedInstanceState)
}
@@ -18,10 +18,12 @@ class ReactionSettingsFragmentVM @Inject constructor(
private val upgradeRepo: UpgradeRepo,
) : ViewModel3(dispatcherProvider) {
val bondedDevices = bluetoothManager.bondedDevices().toList()
val isPro = upgradeRepo.upgradeInfo.map { it.isPro }.asLiveData2()
val bondedDevices = bluetoothManager.bondedDevices()
.map { it.toList() }
.asLiveData2()
companion object {
private val TAG = logTag("Settings", "Reaction", "VM")
}