diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index 0e0b1dec..5653eccf 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -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) { + /* + - override fun getItemCount(): Int = 2 + /-- + + + --> + */ + 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(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.Stub.asInterface(it) - }) { + private + val mesh = object : + ServiceClient({ + 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 diff --git a/app/src/main/java/com/geeksville/mesh/ui/Analytics.kt b/app/src/main/java/com/geeksville/mesh/ui/Analytics.kt index 57fedcb3..96e87da3 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Analytics.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Analytics.kt @@ -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() } } -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/AppDrawer.kt b/app/src/main/java/com/geeksville/mesh/ui/AppDrawer.kt index 4de02356..c8e45ebd 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/AppDrawer.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/AppDrawer.kt @@ -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 = { } ) -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt index 0cb0de09..1e9a0b32 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt @@ -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) diff --git a/app/src/main/java/com/geeksville/mesh/ui/Channel.kt b/app/src/main/java/com/geeksville/mesh/ui/Channel.kt index d8b01d8d..168dfd77 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Channel.kt @@ -23,7 +23,6 @@ object ChannelLog : Logging @Composable fun ChannelContent(channel: Channel?) { - analyticsScreen(name = "channel") val typography = MaterialTheme.typography val context = ContextAmbient.current diff --git a/app/src/main/java/com/geeksville/mesh/ui/Map.kt b/app/src/main/java/com/geeksville/mesh/ui/Map.kt index 1ebc95b8..08b4e6f5 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Map.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Map.kt @@ -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( diff --git a/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt b/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt index 2641ef5c..8958d63b 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt @@ -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) { } //} } +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Messages.kt b/app/src/main/java/com/geeksville/mesh/ui/Messages.kt index 75e5d298..ba71fa36 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Messages.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Messages.kt @@ -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 diff --git a/app/src/main/java/com/geeksville/mesh/ui/Status.kt b/app/src/main/java/com/geeksville/mesh/ui/Status.kt index dbe4bb64..c20355c3 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Status.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Status.kt @@ -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 } +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Users.kt b/app/src/main/java/com/geeksville/mesh/ui/Users.kt index 08d49e99..10abb089 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Users.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Users.kt @@ -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 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index e7bab3fe..ae63bf09 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -32,6 +32,8 @@ Screen.channel -> ChannelContent(UIState.getChannel()) Screen.map -> MapContent() --> + /-- + + -->