mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
246 lines
No EOL
8.4 KiB
Kotlin
246 lines
No EOL
8.4 KiB
Kotlin
package com.geeksville.mesh.ui
|
|
|
|
import android.content.Intent
|
|
import android.graphics.ColorMatrix
|
|
import android.graphics.ColorMatrixColorFilter
|
|
import android.os.Bundle
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.view.inputmethod.EditorInfo
|
|
import android.widget.ArrayAdapter
|
|
import android.widget.ImageView
|
|
import androidx.fragment.app.activityViewModels
|
|
import androidx.lifecycle.Observer
|
|
import com.geeksville.analytics.DataPair
|
|
import com.geeksville.android.GeeksvilleApplication
|
|
import com.geeksville.android.Logging
|
|
import com.geeksville.android.hideKeyboard
|
|
import com.geeksville.mesh.R
|
|
import com.geeksville.mesh.model.UIViewModel
|
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
import kotlinx.android.synthetic.main.channel_fragment.*
|
|
|
|
|
|
// 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
|
|
}
|
|
|
|
class ChannelFragment : ScreenFragment("Channel"), Logging {
|
|
|
|
private val model: UIViewModel by activityViewModels()
|
|
|
|
override fun onCreateView(
|
|
inflater: LayoutInflater, container: ViewGroup?,
|
|
savedInstanceState: Bundle?
|
|
): View? {
|
|
return inflater.inflate(R.layout.channel_fragment, container, false)
|
|
}
|
|
|
|
/// 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)
|
|
}
|
|
}
|
|
|
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
super.onViewCreated(view, savedInstanceState)
|
|
|
|
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(R.string.change_channel)
|
|
.setMessage(R.string.are_you_sure_channel)
|
|
.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
|
|
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()
|
|
}
|
|
|
|
onEditingChanged() // update GUI on what user is allowed to edit/share
|
|
}
|
|
|
|
// Share this particular channel if someone clicks share
|
|
shareButton.setOnClickListener {
|
|
shareChannel()
|
|
}
|
|
|
|
model.radioConfig.observe(viewLifecycleOwner, Observer { config ->
|
|
setGUIfromModel()
|
|
})
|
|
}
|
|
}
|
|
|
|
/*
|
|
@Composable
|
|
fun ChannelContent(channel: Channel?) {
|
|
|
|
val typography = MaterialTheme.typography
|
|
val context = ContextAmbient.current
|
|
|
|
Column(modifier = LayoutSize.Fill + LayoutPadding(16.dp)) {
|
|
if (channel != null) {
|
|
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)
|
|
),
|
|
imeAction = ImeAction.Done,
|
|
onImeActionPerformed = {
|
|
ChannelLog.errormsg("FIXME, implement channel edit button")
|
|
}
|
|
)
|
|
} else {
|
|
Text(
|
|
text = channel.name,
|
|
style = typography.h4
|
|
)
|
|
}
|
|
}
|
|
|
|
// simulated qr code
|
|
// val image = imageResource(id = R.drawable.qrcode)
|
|
val image = AndroidImage(channel.getChannelQR())
|
|
|
|
ScaledImage(
|
|
image = image,
|
|
modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)
|
|
)
|
|
|
|
Text(
|
|
text = "Mode: ${channel.modemConfig.toHumanString()}",
|
|
modifier = LayoutGravity.Center + LayoutPadding(bottom = 16.dp)
|
|
)
|
|
|
|
Row(modifier = LayoutGravity.Center) {
|
|
|
|
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
|
|
)
|
|
}
|
|
|
|
// Only show the share buttone once we are locked
|
|
if (!channel.editable)
|
|
OutlinedButton(modifier = LayoutPadding(start = 24.dp),
|
|
onClick = {
|
|
|
|
}) {
|
|
VectorImage(
|
|
id = R.drawable.ic_twotone_share_24,
|
|
tint = palette.onBackground
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*/ |