Meshtastic-Android/app/src/main/java/com/geeksville/mesh/ui/ChannelFragment.kt

246 lines
8.5 KiB
Kotlin
Raw Normal View History

2020-02-17 20:00:11 -08:00
package com.geeksville.mesh.ui
import android.content.Intent
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
2020-04-07 16:04:58 -07:00
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
2020-04-07 17:42:31 -07:00
import android.widget.ArrayAdapter
import android.widget.ImageView
2020-04-07 17:42:31 -07:00
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import com.geeksville.analytics.DataPair
import com.geeksville.android.GeeksvilleApplication
2020-02-18 08:56:37 -08:00
import com.geeksville.android.Logging
import com.geeksville.android.hideKeyboard
2020-02-17 20:00:11 -08:00
import com.geeksville.mesh.R
2020-04-07 17:42:31 -07:00
import com.geeksville.mesh.model.UIViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.android.synthetic.main.channel_fragment.*
2020-02-17 20:00:11 -08: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
}
2020-04-07 16:04:58 -07:00
class ChannelFragment : ScreenFragment("Channel"), Logging {
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?
2020-04-07 17:42:31 -07:00
): View? {
return inflater.inflate(R.layout.channel_fragment, container, false)
}
2020-04-07 16:04:58 -07:00
/// Called when the lock/unlock icon has changed
private fun onEditingChanged() {
val isEditing = editableCheckbox.isChecked
channelOptions.isEnabled = false // Not yet ready
shareButton.isEnabled = !isEditing
channelNameView.isEnabled = isEditing
if (isEditing) // Dim the (stale) QR code while editing...
qrView.setDim()
else
qrView.setOpaque()
}
/// Pull the latest data from the model (discarding any user edits)
private fun setGUIfromModel() {
val channel = UIViewModel.getChannel(model.radioConfig.value)
editableCheckbox.isChecked = false // start locked
if (channel != null) {
qrView.visibility = View.VISIBLE
channelNameEdit.visibility = View.VISIBLE
channelNameEdit.setText(channel.name)
editableCheckbox.isEnabled = true
qrView.setImageBitmap(channel.getChannelQR())
} else {
qrView.visibility = View.INVISIBLE
channelNameEdit.visibility = View.INVISIBLE
editableCheckbox.isEnabled = false
}
onEditingChanged() // we just locked the gui
val adapter = ArrayAdapter(
requireContext(),
R.layout.dropdown_menu_popup_item,
arrayOf("Item 1", "Item 2", "Item 3", "Item 4")
)
filled_exposed_dropdown.setAdapter(adapter)
}
private fun shareChannel() {
UIViewModel.getChannel(model.radioConfig.value)?.let { channel ->
GeeksvilleApplication.analytics.track(
"share",
DataPair("content_type", "channel")
) // track how many times users share channels
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, channel.getChannelUrl().toString())
putExtra(
Intent.EXTRA_TITLE,
getString(R.string.url_for_join)
)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
requireActivity().startActivity(shareIntent)
}
}
2020-04-07 16:04:58 -07:00
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
2020-04-07 17:42:31 -07:00
channelNameEdit.on(EditorInfo.IME_ACTION_DONE) {
requireActivity().hideKeyboard()
}
editableCheckbox.setOnCheckedChangeListener { _, checked ->
if (!checked) {
// User just locked it, we should warn and then apply changes to radio
/* Snackbar.make(
editableCheckbox,
"Changing channels is not yet supported",
Snackbar.LENGTH_SHORT
).show() */
MaterialAlertDialogBuilder(requireContext())
.setTitle("Change channel")
.setMessage("Are you sure you want to change the channel? All communication with other nodes will stop until you share the new channel settings.")
.setNeutralButton("Cancel") { _, _ ->
setGUIfromModel()
}
.setPositiveButton("Accept") { _, _ ->
// Generate a new channel with only the changes the user can change in the GUI
UIViewModel.getChannel(model.radioConfig.value)?.let { old ->
val newSettings = old.settings.toBuilder()
newSettings.name = channelNameEdit.text.toString().trim()
// FIXME, regenerate a new preshared key!
model.setChannel(newSettings.build())
// Since we are writing to radioconfig, that will trigger the rest of the GUI update (QR code etc)
}
}
.show()
2020-04-07 17:42:31 -07:00
}
onEditingChanged() // update GUI on what user is allowed to edit/share
}
2020-04-07 17:42:31 -07:00
// Share this particular channel if someone clicks share
shareButton.setOnClickListener {
shareChannel()
}
model.radioConfig.observe(viewLifecycleOwner, Observer { config ->
setGUIfromModel()
2020-04-07 17:42:31 -07:00
})
2020-04-07 16:04:58 -07:00
}
}
/*
@Composable
2020-03-15 16:30:12 -07:00
fun ChannelContent(channel: Channel?) {
val typography = MaterialTheme.typography
2020-02-29 14:34:20 -08:00
val context = ContextAmbient.current
2020-02-17 20:00:11 -08:00
Column(modifier = LayoutSize.Fill + LayoutPadding(16.dp)) {
2020-03-15 16:30:12 -07:00
if (channel != null) {
2020-03-15 18:44:10 -07:00
Row(modifier = LayoutGravity.Center) {
Text(text = "Channel ", modifier = LayoutGravity.Center)
if (channel.editable) {
// FIXME - limit to max length
StyledTextField(
value = channel.name,
onValueChange = { channel.name = it },
textStyle = typography.h4.copy(
color = palette.onSecondary.copy(alpha = 0.8f)
),
2020-03-17 11:35:19 -07:00
imeAction = ImeAction.Done,
2020-03-15 18:44:10 -07:00
onImeActionPerformed = {
ChannelLog.errormsg("FIXME, implement channel edit button")
2020-03-15 18:44:10 -07:00
}
)
} else {
Text(
text = channel.name,
style = typography.h4
)
}
}
// simulated qr code
// val image = imageResource(id = R.drawable.qrcode)
2020-03-17 11:35:19 -07:00
val image = AndroidImage(channel.getChannelQR())
2020-03-15 18:44:10 -07:00
ScaledImage(
image = image,
modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)
)
2020-03-15 16:30:12 -07:00
Text(
2020-03-15 18:44:10 -07:00
text = "Mode: ${channel.modemConfig.toHumanString()}",
modifier = LayoutGravity.Center + LayoutPadding(bottom = 16.dp)
)
2020-02-17 20:17:08 -08:00
2020-03-15 16:30:12 -07:00
Row(modifier = LayoutGravity.Center) {
2020-03-15 18:44:10 -07:00
OutlinedButton(onClick = {
channel.editable = !channel.editable
}) {
if (channel.editable)
VectorImage(
id = R.drawable.ic_twotone_lock_open_24,
tint = palette.onBackground
)
else
VectorImage(
id = R.drawable.ic_twotone_lock_24,
tint = palette.onBackground
)
}
2020-03-15 16:30:12 -07:00
2020-03-15 18:44:10 -07:00
// Only show the share buttone once we are locked
if (!channel.editable)
OutlinedButton(modifier = LayoutPadding(start = 24.dp),
2020-03-15 16:30:12 -07:00
onClick = {
2020-03-15 16:30:12 -07:00
}) {
VectorImage(
id = R.drawable.ic_twotone_share_24,
tint = palette.onBackground
)
}
2020-02-18 08:56:37 -08:00
}
2020-03-15 16:30:12 -07:00
}
2020-02-17 20:00:11 -08:00
}
}
*/