refactor: consolidate QR code scanning methods

This commit is contained in:
andrekir 2024-11-20 18:40:24 -03:00 committed by Andre K
parent 75003bb6f0
commit f73d909cd0
44 changed files with 89 additions and 226 deletions

View file

@ -11,9 +11,9 @@ import com.journeyapps.barcodescanner.BarcodeEncoder
import java.net.MalformedURLException
import kotlin.jvm.Throws
internal const val URL_PREFIX = "https://meshtastic.org/e/#"
private const val MESHTASTIC_DOMAIN = "meshtastic.org"
private const val MESHTASTIC_CHANNEL_CONFIG_PATH = "/e/"
private const val MESHTASTIC_HOST = "meshtastic.org"
private const val MESHTASTIC_PATH = "/e/"
internal const val URL_PREFIX = "https://$MESHTASTIC_HOST$MESHTASTIC_PATH#"
private const val BASE64FLAGS = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PADDING
/**
@ -23,37 +23,21 @@ private const val BASE64FLAGS = Base64.URL_SAFE + Base64.NO_WRAP + Base64.NO_PAD
@Throws(MalformedURLException::class)
fun Uri.toChannelSet(): ChannelSet {
if (fragment.isNullOrBlank() ||
!host.equals(MESHTASTIC_DOMAIN, true) ||
!path.equals(MESHTASTIC_CHANNEL_CONFIG_PATH, true)
!host.equals(MESHTASTIC_HOST, true) ||
!path.equals(MESHTASTIC_PATH, true)
) {
throw MalformedURLException("Not a valid Meshtastic URL: ${toString().take(40)}")
}
// Older versions of Meshtastic clients (Apple/web) included `?add=true` within the URL fragment.
// This gracefully handles those cases until the newer version are generally available/used.
return ChannelSet.parseFrom(Base64.decode(fragment!!.substringBefore('?'), BASE64FLAGS))
}
/**
* Return a [Boolean] if the URL indicates the associated [ChannelSet] should be added to the
* existing configuration.
* @throws MalformedURLException when not recognized as a valid Meshtastic URL
*/
@Throws(MalformedURLException::class)
fun Uri.shouldAddChannels(): Boolean {
if (fragment.isNullOrBlank() ||
!host.equals(MESHTASTIC_DOMAIN, true) ||
!path.equals(MESHTASTIC_CHANNEL_CONFIG_PATH, true)
) {
throw MalformedURLException("Not a valid Meshtastic URL: ${toString().take(40)}")
}
// Older versions of Meshtastic clients (Apple/web) included `?add=true` within the URL fragment.
// This gracefully handles those cases until the newer version are generally available/used.
return fragment?.substringAfter('?', "")
val url = ChannelSet.parseFrom(Base64.decode(fragment!!.substringBefore('?'), BASE64FLAGS))
val shouldAdd = fragment?.substringAfter('?', "")
?.takeUnless { it.isBlank() }
?.equals("add=true")
?: getBooleanQueryParameter("add", false)
return url.toBuilder().apply { if (shouldAdd) clearLoraConfig() }.build()
}
/**

View file

@ -451,18 +451,18 @@ class UIViewModel @Inject constructor(
val connectionState get() = radioConfigRepository.connectionState
fun isConnected() = connectionState.value != MeshService.ConnectionState.DISCONNECTED
private val _requestChannelUrl = MutableLiveData<Uri?>(null)
val requestChannelUrl: LiveData<Uri?> get() = _requestChannelUrl
private val _requestChannelSet = MutableStateFlow<AppOnlyProtos.ChannelSet?>(null)
val requestChannelSet: StateFlow<AppOnlyProtos.ChannelSet?> get() = _requestChannelSet
fun setRequestChannelUrl(channelUrl: Uri) {
_requestChannelUrl.value = channelUrl
fun requestChannelSet(channelSet: AppOnlyProtos.ChannelSet) {
_requestChannelSet.value = channelSet
}
/**
* Called immediately after activity observes requestChannelUrl
*/
fun clearRequestChannelUrl() {
_requestChannelUrl.value = null
_requestChannelSet.value = null
}
fun showSnackbar(resString: Any) {
@ -538,24 +538,14 @@ class UIViewModel @Inject constructor(
}
/**
* Set the radio config (also updates our saved copy in preferences). By default, this will replace
* all channels in the existing radio config. Otherwise, it will append all [ChannelSettings] that
* are unique in [channelSet] to the existing radio config.
* Set the radio config (also updates our saved copy in preferences).
*/
fun setChannels(channelSet: AppOnlyProtos.ChannelSet, overwrite: Boolean = true) = viewModelScope.launch {
val newRadioSettings: List<ChannelSettings> = if (overwrite) {
channelSet.settingsList
} else {
// To guarantee consistent ordering, using a LinkedHashSet which iterates through it's
// entries according to the order an item was *first* inserted.
// https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-linked-hash-set/
LinkedHashSet(channels.value.settingsList + channelSet.settingsList).toList()
}
fun setChannels(channelSet: AppOnlyProtos.ChannelSet) = viewModelScope.launch {
getChannelList(channelSet.settingsList, channels.value.settingsList).forEach(::setChannel)
radioConfigRepository.replaceAllSettings(channelSet.settingsList)
getChannelList(newRadioSettings, channels.value.settingsList).forEach(::setChannel)
radioConfigRepository.replaceAllSettings(newRadioSettings)
val newConfig = config { lora = channelSet.loraConfig }
if (overwrite && config.lora != newConfig.lora) setConfig(newConfig)
if (config.lora != newConfig.lora) setConfig(newConfig)
}
val provideLocation = object : MutableLiveData<Boolean>(preferences.getBoolean("provide-location", false)) {