kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
commit
c32a35833f
|
@ -978,6 +978,15 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
handler.removeCallbacksAndMessages(null)
|
handler.removeCallbacksAndMessages(null)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
R.id.advanced_settings -> {
|
||||||
|
val fragmentManager: FragmentManager = supportFragmentManager
|
||||||
|
val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction()
|
||||||
|
val nameFragment = AdvancedSettingsFragment()
|
||||||
|
fragmentTransaction.add(R.id.mainActivityLayout, nameFragment)
|
||||||
|
fragmentTransaction.addToBackStack(null)
|
||||||
|
fragmentTransaction.commit()
|
||||||
|
return true
|
||||||
|
}
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ package com.geeksville.mesh.model
|
||||||
import com.geeksville.mesh.MeshProtos
|
import com.geeksville.mesh.MeshProtos
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
|
|
||||||
enum class ChannelOption(val modemConfig: MeshProtos.ChannelSettings.ModemConfig, val configRes: Int) {
|
enum class ChannelOption(val modemConfig: MeshProtos.ChannelSettings.ModemConfig, val configRes: Int, val minBroadcastPeriodSecs: Int) {
|
||||||
SHORT(MeshProtos.ChannelSettings.ModemConfig.Bw500Cr45Sf128, R.string.modem_config_short),
|
SHORT(MeshProtos.ChannelSettings.ModemConfig.Bw500Cr45Sf128, R.string.modem_config_short, 3),
|
||||||
MEDIUM(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128, R.string.modem_config_medium),
|
MEDIUM(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr45Sf128, R.string.modem_config_medium, 12),
|
||||||
LONG(MeshProtos.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512, R.string.modem_config_long),
|
LONG(MeshProtos.ChannelSettings.ModemConfig.Bw31_25Cr48Sf512, R.string.modem_config_long, 240),
|
||||||
VERY_LONG(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr48Sf4096, R.string.modem_config_very_long);
|
VERY_LONG(MeshProtos.ChannelSettings.ModemConfig.Bw125Cr48Sf4096, R.string.modem_config_very_long, 375);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromConfig(modemConfig: MeshProtos.ChannelSettings.ModemConfig?): ChannelOption? {
|
fun fromConfig(modemConfig: MeshProtos.ChannelSettings.ModemConfig?): ChannelOption? {
|
||||||
|
@ -17,5 +17,6 @@ enum class ChannelOption(val modemConfig: MeshProtos.ChannelSettings.ModemConfig
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
val defaultMinBroadcastPeriod = VERY_LONG.minBroadcastPeriodSecs
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import com.geeksville.android.Logging
|
||||||
|
import com.geeksville.android.hideKeyboard
|
||||||
|
import com.geeksville.mesh.R
|
||||||
|
import com.geeksville.mesh.databinding.AdvancedSettingsBinding
|
||||||
|
import com.geeksville.mesh.model.ChannelOption
|
||||||
|
import com.geeksville.mesh.model.UIViewModel
|
||||||
|
import com.geeksville.mesh.service.MeshService
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
|
||||||
|
class AdvancedSettingsFragment : ScreenFragment("Advanced Settings"), Logging {
|
||||||
|
private val MAX_INT_DEVICE = 0xFFFFFFFF
|
||||||
|
private var _binding: AdvancedSettingsBinding? = null
|
||||||
|
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
|
private val model: UIViewModel by activityViewModels()
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
_binding = AdvancedSettingsBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
|
model.radioConfig.observe(viewLifecycleOwner, { _ ->
|
||||||
|
binding.positionBroadcastPeriodEditText.setText(model.positionBroadcastSecs.toString())
|
||||||
|
binding.lsSleepEditText.setText(model.lsSleepSecs.toString())
|
||||||
|
})
|
||||||
|
|
||||||
|
model.isConnected.observe(viewLifecycleOwner, Observer { connectionState ->
|
||||||
|
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
||||||
|
binding.positionBroadcastPeriodView.isEnabled = connected
|
||||||
|
binding.lsSleepView.isEnabled = connected
|
||||||
|
})
|
||||||
|
|
||||||
|
binding.positionBroadcastPeriodEditText.on(EditorInfo.IME_ACTION_DONE) {
|
||||||
|
val textEdit = binding.positionBroadcastPeriodEditText
|
||||||
|
val n = textEdit.text.toString().toIntOrNull()
|
||||||
|
val minBroadcastPeriodSecs =
|
||||||
|
ChannelOption.fromConfig(model.radioConfig.value?.channelSettings?.modemConfig)?.minBroadcastPeriodSecs
|
||||||
|
?: ChannelOption.defaultMinBroadcastPeriod
|
||||||
|
|
||||||
|
if (n != null && n < MAX_INT_DEVICE && (n == 0 || n >= minBroadcastPeriodSecs)) {
|
||||||
|
model.positionBroadcastSecs = n
|
||||||
|
} else {
|
||||||
|
// restore the value in the edit field
|
||||||
|
textEdit.setText(model.positionBroadcastSecs.toString())
|
||||||
|
val errorText =
|
||||||
|
if (n == null || n < 0 || n >= MAX_INT_DEVICE)
|
||||||
|
"Bad value: ${textEdit.text.toString()}"
|
||||||
|
else
|
||||||
|
getString(R.string.broadcast_period_too_small).format(minBroadcastPeriodSecs)
|
||||||
|
|
||||||
|
Snackbar.make(requireView(), errorText, Snackbar.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
requireActivity().hideKeyboard()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.lsSleepEditText.on(EditorInfo.IME_ACTION_DONE) {
|
||||||
|
val str = binding.lsSleepEditText.text.toString()
|
||||||
|
val n = str.toIntOrNull()
|
||||||
|
if (n != null && n < MAX_INT_DEVICE && n >= 0) {
|
||||||
|
model.lsSleepSecs = n
|
||||||
|
} else {
|
||||||
|
Snackbar.make(requireView(), "Bad value: $str", Snackbar.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
requireActivity().hideKeyboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,7 +30,6 @@ import com.geeksville.android.Logging
|
||||||
import com.geeksville.android.hideKeyboard
|
import com.geeksville.android.hideKeyboard
|
||||||
import com.geeksville.android.isGooglePlayAvailable
|
import com.geeksville.android.isGooglePlayAvailable
|
||||||
import com.geeksville.mesh.MainActivity
|
import com.geeksville.mesh.MainActivity
|
||||||
import com.geeksville.mesh.MeshProtos
|
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.android.bluetoothManager
|
import com.geeksville.mesh.android.bluetoothManager
|
||||||
import com.geeksville.mesh.android.usbManager
|
import com.geeksville.mesh.android.usbManager
|
||||||
|
@ -462,7 +461,6 @@ class BTScanModel(app: Application) : AndroidViewModel(app), Logging {
|
||||||
|
|
||||||
@SuppressLint("NewApi")
|
@SuppressLint("NewApi")
|
||||||
class SettingsFragment : ScreenFragment("Settings"), Logging {
|
class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
private val MAX_INT_DEVICE = 0xFFFFFFFF
|
|
||||||
private var _binding: SettingsFragmentBinding? = null
|
private var _binding: SettingsFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
@ -574,28 +572,18 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
|
|
||||||
/// Setup the ui widgets unrelated to BLE scanning
|
/// Setup the ui widgets unrelated to BLE scanning
|
||||||
private fun initCommonUI() {
|
private fun initCommonUI() {
|
||||||
// We want to leave these visible in the IDE, but make sure they default to not visible until we have valid data
|
|
||||||
binding.positionBroadcastPeriodView.visibility = View.GONE
|
|
||||||
binding.lsSleepView.visibility = View.GONE
|
|
||||||
|
|
||||||
model.ownerName.observe(viewLifecycleOwner, { name ->
|
model.ownerName.observe(viewLifecycleOwner, { name ->
|
||||||
binding.usernameEditText.setText(name)
|
binding.usernameEditText.setText(name)
|
||||||
})
|
})
|
||||||
|
|
||||||
model.radioConfig.observe(viewLifecycleOwner, { _ ->
|
|
||||||
binding.positionBroadcastPeriodEditText.setText(model.positionBroadcastSecs.toString())
|
|
||||||
binding.lsSleepEditText.setText(model.lsSleepSecs.toString())
|
|
||||||
})
|
|
||||||
|
|
||||||
// Only let user edit their name or set software update while connected to a radio
|
// Only let user edit their name or set software update while connected to a radio
|
||||||
model.isConnected.observe(viewLifecycleOwner, Observer { connectionState ->
|
model.isConnected.observe(viewLifecycleOwner, Observer { connectionState ->
|
||||||
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
val connected = connectionState == MeshService.ConnectionState.CONNECTED
|
||||||
binding.usernameView.isEnabled = connected
|
binding.usernameView.isEnabled = connected
|
||||||
|
|
||||||
// Don't even show advanced fields until after we have a connection
|
|
||||||
binding.positionBroadcastPeriodView.visibility = if (connected) View.VISIBLE else View.GONE
|
|
||||||
binding.lsSleepView.visibility = if (connected) View.VISIBLE else View.GONE
|
|
||||||
|
|
||||||
if (connectionState == MeshService.ConnectionState.DISCONNECTED)
|
if (connectionState == MeshService.ConnectionState.DISCONNECTED)
|
||||||
model.ownerName.value = ""
|
model.ownerName.value = ""
|
||||||
|
|
||||||
|
@ -619,27 +607,6 @@ class SettingsFragment : ScreenFragment("Settings"), Logging {
|
||||||
requireActivity().hideKeyboard()
|
requireActivity().hideKeyboard()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.positionBroadcastPeriodEditText.on(EditorInfo.IME_ACTION_DONE) {
|
|
||||||
val str = binding.positionBroadcastPeriodEditText.text.toString()
|
|
||||||
val n = str.toIntOrNull()
|
|
||||||
if (n != null && n <= MAX_INT_DEVICE && n >= 0) {
|
|
||||||
model.positionBroadcastSecs = n
|
|
||||||
} else {
|
|
||||||
binding.scanStatusText.text = "Bad value: $str"
|
|
||||||
}
|
|
||||||
requireActivity().hideKeyboard()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.lsSleepEditText.on(EditorInfo.IME_ACTION_DONE) {
|
|
||||||
val str = binding.lsSleepEditText.text.toString()
|
|
||||||
val n = str.toIntOrNull()
|
|
||||||
if (n != null && n < MAX_INT_DEVICE && n >= 0) {
|
|
||||||
model.lsSleepSecs = n
|
|
||||||
} else {
|
|
||||||
binding.scanStatusText.text = "Bad value: $str"
|
|
||||||
}
|
|
||||||
requireActivity().hideKeyboard()
|
|
||||||
}
|
|
||||||
|
|
||||||
val app = (requireContext().applicationContext as GeeksvilleApplication)
|
val app = (requireContext().applicationContext as GeeksvilleApplication)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#FFFFFF">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/positionBroadcastPeriodView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:hint="@string/broadcast_position_secs"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/positionBroadcastPeriodEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="number"
|
||||||
|
android:singleLine="true" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/lsSleepView"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:hint="@string/ls_sleep_secs"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/positionBroadcastPeriodView">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/lsSleepEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:imeOptions="actionDone"
|
||||||
|
android:inputType="number"
|
||||||
|
android:singleLine="true" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -152,48 +152,6 @@
|
||||||
app:layout_constraintTop_toBottomOf="@+id/updateFirmwareButton" />
|
app:layout_constraintTop_toBottomOf="@+id/updateFirmwareButton" />
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/positionBroadcastPeriodView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:hint="@string/broadcast_position_secs"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/warningNotPaired">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/positionBroadcastPeriodEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:imeOptions="actionDone"
|
|
||||||
android:inputType="number"
|
|
||||||
android:singleLine="true" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/lsSleepView"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:hint="@string/ls_sleep_secs"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/positionBroadcastPeriodView">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:id="@+id/lsSleepEditText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:imeOptions="actionDone"
|
|
||||||
android:inputType="number"
|
|
||||||
android:singleLine="true" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
|
@ -16,6 +16,10 @@
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:checked="false"
|
android:checked="false"
|
||||||
android:title="Protocol stress test" />
|
android:title="Protocol stress test" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/advanced_settings"
|
||||||
|
app:showAsAction="withText"
|
||||||
|
android:title="Advanced settings" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/about"
|
android:id="@+id/about"
|
||||||
android:title="@string/about"
|
android:title="@string/about"
|
||||||
|
|
|
@ -86,4 +86,5 @@
|
||||||
<string name="broadcast_position_secs">Broadcast position period (in seconds), 0 - disable</string>
|
<string name="broadcast_position_secs">Broadcast position period (in seconds), 0 - disable</string>
|
||||||
<string name="ls_sleep_secs">Device sleep period (in seconds)</string>
|
<string name="ls_sleep_secs">Device sleep period (in seconds)</string>
|
||||||
<string name="meshtastic_messages_notifications">Notifications about messages</string>
|
<string name="meshtastic_messages_notifications">Notifications about messages</string>
|
||||||
|
<string name="broadcast_period_too_small">Minimum broadcast period for this channel is %d</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Ładowanie…
Reference in New Issue