showing real channel data works

pull/8/head
geeksville 2020-03-15 16:30:12 -07:00
rodzic 6ce859a952
commit 36b2da72e4
5 zmienionych plików z 171 dodań i 132 usunięć

Wyświetl plik

@ -10,11 +10,37 @@ import androidx.core.content.edit
import com.geeksville.android.Logging
import com.geeksville.mesh.IMeshService
import com.geeksville.mesh.MeshProtos
import com.geeksville.mesh.MeshProtos.ChannelSettings.ModemConfig
import com.geeksville.mesh.ui.getInitials
import com.google.zxing.BarcodeFormat
import com.google.zxing.MultiFormatWriter
import com.journeyapps.barcodescanner.BarcodeEncoder
data class Channel(
val name: String,
val num: Int,
val modemConfig: ModemConfig = ModemConfig.Bw125Cr45Sf128
) {
companion object {
// Placeholder when emulating
val emulated = Channel("Default", 7)
}
constructor(c: MeshProtos.ChannelSettings) : this(c.name, c.channelNum, c.modemConfig) {
}
}
/**
* a nice readable description of modem configs
*/
fun ModemConfig.toHumanString(): String = when (this) {
ModemConfig.Bw125Cr45Sf128 -> "Medium range (but fast)"
ModemConfig.Bw500Cr45Sf128 -> "Short range (but fast)"
ModemConfig.Bw31_25Cr48Sf512 -> "Long range (but slower)"
ModemConfig.Bw125Cr48Sf4096 -> "Very long range (but slow)"
else -> this.toString()
}
/// FIXME - figure out how to merge this staate with the AppStatus Model
object UIState : Logging {
@ -34,6 +60,8 @@ object UIState : Logging {
/// our activity will read this from prefs or set it to the empty string
var ownerName: String = "MrInIDE Ownername"
fun getChannel() = radioConfig.value?.channelSettings?.let { Channel(it) }
/// Return an URL that represents the current channel values
fun getChannelUrl(context: Context): String {
// If we have a valid radio config use it, othterwise use whatever we have saved in the prefs
@ -52,8 +80,7 @@ object UIState : Logging {
}
}
fun getChannelQR(context: Context): Bitmap
{
fun getChannelQR(context: Context): Bitmap {
val multiFormatWriter = MultiFormatWriter()
val bitMatrix =

Wyświetl plik

@ -0,0 +1,89 @@
package com.geeksville.mesh.ui
import android.graphics.Bitmap
import androidx.compose.Composable
import androidx.ui.core.DensityAmbient
import androidx.ui.core.DrawModifier
import androidx.ui.core.Modifier
import androidx.ui.core.toModifier
import androidx.ui.foundation.Box
import androidx.ui.graphics.*
import androidx.ui.graphics.colorspace.ColorSpace
import androidx.ui.graphics.colorspace.ColorSpaces
import androidx.ui.graphics.painter.ImagePainter
import androidx.ui.unit.Density
import androidx.ui.unit.PxSize
import androidx.ui.unit.toRect
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
// TODO(mount, malkov) : remove when RepaintBoundary is a modifier: b/149982905
// This is class and not val because if b/149985596
private object ClipModifier : DrawModifier {
override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
canvas.save()
canvas.clipRect(size.toRect())
drawContent()
canvas.restore()
}
}
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
@Composable
fun ScaledImage(
image: Image,
modifier: Modifier = Modifier.None,
tint: Color? = null
) {
with(DensityAmbient.current) {
val imageModifier = ImagePainter(image).toModifier(
scaleFit = ScaleFit.FillMaxDimension,
colorFilter = tint?.let { ColorFilter(it, BlendMode.srcIn) }
)
Box(modifier + ClipModifier + imageModifier)
}
}
/// Borrowed from Compose
class AndroidImage(val bitmap: Bitmap) : Image {
/**
* @see Image.width
*/
override val width: Int
get() = bitmap.width
/**
* @see Image.height
*/
override val height: Int
get() = bitmap.height
override val config: ImageConfig get() = ImageConfig.Argb8888
/**
* @see Image.colorSpace
*/
override val colorSpace: ColorSpace
get() = ColorSpaces.Srgb
/**
* @see Image.hasAlpha
*/
override val hasAlpha: Boolean
get() = bitmap.hasAlpha()
/**
* @see Image.nativeImage
*/
override val nativeImage: NativeImage
get() = bitmap
/**
* @see
*/
override fun prepareToDraw() {
bitmap.prepareToDraw()
}
}

Wyświetl plik

@ -1,164 +1,87 @@
package com.geeksville.mesh.ui
import android.content.Intent
import android.graphics.Bitmap
import androidx.compose.Composable
import androidx.ui.core.*
import androidx.ui.foundation.Box
import androidx.ui.graphics.*
import androidx.ui.graphics.colorspace.ColorSpace
import androidx.ui.graphics.colorspace.ColorSpaces
import androidx.ui.graphics.painter.ImagePainter
import androidx.ui.core.ContextAmbient
import androidx.ui.core.Text
import androidx.ui.layout.*
import androidx.ui.material.MaterialTheme
import androidx.ui.material.OutlinedButton
import androidx.ui.material.ripple.Ripple
import androidx.ui.tooling.preview.Preview
import androidx.ui.unit.Density
import androidx.ui.unit.PxSize
import androidx.ui.unit.dp
import androidx.ui.unit.toRect
import com.geeksville.analytics.DataPair
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.mesh.R
import com.geeksville.mesh.model.Channel
import com.geeksville.mesh.model.UIState
import com.geeksville.mesh.model.toHumanString
/// The Compose IDE preview doesn't like the protobufs
data class Channel(val name: String, val num: Int)
object ChannelLog : Logging
/// Borrowed from Compose
class AndroidImage(val bitmap: Bitmap) : Image {
/**
* @see Image.width
*/
override val width: Int
get() = bitmap.width
/**
* @see Image.height
*/
override val height: Int
get() = bitmap.height
override val config: ImageConfig get() = ImageConfig.Argb8888
/**
* @see Image.colorSpace
*/
override val colorSpace: ColorSpace
get() = ColorSpaces.Srgb
/**
* @see Image.hasAlpha
*/
override val hasAlpha: Boolean
get() = bitmap.hasAlpha()
/**
* @see Image.nativeImage
*/
override val nativeImage: NativeImage
get() = bitmap
/**
* @see
*/
override fun prepareToDraw() {
bitmap.prepareToDraw()
}
}
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
// TODO(mount, malkov) : remove when RepaintBoundary is a modifier: b/149982905
// This is class and not val because if b/149985596
private object ClipModifier : DrawModifier {
override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) {
canvas.save()
canvas.clipRect(size.toRect())
drawContent()
canvas.restore()
}
}
/// Stolen from the Compose SimpleImage, replace with their real Image component someday
@Composable
fun ScaledImage(
image: Image,
modifier: Modifier = Modifier.None,
tint: Color? = null
) {
with(DensityAmbient.current) {
val imageModifier = ImagePainter(image).toModifier(
scaleFit = ScaleFit.FillMaxDimension,
colorFilter = tint?.let { ColorFilter(it, BlendMode.srcIn) }
)
Box(modifier + ClipModifier + imageModifier)
}
}
@Composable
fun ChannelContent(channel: Channel = Channel("Default", 7)) {
fun ChannelContent(channel: Channel?) {
analyticsScreen(name = "channel")
val typography = MaterialTheme.typography()
val context = ContextAmbient.current
Column(modifier = LayoutSize.Fill + LayoutPadding(16.dp)) {
Text(
text = "Channel: ${channel.name}",
modifier = LayoutGravity.Center,
style = typography.h4
)
Row(modifier = LayoutGravity.Center) {
// simulated qr code
// val image = imageResource(id = R.drawable.qrcode)
val image = AndroidImage(UIState.getChannelQR(context))
ScaledImage(
image = image,
modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)
if (channel != null) {
Text(
text = "Channel: ${channel.name}",
modifier = LayoutGravity.Center,
style = typography.h4
)
Ripple(bounded = false) {
OutlinedButton(modifier = LayoutGravity.Center + LayoutPadding(start = 24.dp),
onClick = {
GeeksvilleApplication.analytics.track(
"share",
DataPair("content_type", "channel")
) // track how many times users share channels
Row(modifier = LayoutGravity.Center) {
// simulated qr code
// val image = imageResource(id = R.drawable.qrcode)
val image = AndroidImage(UIState.getChannelQR(context))
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, UIState.getChannelUrl(context))
putExtra(Intent.EXTRA_TITLE, "A URL for joining a Meshtastic mesh")
type = "text/plain"
}
ScaledImage(
image = image,
modifier = LayoutGravity.Center + LayoutSize.Min(200.dp, 200.dp)
)
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
}) {
VectorImage(
id = R.drawable.ic_twotone_share_24,
tint = palette.onBackground
)
Ripple(bounded = false) {
OutlinedButton(modifier = LayoutGravity.Center + LayoutPadding(start = 24.dp),
onClick = {
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, UIState.getChannelUrl(context))
putExtra(Intent.EXTRA_TITLE, "A URL for joining a Meshtastic mesh")
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
context.startActivity(shareIntent)
}) {
VectorImage(
id = R.drawable.ic_twotone_share_24,
tint = palette.onBackground
)
}
}
}
}
Text(
text = "Number: ${channel.num}",
modifier = LayoutGravity.Center
)
Text(
text = "Mode: Long range (but slow)",
modifier = LayoutGravity.Center
)
Text(
text = "Number: ${channel.num}",
modifier = LayoutGravity.Center
)
Text(
text = "Mode: ${channel.modemConfig.toHumanString()}",
modifier = LayoutGravity.Center
)
}
}
}
@ -168,6 +91,6 @@ fun ChannelContent(channel: Channel = Channel("Default", 7)) {
fun previewChannel() {
// another bug? It seems modaldrawerlayout not yet supported in preview
MaterialTheme(colors = palette) {
ChannelContent()
ChannelContent(Channel.emulated)
}
}

Wyświetl plik

@ -145,7 +145,7 @@ private fun AppContent(openDrawer: () -> Unit) {
Screen.messages -> MessagesContent()
Screen.settings -> SettingsContent()
Screen.users -> HomeContent()
Screen.channel -> ChannelContent()
Screen.channel -> ChannelContent(UIState.getChannel())
Screen.map -> MapContent()
else -> TODO()
}

@ -1 +1 @@
Subproject commit f309ee8f9e9db37daabd7c76da683e052ef62f7a
Subproject commit 66e926740acb30518d1fdcb901d1cc0b0d48122c