WIP is a little better

pull/12/head
geeksville 2020-04-07 10:40:01 -07:00
rodzic 9491a74fc6
commit 5403b15044
11 zmienionych plików z 156 dodań i 107 usunięć

Wyświetl plik

@ -21,9 +21,9 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.ui.core.setContent
import androidx.ui.foundation.Text
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.ServiceClient
import com.geeksville.mesh.model.MessagesState
@ -31,7 +31,7 @@ import com.geeksville.mesh.model.NodeDB
import com.geeksville.mesh.model.TextMessage
import com.geeksville.mesh.model.UIState
import com.geeksville.mesh.service.*
import com.geeksville.mesh.ui.ScanState
import com.geeksville.mesh.ui.*
import com.geeksville.util.Exceptions
import com.geeksville.util.exceptionReporter
import com.google.android.gms.auth.api.signin.GoogleSignIn
@ -109,23 +109,31 @@ fun androidx.fragment.app.Fragment.setComposable(
}
}
class ComposeFragment(id: Int, private val content: @Composable() () -> Unit) : Fragment(),
/**
* A fragment that represents a current 'screen' in our app.
*
* Useful for tracking analytics
*/
open class ScreenFragment(private val screenName: String) : Fragment() {
override fun onResume() {
super.onResume()
GeeksvilleApplication.analytics.sendScreenView(screenName)
}
override fun onPause() {
GeeksvilleApplication.analytics.endScreenView()
super.onPause()
}
}
class ComposeFragment(screenName: String, id: Int, private val content: @Composable() () -> Unit) :
ScreenFragment(screenName),
Logging {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? =
setComposable(id, content)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
debug("view w=${view.width}, h=${view.height}")
}
override fun onStart() {
super.onStart()
debug("view w=${view?.width}, h=${view?.height}")
}
}
@ -144,9 +152,56 @@ class MainActivity : AppCompatActivity(), Logging,
bluetoothManager.adapter
}
private val tabsAdapter = object : FragmentStateAdapter(this) {
/*
<!-- Screen.messages -> MessagesContent()
Screen.settings -> SettingsContent()
Screen.users -> UsersContent()
Screen.channel -> ChannelContent(UIState.getChannel())
Screen.map -> MapContent() -->
override fun getItemCount(): Int = 2
/--
<com.google.android.material.tabs.TabItem
android:icon="@drawable/ic_twotone_message_24"
android:text="Messages"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
<com.google.android.material.tabs.TabItem
android:icon="@drawable/ic_twotone_settings_applications_24"
android:text="Settings"
android:layout_height="wrap_content"
android:layout_width="wrap_content" /> -->
*/
data class TabInfo(val text: String, val icon: Int, val content: Fragment)
// private val tabIndexes = generateSequence(0) { it + 1 } FIXME, instead do withIndex or zip? to get the ids below, also stop duplicating strings
private val tabInfos = arrayOf(
TabInfo(
"Messages",
R.drawable.ic_twotone_message_24,
ComposeFragment("Messages", 1) { MessagesContent() }),
TabInfo(
"Settings",
R.drawable.ic_twotone_settings_applications_24,
ComposeFragment("Settings", 2) { SettingsContent() }),
TabInfo(
"Users",
R.drawable.ic_twotone_people_24,
ComposeFragment("Users", 3) { UsersContent() }),
TabInfo(
"Channel",
R.drawable.ic_twotone_contactless_24,
ComposeFragment("Channel", 4) { ChannelContent(UIState.getChannel()) }),
TabInfo(
"Map",
R.drawable.ic_twotone_map_24,
ComposeFragment("Map", 5) { MapContent() })
)
private
val tabsAdapter = object : FragmentStateAdapter(this) {
override fun getItemCount(): Int = tabInfos.size
override fun createFragment(position: Int): Fragment {
// Return a NEW fragment instance in createFragment(int)
@ -155,9 +210,7 @@ class MainActivity : AppCompatActivity(), Logging,
// Our object is just an integer :-P
putInt(ARG_OBJECT, position + 1)
} */
return ComposeFragment(position + 1) {
Text("Jetpack Compose")
}
return tabInfos[position].content
}
}
@ -255,7 +308,11 @@ class MainActivity : AppCompatActivity(), Logging,
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
}
} else {
Toast.makeText(this, "Error - this app requires bluetooth", Toast.LENGTH_LONG)
Toast.makeText(
this,
"Error - this app requires bluetooth",
Toast.LENGTH_LONG
)
.show()
}
@ -289,7 +346,8 @@ class MainActivity : AppCompatActivity(), Logging,
val pager = findViewById<ViewPager2>(R.id.pager)
pager.adapter = tabsAdapter
TabLayoutMediator(tab_layout, pager) { tab, position ->
tab.text = "OBJECT ${(position + 1)}"
tab.text = tabInfos[position].text
tab.icon = getDrawable(tabInfos[position].icon)
}.attach()
}
@ -323,7 +381,11 @@ class MainActivity : AppCompatActivity(), Logging,
/**
* Dispatch incoming result to the correct fragment.
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
@ -350,7 +412,8 @@ class MainActivity : AppCompatActivity(), Logging,
} */
}
private var receiverRegistered = false
private
var receiverRegistered = false
private fun registerMeshReceiver() {
logAssert(!receiverRegistered)
@ -418,57 +481,67 @@ class MainActivity : AppCompatActivity(), Logging,
}
}
private val meshServiceReceiver = object : BroadcastReceiver() {
private
val meshServiceReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) = exceptionReporter {
debug("Received from mesh service $intent")
override fun onReceive(context: Context, intent: Intent) =
exceptionReporter {
debug("Received from mesh service $intent")
when (intent.action) {
MeshService.ACTION_NODE_CHANGE -> {
val info: NodeInfo = intent.getParcelableExtra(EXTRA_NODEINFO)!!
debug("UI nodechange $info")
when (intent.action) {
MeshService.ACTION_NODE_CHANGE -> {
val info: NodeInfo =
intent.getParcelableExtra(EXTRA_NODEINFO)!!
debug("UI nodechange $info")
// We only care about nodes that have user info
info.user?.id?.let {
NodeDB.nodes[it] = info
}
}
MeshService.ACTION_RECEIVED_DATA -> {
debug("TODO rxdata")
val sender = intent.getStringExtra(EXTRA_SENDER)!!
val payload = intent.getByteArrayExtra(EXTRA_PAYLOAD)!!
val typ = intent.getIntExtra(EXTRA_TYP, -1)
when (typ) {
MeshProtos.Data.Type.CLEAR_TEXT_VALUE -> {
// FIXME - use the real time from the packet
// FIXME - don't just slam in a new list each time, it probably causes extra drawing. Figure out how to be Compose smarter...
val msg = TextMessage(sender, payload.toString(utf8))
MessagesState.addMessage(msg)
// We only care about nodes that have user info
info.user?.id?.let {
NodeDB.nodes[it] = info
}
else -> TODO()
}
MeshService.ACTION_RECEIVED_DATA -> {
debug("TODO rxdata")
val sender =
intent.getStringExtra(EXTRA_SENDER)!!
val payload =
intent.getByteArrayExtra(EXTRA_PAYLOAD)!!
val typ = intent.getIntExtra(EXTRA_TYP, -1)
when (typ) {
MeshProtos.Data.Type.CLEAR_TEXT_VALUE -> {
// FIXME - use the real time from the packet
// FIXME - don't just slam in a new list each time, it probably causes extra drawing. Figure out how to be Compose smarter...
val msg = TextMessage(
sender,
payload.toString(utf8)
)
MessagesState.addMessage(msg)
}
else -> TODO()
}
}
MeshService.ACTION_MESH_CONNECTED -> {
val connected =
MeshService.ConnectionState.valueOf(
intent.getStringExtra(
EXTRA_CONNECTED
)!!
)
onMeshConnectionChanged(connected)
}
else -> TODO()
}
MeshService.ACTION_MESH_CONNECTED -> {
val connected =
MeshService.ConnectionState.valueOf(
intent.getStringExtra(
EXTRA_CONNECTED
)!!
)
onMeshConnectionChanged(connected)
}
else -> TODO()
}
}
}
private val mesh = object : ServiceClient<com.geeksville.mesh.IMeshService>({
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
}) {
private
val mesh = object :
ServiceClient<com.geeksville.mesh.IMeshService>({
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
}) {
override fun onConnected(service: com.geeksville.mesh.IMeshService) {
UIState.meshService = service
@ -476,7 +549,8 @@ class MainActivity : AppCompatActivity(), Logging,
registerMeshReceiver()
// We won't receive a notify for the initial state of connection, so we force an update here
val connectionState = MeshService.ConnectionState.valueOf(service.connectionState())
val connectionState =
MeshService.ConnectionState.valueOf(service.connectionState())
onMeshConnectionChanged(connectionState)
debug("connected to mesh service, isConnected=${UIState.isConnected.value}")
@ -522,7 +596,8 @@ class MainActivity : AppCompatActivity(), Logging,
bindMeshService()
val bonded = RadioInterfaceService.getBondedDeviceAddress(this) != null
val bonded =
RadioInterfaceService.getBondedDeviceAddress(this) != null
/* FIXME - not yet working
if (!bonded)
AppStatus.currentScreen = Screen.settings

Wyświetl plik

@ -1,12 +1,10 @@
package com.geeksville.mesh.ui
import androidx.compose.Composable
import androidx.compose.onCommit
import com.geeksville.android.GeeksvilleApplication
/**
* Track compose screen visibility
*/
/*
@Composable
fun analyticsScreen(name: String) {
onCommit(AppStatus.currentScreen) {
@ -16,4 +14,4 @@ fun analyticsScreen(name: String) {
GeeksvilleApplication.analytics.endScreenView()
}
}
}
} */

Wyświetl plik

@ -1,21 +1,6 @@
package com.geeksville.mesh.ui
import androidx.annotation.DrawableRes
import androidx.compose.Composable
import androidx.ui.core.Modifier
import androidx.ui.foundation.Text
import androidx.ui.foundation.shape.corner.RoundedCornerShape
import androidx.ui.graphics.Color
import androidx.ui.layout.*
import androidx.ui.material.Divider
import androidx.ui.material.MaterialTheme
import androidx.ui.material.Surface
import androidx.ui.material.TextButton
import androidx.ui.tooling.preview.Preview
import androidx.ui.unit.dp
import com.geeksville.mesh.R
/*
@Composable
fun AppDrawer(
currentScreen: ScreenInfo,
@ -111,4 +96,4 @@ fun previewDrawer() {
currentScreen = AppStatus.currentScreen,
closeDrawer = { }
)
}
} */

Wyświetl plik

@ -73,8 +73,8 @@ fun BTScanScreen() {
val bluetoothAdapter =
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
analyticsScreen(name = "settings")
onCommit(AppStatus.currentScreen) {
// FIXME - remove onCommit now that we have a fragement to run in
onCommit() {
ScanState.debug("BTScan component active")
ScanUIState.selectedMacAddr = RadioInterfaceService.getBondedDeviceAddress(context)

Wyświetl plik

@ -23,7 +23,6 @@ object ChannelLog : Logging
@Composable
fun ChannelContent(channel: Channel?) {
analyticsScreen(name = "channel")
val typography = MaterialTheme.typography
val context = ContextAmbient.current

Wyświetl plik

@ -75,11 +75,10 @@ private val mapLifecycleCallbacks = object : Application.ActivityLifecycleCallba
@Composable
fun MapContent() {
analyticsScreen(name = "map")
val context = ContextAmbient.current
onCommit(AppStatus.currentScreen) {
// FIXME - remove onCommit
onCommit() {
onDispose {
// We no longer care about activity lifecycle
(context.applicationContext as Application).unregisterActivityLifecycleCallbacks(

Wyświetl plik

@ -1,19 +1,14 @@
package com.geeksville.mesh.ui
import androidx.compose.Composable
import androidx.compose.state
import androidx.ui.foundation.Text
import androidx.ui.material.*
import androidx.ui.tooling.preview.Preview
import androidx.ui.material.lightColorPalette
import com.geeksville.android.Logging
import com.geeksville.mesh.R
import com.geeksville.mesh.model.UIState
object UILog : Logging
val palette = lightColorPalette() // darkColorPalette()
/*
@Composable
fun MeshApp() {
val (drawerState, onDrawerStateChange) = state { DrawerState.Closed }
@ -73,3 +68,4 @@ private fun AppContent(openDrawer: () -> Unit) {
}
//}
}
*/

Wyświetl plik

@ -67,8 +67,6 @@ fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) {
@Composable
fun MessagesContent() {
analyticsScreen(name = "messages")
Column(modifier = LayoutSize.Fill) {
val sidePad = 8.dp

Wyświetl plik

@ -1,9 +1,6 @@
package com.geeksville.mesh.ui
import androidx.compose.Model
import com.geeksville.mesh.R
/*
data class ScreenInfo(val icon: Int, val label: String)
// defines the screens we have in the app
@ -28,3 +25,4 @@ object AppStatus {
fun navigateTo(destination: ScreenInfo) {
AppStatus.currentScreen = destination
}
*/

Wyświetl plik

@ -27,8 +27,6 @@ fun getInitials(name: String): String {
@Composable
fun UsersContent() {
analyticsScreen(name = "users")
Column {
Row {
fun connected() = UIState.isConnected.value != MeshService.ConnectionState.DISCONNECTED

Wyświetl plik

@ -32,6 +32,8 @@
Screen.channel -> ChannelContent(UIState.getChannel())
Screen.map -> MapContent() -->
/--
<com.google.android.material.tabs.TabItem
android:icon="@drawable/ic_twotone_message_24"
android:text="Messages"
@ -43,6 +45,7 @@
android:text="Settings"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
-->
</com.google.android.material.tabs.TabLayout>