channel sharing WIP

This commit is contained in:
geeksville 2020-03-17 11:35:19 -07:00
parent 8812793cbd
commit 40a142064f
4 changed files with 70 additions and 39 deletions

View file

@ -200,9 +200,6 @@ class MainActivity : AppCompatActivity(), Logging,
requestPermission()
setContent {
MeshApp()
}
/* not yet working
// Configure sign-in to request the user's ID, email address, and basic
@ -221,6 +218,10 @@ class MainActivity : AppCompatActivity(), Logging,
// Handle any intent
handleIntent(intent)
setContent {
MeshApp()
}
}
override fun onNewIntent(intent: Intent) {
@ -233,9 +234,12 @@ class MainActivity : AppCompatActivity(), Logging,
val appLinkAction = intent.action
val appLinkData: Uri? = intent.data
UIState.requestedChannelUrl = null // assume none
// Were we asked to open one our channel URLs?
if (Intent.ACTION_VIEW == appLinkAction && appLinkData != null) {
if (Intent.ACTION_VIEW == appLinkAction) {
debug("Asked to open a channel URL - FIXME, ask user if they want to switch to that channel. If so send the config to the radio")
UIState.requestedChannelUrl = appLinkData
}
}

View file

@ -3,6 +3,7 @@ package com.geeksville.mesh.model
import android.content.Context
import android.content.SharedPreferences
import android.graphics.Bitmap
import android.net.Uri
import android.os.RemoteException
import android.util.Base64
import androidx.compose.Model
@ -17,24 +18,61 @@ import com.geeksville.mesh.ui.getInitials
import com.google.zxing.BarcodeFormat
import com.google.zxing.MultiFormatWriter
import com.journeyapps.barcodescanner.BarcodeEncoder
import java.net.MalformedURLException
@Model
data class Channel(
var name: String,
var modemConfig: ModemConfig
var modemConfig: ModemConfig,
var settings: MeshProtos.ChannelSettings? = null
) {
companion object {
// Placeholder when emulating
val emulated = Channel("Default", ModemConfig.Bw125Cr45Sf128)
const val prefix = "https://www.meshtastic.org/c/"
private const val base64Flags = Base64.URL_SAFE + Base64.NO_WRAP
private fun urlToSettings(url: Uri): MeshProtos.ChannelSettings {
val urlStr = url.toString()
val pathRegex = Regex("$prefix(.*)")
val (base64) = pathRegex.find(urlStr)?.destructured
?: throw MalformedURLException("Not a meshtastic URL")
val bytes = Base64.decode(base64, base64Flags)
return MeshProtos.ChannelSettings.parseFrom(bytes)
}
}
constructor(c: MeshProtos.ChannelSettings) : this(c.name, c.modemConfig) {
}
constructor(c: MeshProtos.ChannelSettings) : this(c.name, c.modemConfig, c)
constructor(url: Uri) : this(urlToSettings(url))
/// Can this channel be changed right now?
var editable = false
/// Return an URL that represents the current channel values
fun getChannelUrl(): String {
// If we have a valid radio config use it, othterwise use whatever we have saved in the prefs
val channelBytes = settings?.toByteArray() ?: ByteArray(0) // if unset just use empty
val enc = Base64.encodeToString(channelBytes, base64Flags)
return "$prefix$enc"
}
fun getChannelQR(): Bitmap {
val multiFormatWriter = MultiFormatWriter()
val bitMatrix =
multiFormatWriter.encode(getChannelUrl(), BarcodeFormat.QR_CODE, 192, 192);
val barcodeEncoder = BarcodeEncoder()
return barcodeEncoder.createBitmap(bitMatrix)
}
}
/**
* a nice readable description of modem configs
*/
@ -65,6 +103,9 @@ object UIState : Logging {
/// our activity will read this from prefs or set it to the empty string
var ownerName: String = "MrInIDE Ownername"
/// If the app was launched because we received a new channel intent, the Url will be here
var requestedChannelUrl: Uri? = null
/**
* Return the current channel info
* FIXME, we should sim channels at the MeshService level if we are running on an emulator,
@ -79,33 +120,6 @@ object UIState : Logging {
channel
}
/// 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
val radio = radioConfig.value
if (radio != null) {
val settings = radio.channelSettings
val channelBytes = settings.toByteArray()
val enc = Base64.encodeToString(channelBytes, Base64.URL_SAFE + Base64.NO_WRAP)
return "https://www.meshtastic.org/c/$enc"
} else {
return getPreferences(context).getString(
"owner",
"https://www.meshtastic.org/c/unset"
)!!
}
}
fun getChannelQR(context: Context): Bitmap {
val multiFormatWriter = MultiFormatWriter()
val bitMatrix =
multiFormatWriter.encode(getChannelUrl(context), BarcodeFormat.QR_CODE, 192, 192);
val barcodeEncoder = BarcodeEncoder()
return barcodeEncoder.createBitmap(bitMatrix)
}
fun getPreferences(context: Context): SharedPreferences =
context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE)
@ -114,7 +128,7 @@ object UIState : Logging {
radioConfig.value = c
getPreferences(context).edit(commit = true) {
this.putString("channel-url", getChannelUrl(context))
this.putString("channel-url", getChannel()!!.getChannelUrl())
}
}

View file

@ -15,7 +15,6 @@ 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
@ -43,7 +42,7 @@ fun ChannelContent(channel: Channel?) {
textStyle = typography.h4.copy(
color = palette.onSecondary.copy(alpha = 0.8f)
),
imeAction = ImeAction.Send,
imeAction = ImeAction.Done,
onImeActionPerformed = {
TODO()
}
@ -58,7 +57,7 @@ fun ChannelContent(channel: Channel?) {
// simulated qr code
// val image = imageResource(id = R.drawable.qrcode)
val image = AndroidImage(UIState.getChannelQR(context))
val image = AndroidImage(channel.getChannelQR())
ScaledImage(
image = image,
@ -98,7 +97,7 @@ fun ChannelContent(channel: Channel?) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, UIState.getChannelUrl(context))
putExtra(Intent.EXTRA_TEXT, channel.getChannelUrl())
putExtra(
Intent.EXTRA_TITLE,
"A URL for joining a Meshtastic mesh"