2020-02-17 20:00:11 -08:00
|
|
|
package com.geeksville.mesh.ui
|
|
|
|
|
|
2021-03-31 19:45:31 +08:00
|
|
|
import android.content.ActivityNotFoundException
|
2020-04-08 10:55:28 -07:00
|
|
|
import android.content.Intent
|
2020-04-09 16:33:42 -07:00
|
|
|
import android.graphics.ColorMatrix
|
|
|
|
|
import android.graphics.ColorMatrixColorFilter
|
2021-11-15 10:54:10 -03:00
|
|
|
import android.net.Uri
|
2020-04-07 16:04:58 -07:00
|
|
|
import android.os.Bundle
|
2020-04-15 07:49:39 -07:00
|
|
|
import android.os.RemoteException
|
2020-04-07 16:04:58 -07:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
|
import android.view.View
|
|
|
|
|
import android.view.ViewGroup
|
2020-04-09 16:33:42 -07:00
|
|
|
import android.view.inputmethod.EditorInfo
|
2020-04-07 17:42:31 -07:00
|
|
|
import android.widget.ArrayAdapter
|
2020-04-09 16:33:42 -07:00
|
|
|
import android.widget.ImageView
|
2022-05-17 17:29:21 -03:00
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
2020-04-07 17:42:31 -07:00
|
|
|
import androidx.fragment.app.activityViewModels
|
2022-09-12 19:07:30 -03:00
|
|
|
import androidx.lifecycle.asLiveData
|
2022-09-04 22:52:40 -03:00
|
|
|
import com.geeksville.mesh.analytics.DataPair
|
|
|
|
|
import com.geeksville.mesh.android.GeeksvilleApplication
|
|
|
|
|
import com.geeksville.mesh.android.Logging
|
|
|
|
|
import com.geeksville.mesh.android.hideKeyboard
|
2021-02-27 13:43:55 +08:00
|
|
|
import com.geeksville.mesh.ChannelProtos
|
2022-05-26 16:23:47 -03:00
|
|
|
import com.geeksville.mesh.ConfigProtos
|
2020-02-17 20:00:11 -08:00
|
|
|
import com.geeksville.mesh.R
|
2022-06-01 00:04:31 -03:00
|
|
|
import com.geeksville.mesh.android.getCameraPermissions
|
2021-11-19 01:20:54 -03:00
|
|
|
import com.geeksville.mesh.android.hasCameraPermission
|
2022-09-16 18:17:47 -03:00
|
|
|
import com.geeksville.mesh.channelSet
|
|
|
|
|
import com.geeksville.mesh.copy
|
2020-12-07 20:33:29 +08:00
|
|
|
import com.geeksville.mesh.databinding.ChannelFragmentBinding
|
2020-06-12 20:26:10 -07:00
|
|
|
import com.geeksville.mesh.model.Channel
|
2020-06-14 00:11:08 -04:00
|
|
|
import com.geeksville.mesh.model.ChannelOption
|
2021-02-27 14:31:52 +08:00
|
|
|
import com.geeksville.mesh.model.ChannelSet
|
2020-04-07 17:42:31 -07:00
|
|
|
import com.geeksville.mesh.model.UIViewModel
|
2020-04-09 16:33:42 -07:00
|
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
2020-04-15 07:49:39 -07:00
|
|
|
import com.google.android.material.snackbar.Snackbar
|
2020-06-12 20:26:10 -07:00
|
|
|
import com.google.protobuf.ByteString
|
2022-05-03 17:32:01 -03:00
|
|
|
import com.journeyapps.barcodescanner.ScanContract
|
|
|
|
|
import com.journeyapps.barcodescanner.ScanOptions
|
2022-02-08 13:50:21 -08:00
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
2020-06-12 20:26:10 -07:00
|
|
|
import java.security.SecureRandom
|
2020-04-08 10:55:28 -07:00
|
|
|
|
2020-02-17 20:00:11 -08:00
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
// Make an image view dim
|
|
|
|
|
fun ImageView.setDim() {
|
|
|
|
|
val matrix = ColorMatrix()
|
|
|
|
|
matrix.setSaturation(0f) //0 means grayscale
|
|
|
|
|
val cf = ColorMatrixColorFilter(matrix)
|
|
|
|
|
colorFilter = cf
|
|
|
|
|
imageAlpha = 64 // 128 = 0.5
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Return image view to normal
|
|
|
|
|
fun ImageView.setOpaque() {
|
|
|
|
|
colorFilter = null
|
|
|
|
|
imageAlpha = 255
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-08 13:50:21 -08:00
|
|
|
@AndroidEntryPoint
|
2020-04-07 16:04:58 -07:00
|
|
|
class ChannelFragment : ScreenFragment("Channel"), Logging {
|
|
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
private var _binding: ChannelFragmentBinding? = null
|
2021-03-24 13:48:26 +08:00
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
// This property is only valid between onCreateView and onDestroyView.
|
|
|
|
|
private val binding get() = _binding!!
|
|
|
|
|
|
2020-04-07 17:42:31 -07:00
|
|
|
private val model: UIViewModel by activityViewModels()
|
|
|
|
|
|
2020-04-07 16:04:58 -07:00
|
|
|
override fun onCreateView(
|
|
|
|
|
inflater: LayoutInflater, container: ViewGroup?,
|
|
|
|
|
savedInstanceState: Bundle?
|
2022-05-03 17:32:01 -03:00
|
|
|
): View {
|
2020-12-07 20:33:29 +08:00
|
|
|
_binding = ChannelFragmentBinding.inflate(inflater, container, false)
|
|
|
|
|
return binding.root
|
2020-04-07 17:42:31 -07:00
|
|
|
}
|
2020-04-07 16:04:58 -07:00
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
/// Called when the lock/unlock icon has changed
|
2020-04-08 10:55:28 -07:00
|
|
|
private fun onEditingChanged() {
|
2020-12-07 20:33:29 +08:00
|
|
|
val isEditing = binding.editableCheckbox.isChecked
|
2020-04-08 10:55:28 -07:00
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.channelOptions.isEnabled = isEditing
|
|
|
|
|
binding.shareButton.isEnabled = !isEditing
|
2021-11-17 16:26:12 -03:00
|
|
|
binding.resetButton.isEnabled = isEditing
|
2021-11-15 10:54:10 -03:00
|
|
|
binding.scanButton.isEnabled = isEditing
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.channelNameView.isEnabled = isEditing
|
2020-04-09 16:33:42 -07:00
|
|
|
if (isEditing) // Dim the (stale) QR code while editing...
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.qrView.setDim()
|
2020-04-09 16:33:42 -07:00
|
|
|
else
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.qrView.setOpaque()
|
2020-04-09 16:33:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Pull the latest data from the model (discarding any user edits)
|
|
|
|
|
private fun setGUIfromModel() {
|
2021-02-27 13:43:55 +08:00
|
|
|
val channels = model.channels.value
|
2022-09-12 19:07:30 -03:00
|
|
|
val channel = channels.primaryChannel
|
2022-04-24 12:12:13 -03:00
|
|
|
val connected = model.isConnected()
|
2021-03-24 13:48:26 +08:00
|
|
|
|
|
|
|
|
// Only let buttons work if we are connected to the radio
|
2022-04-24 12:12:13 -03:00
|
|
|
binding.editableCheckbox.isChecked = false // start locked
|
|
|
|
|
onEditingChanged() // we just locked the gui
|
2021-03-24 13:48:26 +08:00
|
|
|
binding.shareButton.isEnabled = connected
|
|
|
|
|
|
2021-03-17 15:37:09 +08:00
|
|
|
if (channel != null) {
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.qrView.visibility = View.VISIBLE
|
|
|
|
|
binding.channelNameEdit.visibility = View.VISIBLE
|
|
|
|
|
binding.channelNameEdit.setText(channel.humanName)
|
2020-04-13 16:00:48 -07:00
|
|
|
|
|
|
|
|
// For now, we only let the user edit/save channels while the radio is awake - because the service
|
2022-05-26 16:23:47 -03:00
|
|
|
// doesn't cache DeviceConfig writes.
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.editableCheckbox.isEnabled = connected
|
2020-04-09 16:33:42 -07:00
|
|
|
|
2021-04-05 15:52:26 +08:00
|
|
|
val bitmap = channels.qrCode
|
|
|
|
|
if (bitmap != null)
|
|
|
|
|
binding.qrView.setImageBitmap(bitmap)
|
2020-09-04 07:59:07 -04:00
|
|
|
|
2022-05-30 17:43:05 -03:00
|
|
|
val modemPreset = channel.loraConfig.modemPreset
|
2022-05-26 16:23:47 -03:00
|
|
|
val channelOption = ChannelOption.fromConfig(modemPreset)
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.filledExposedDropdown.setText(
|
2020-09-08 12:29:28 -07:00
|
|
|
getString(
|
|
|
|
|
channelOption?.configRes ?: R.string.modem_config_unrecognized
|
|
|
|
|
), false
|
|
|
|
|
)
|
2020-09-04 07:59:07 -04:00
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
} else {
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.qrView.visibility = View.INVISIBLE
|
|
|
|
|
binding.channelNameEdit.visibility = View.INVISIBLE
|
|
|
|
|
binding.editableCheckbox.isEnabled = false
|
2020-04-09 16:33:42 -07:00
|
|
|
}
|
|
|
|
|
|
2022-05-26 16:23:47 -03:00
|
|
|
val modemPresets = ChannelOption.values()
|
|
|
|
|
val modemPresetList = modemPresets.map { getString(it.configRes) }
|
2020-04-09 16:33:42 -07:00
|
|
|
val adapter = ArrayAdapter(
|
|
|
|
|
requireContext(),
|
|
|
|
|
R.layout.dropdown_menu_popup_item,
|
2022-05-26 16:23:47 -03:00
|
|
|
modemPresetList
|
2020-04-09 16:33:42 -07:00
|
|
|
)
|
|
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.filledExposedDropdown.setAdapter(adapter)
|
2020-04-09 16:33:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun shareChannel() {
|
2022-09-12 19:07:30 -03:00
|
|
|
model.channels.value.let { channels ->
|
2020-04-09 16:33:42 -07:00
|
|
|
|
|
|
|
|
GeeksvilleApplication.analytics.track(
|
|
|
|
|
"share",
|
|
|
|
|
DataPair("content_type", "channel")
|
|
|
|
|
) // track how many times users share channels
|
|
|
|
|
|
|
|
|
|
val sendIntent: Intent = Intent().apply {
|
|
|
|
|
action = Intent.ACTION_SEND
|
2021-02-27 13:43:55 +08:00
|
|
|
putExtra(Intent.EXTRA_TEXT, channels.getChannelUrl().toString())
|
2020-04-09 16:33:42 -07:00
|
|
|
putExtra(
|
|
|
|
|
Intent.EXTRA_TITLE,
|
|
|
|
|
getString(R.string.url_for_join)
|
|
|
|
|
)
|
|
|
|
|
type = "text/plain"
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-31 19:45:31 +08:00
|
|
|
try {
|
|
|
|
|
val shareIntent = Intent.createChooser(sendIntent, null)
|
|
|
|
|
requireActivity().startActivity(shareIntent)
|
2021-04-05 15:17:39 +08:00
|
|
|
} catch (ex: ActivityNotFoundException) {
|
2021-03-31 19:45:31 +08:00
|
|
|
Snackbar.make(
|
2022-02-07 21:50:31 -03:00
|
|
|
requireView(),
|
2021-03-31 19:45:31 +08:00
|
|
|
R.string.no_app_found,
|
|
|
|
|
Snackbar.LENGTH_SHORT
|
|
|
|
|
).show()
|
|
|
|
|
}
|
2020-04-09 16:33:42 -07:00
|
|
|
}
|
2020-04-08 10:55:28 -07:00
|
|
|
}
|
|
|
|
|
|
2021-03-24 13:48:26 +08:00
|
|
|
/// Send new channel settings to the device
|
2022-05-30 17:43:05 -03:00
|
|
|
private fun installSettings(
|
|
|
|
|
newChannel: ChannelProtos.ChannelSettings,
|
|
|
|
|
newLoRaConfig: ConfigProtos.Config.LoRaConfig
|
|
|
|
|
) {
|
2022-09-16 18:17:47 -03:00
|
|
|
val newSet = ChannelSet(
|
|
|
|
|
channelSet {
|
2022-09-18 20:23:34 -03:00
|
|
|
settings.add(newChannel)
|
2022-09-16 18:17:47 -03:00
|
|
|
loraConfig = newLoRaConfig
|
|
|
|
|
})
|
2022-05-26 16:23:47 -03:00
|
|
|
// Try to change the radio, if it fails, tell the user why and throw away their edits
|
2021-03-24 13:48:26 +08:00
|
|
|
try {
|
|
|
|
|
model.setChannels(newSet)
|
2022-05-26 16:23:47 -03:00
|
|
|
// Since we are writing to DeviceConfig, that will trigger the rest of the GUI update (QR code etc)
|
2021-03-24 13:48:26 +08:00
|
|
|
} catch (ex: RemoteException) {
|
|
|
|
|
errormsg("ignoring channel problem", ex)
|
|
|
|
|
|
|
|
|
|
setGUIfromModel() // Throw away user edits
|
|
|
|
|
|
|
|
|
|
// Tell the user to try again
|
|
|
|
|
Snackbar.make(
|
2022-02-07 21:50:31 -03:00
|
|
|
requireView(),
|
2021-03-24 13:48:26 +08:00
|
|
|
R.string.radio_sleeping,
|
|
|
|
|
Snackbar.LENGTH_SHORT
|
|
|
|
|
).show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-04 23:56:52 -03:00
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
|
|
|
super.onViewCreated(view, savedInstanceState)
|
2022-05-17 17:29:21 -03:00
|
|
|
|
2022-08-04 23:56:52 -03:00
|
|
|
val barcodeLauncher = registerForActivityResult(ScanContract()) { result ->
|
|
|
|
|
if (result.contents != null) {
|
|
|
|
|
model.setRequestChannelUrl(Uri.parse(result.contents))
|
2022-05-17 17:29:21 -03:00
|
|
|
}
|
2022-08-04 23:56:52 -03:00
|
|
|
}
|
2022-05-17 17:29:21 -03:00
|
|
|
|
2022-08-04 23:56:52 -03:00
|
|
|
fun zxingScan() {
|
|
|
|
|
debug("Starting zxing QR code scanner")
|
|
|
|
|
val zxingScan = ScanOptions()
|
|
|
|
|
zxingScan.setCameraId(0)
|
|
|
|
|
zxingScan.setPrompt("")
|
|
|
|
|
zxingScan.setBeepEnabled(false)
|
|
|
|
|
zxingScan.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
|
|
|
|
|
barcodeLauncher.launch(zxingScan)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val requestPermissionAndScanLauncher =
|
|
|
|
|
registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
|
|
|
|
if (permissions.entries.all { it.value }) zxingScan()
|
2022-05-17 17:29:21 -03:00
|
|
|
}
|
|
|
|
|
|
2022-08-04 23:56:52 -03:00
|
|
|
fun requestPermissionAndScan() {
|
|
|
|
|
MaterialAlertDialogBuilder(requireContext())
|
|
|
|
|
.setTitle(R.string.camera_required)
|
|
|
|
|
.setMessage(R.string.why_camera_required)
|
|
|
|
|
.setNeutralButton(R.string.cancel) { _, _ ->
|
|
|
|
|
debug("Camera permission denied")
|
|
|
|
|
}
|
|
|
|
|
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
|
|
|
|
requestPermissionAndScanLauncher.launch(requireContext().getCameraPermissions())
|
|
|
|
|
}
|
|
|
|
|
.show()
|
|
|
|
|
}
|
2020-04-07 17:42:31 -07:00
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.channelNameEdit.on(EditorInfo.IME_ACTION_DONE) {
|
2020-04-09 16:33:42 -07:00
|
|
|
requireActivity().hideKeyboard()
|
|
|
|
|
}
|
2020-04-08 10:55:28 -07:00
|
|
|
|
2022-05-03 17:32:01 -03:00
|
|
|
binding.resetButton.setOnClickListener {
|
2021-03-24 13:48:26 +08:00
|
|
|
// User just locked it, we should warn and then apply changes to radio
|
|
|
|
|
MaterialAlertDialogBuilder(requireContext())
|
|
|
|
|
.setTitle(R.string.reset_to_defaults)
|
2022-12-28 17:37:25 -03:00
|
|
|
.setMessage(R.string.are_you_sure_change_default)
|
2021-03-24 13:48:26 +08:00
|
|
|
.setNeutralButton(R.string.cancel) { _, _ ->
|
|
|
|
|
setGUIfromModel() // throw away any edits
|
|
|
|
|
}
|
2021-03-24 14:28:11 +08:00
|
|
|
.setPositiveButton(R.string.apply) { _, _ ->
|
2021-03-24 13:48:26 +08:00
|
|
|
debug("Switching back to default channel")
|
2022-07-26 23:01:28 -03:00
|
|
|
installSettings(
|
|
|
|
|
Channel.default.settings,
|
2022-09-18 18:35:13 -03:00
|
|
|
Channel.default.loraConfig.copy {
|
|
|
|
|
region = model.region
|
|
|
|
|
txEnabled = model.txEnabled
|
|
|
|
|
}
|
2022-07-26 23:01:28 -03:00
|
|
|
)
|
2021-03-24 13:48:26 +08:00
|
|
|
}
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-15 10:54:10 -03:00
|
|
|
binding.scanButton.setOnClickListener {
|
2022-08-25 20:50:55 -03:00
|
|
|
if (requireContext().hasCameraPermission()) zxingScan()
|
|
|
|
|
else requestPermissionAndScan()
|
2021-11-15 10:54:10 -03:00
|
|
|
}
|
|
|
|
|
|
2020-09-08 12:29:28 -07:00
|
|
|
// Note: Do not use setOnCheckedChanged here because we don't want to be called when we programmatically disable editing
|
2022-05-03 17:32:01 -03:00
|
|
|
binding.editableCheckbox.setOnClickListener {
|
2021-04-05 15:17:39 +08:00
|
|
|
|
|
|
|
|
/// We use this to determine if the user tried to install a custom name
|
|
|
|
|
var originalName = ""
|
|
|
|
|
|
2020-12-07 20:33:29 +08:00
|
|
|
val checked = binding.editableCheckbox.isChecked
|
2020-08-12 12:31:37 -07:00
|
|
|
if (checked) {
|
|
|
|
|
// User just unlocked for editing - remove the # goo around the channel name
|
2022-09-12 19:07:30 -03:00
|
|
|
model.channels.value.primaryChannel?.let { ch ->
|
2022-05-26 16:23:47 -03:00
|
|
|
// Note: We are careful to show the empty string here if the user was on a default channel, so the user knows they should it for any changes
|
2021-04-05 15:17:39 +08:00
|
|
|
originalName = ch.settings.name
|
|
|
|
|
binding.channelNameEdit.setText(originalName)
|
2020-08-12 12:31:37 -07:00
|
|
|
}
|
|
|
|
|
} else {
|
2020-04-09 16:33:42 -07:00
|
|
|
// User just locked it, we should warn and then apply changes to radio
|
2022-08-22 16:19:59 +01:00
|
|
|
|
2022-09-12 19:07:30 -03:00
|
|
|
model.channels.value.primaryChannel?.let { oldPrimary ->
|
2022-09-16 18:17:47 -03:00
|
|
|
var newSettings = oldPrimary.settings
|
2022-08-22 16:19:59 +01:00
|
|
|
val newName = binding.channelNameEdit.text.toString().trim()
|
|
|
|
|
|
|
|
|
|
// Find the new modem config
|
|
|
|
|
val selectedModemPresetString =
|
|
|
|
|
binding.filledExposedDropdown.editableText.toString()
|
|
|
|
|
var newModemPreset = getModemPreset(selectedModemPresetString)
|
|
|
|
|
if (newModemPreset == ConfigProtos.Config.LoRaConfig.ModemPreset.UNRECOGNIZED) // Huh? didn't find it - keep same
|
|
|
|
|
newModemPreset = oldPrimary.loraConfig.modemPreset
|
|
|
|
|
|
|
|
|
|
// Generate a new AES256 key if the user changes channel name or the name is non-default and the settings changed
|
|
|
|
|
val shouldUseRandomKey =
|
|
|
|
|
newName != originalName || (newName.isNotEmpty() && newModemPreset != oldPrimary.loraConfig.modemPreset)
|
|
|
|
|
if (shouldUseRandomKey) {
|
|
|
|
|
|
|
|
|
|
// Install a new customized channel
|
|
|
|
|
debug("ASSIGNING NEW AES256 KEY")
|
|
|
|
|
val random = SecureRandom()
|
|
|
|
|
val bytes = ByteArray(32)
|
|
|
|
|
random.nextBytes(bytes)
|
2022-09-18 20:23:34 -03:00
|
|
|
newSettings = newSettings.copy {
|
2022-09-16 18:17:47 -03:00
|
|
|
name = newName.take(11) // proto max_size:12
|
|
|
|
|
psk = ByteString.copyFrom(bytes)
|
|
|
|
|
}
|
2022-08-22 16:19:59 +01:00
|
|
|
} else {
|
|
|
|
|
debug("Switching back to default channel")
|
2022-09-16 18:17:47 -03:00
|
|
|
newSettings = Channel.default.settings
|
2020-04-08 10:55:28 -07:00
|
|
|
}
|
2020-04-15 07:49:39 -07:00
|
|
|
|
2022-08-22 16:19:59 +01:00
|
|
|
// No matter what apply the speed selection from the user
|
2022-10-13 18:20:51 -03:00
|
|
|
val newLoRaConfig = model.config.lora.copy {
|
2022-09-18 18:35:13 -03:00
|
|
|
usePreset = true
|
2022-09-16 18:17:47 -03:00
|
|
|
modemPreset = newModemPreset
|
2022-10-13 18:20:51 -03:00
|
|
|
bandwidth = 0
|
|
|
|
|
spreadFactor = 0
|
|
|
|
|
codingRate = 0
|
2022-09-16 18:17:47 -03:00
|
|
|
}
|
2022-08-22 16:19:59 +01:00
|
|
|
|
2022-09-16 18:17:47 -03:00
|
|
|
val humanName = Channel(newSettings, newLoRaConfig).humanName
|
2022-08-23 10:44:34 +00:00
|
|
|
binding.channelNameEdit.setText(humanName)
|
|
|
|
|
|
|
|
|
|
val message = buildString {
|
|
|
|
|
append(getString(R.string.are_you_sure_channel))
|
|
|
|
|
if (!shouldUseRandomKey)
|
|
|
|
|
append("\n\n" + getString(R.string.warning_default_psk).format(humanName))
|
|
|
|
|
}
|
2022-08-22 16:19:59 +01:00
|
|
|
|
|
|
|
|
MaterialAlertDialogBuilder(requireContext())
|
|
|
|
|
.setTitle(R.string.change_channel)
|
2022-08-23 10:44:34 +00:00
|
|
|
.setMessage(message)
|
2022-08-22 16:19:59 +01:00
|
|
|
.setNeutralButton(R.string.cancel) { _, _ ->
|
|
|
|
|
setGUIfromModel()
|
|
|
|
|
}
|
|
|
|
|
.setPositiveButton(getString(R.string.accept)) { _, _ ->
|
|
|
|
|
// Generate a new channel with only the changes the user can change in the GUI
|
2021-04-05 15:17:39 +08:00
|
|
|
|
2022-09-16 18:17:47 -03:00
|
|
|
installSettings(newSettings, newLoRaConfig)
|
2020-04-09 16:33:42 -07:00
|
|
|
}
|
2022-08-22 16:19:59 +01:00
|
|
|
.show()
|
|
|
|
|
}
|
2020-04-07 17:42:31 -07:00
|
|
|
}
|
|
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
onEditingChanged() // update GUI on what user is allowed to edit/share
|
|
|
|
|
}
|
2020-04-07 17:42:31 -07:00
|
|
|
|
2020-04-09 16:33:42 -07:00
|
|
|
// Share this particular channel if someone clicks share
|
2020-12-07 20:33:29 +08:00
|
|
|
binding.shareButton.setOnClickListener {
|
2020-04-09 16:33:42 -07:00
|
|
|
shareChannel()
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-12 19:07:30 -03:00
|
|
|
model.channels.asLiveData().observe(viewLifecycleOwner) {
|
2020-04-13 16:00:48 -07:00
|
|
|
setGUIfromModel()
|
2022-04-24 12:12:13 -03:00
|
|
|
}
|
2020-04-13 16:00:48 -07:00
|
|
|
|
|
|
|
|
// If connection state changes, we might need to enable/disable buttons
|
2022-04-24 12:12:13 -03:00
|
|
|
model.connectionState.observe(viewLifecycleOwner) {
|
2020-04-09 16:33:42 -07:00
|
|
|
setGUIfromModel()
|
2022-04-24 12:12:13 -03:00
|
|
|
}
|
2020-04-07 16:04:58 -07:00
|
|
|
}
|
2020-06-14 00:11:08 -04:00
|
|
|
|
2022-05-26 16:23:47 -03:00
|
|
|
private fun getModemPreset(selectedChannelOptionString: String): ConfigProtos.Config.LoRaConfig.ModemPreset {
|
2020-06-14 00:11:08 -04:00
|
|
|
for (item in ChannelOption.values()) {
|
|
|
|
|
if (getString(item.configRes) == selectedChannelOptionString)
|
2022-05-26 16:23:47 -03:00
|
|
|
return item.modemPreset
|
2020-06-14 00:11:08 -04:00
|
|
|
}
|
2022-05-26 16:23:47 -03:00
|
|
|
return ConfigProtos.Config.LoRaConfig.ModemPreset.UNRECOGNIZED
|
2020-06-14 00:11:08 -04:00
|
|
|
}
|
2021-11-17 16:26:12 -03:00
|
|
|
}
|