kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
WIP is a little better
rodzic
9491a74fc6
commit
5403b15044
|
@ -21,9 +21,9 @@ import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.ui.core.setContent
|
import androidx.ui.core.setContent
|
||||||
import androidx.ui.foundation.Text
|
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.geeksville.android.GeeksvilleApplication
|
||||||
import com.geeksville.android.Logging
|
import com.geeksville.android.Logging
|
||||||
import com.geeksville.android.ServiceClient
|
import com.geeksville.android.ServiceClient
|
||||||
import com.geeksville.mesh.model.MessagesState
|
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.TextMessage
|
||||||
import com.geeksville.mesh.model.UIState
|
import com.geeksville.mesh.model.UIState
|
||||||
import com.geeksville.mesh.service.*
|
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.Exceptions
|
||||||
import com.geeksville.util.exceptionReporter
|
import com.geeksville.util.exceptionReporter
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
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 {
|
Logging {
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? =
|
): View? =
|
||||||
setComposable(id, content)
|
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
|
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 {
|
override fun createFragment(position: Int): Fragment {
|
||||||
// Return a NEW fragment instance in createFragment(int)
|
// Return a NEW fragment instance in createFragment(int)
|
||||||
|
@ -155,9 +210,7 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
// Our object is just an integer :-P
|
// Our object is just an integer :-P
|
||||||
putInt(ARG_OBJECT, position + 1)
|
putInt(ARG_OBJECT, position + 1)
|
||||||
} */
|
} */
|
||||||
return ComposeFragment(position + 1) {
|
return tabInfos[position].content
|
||||||
Text("Jetpack Compose")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +308,11 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
|
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(this, "Error - this app requires bluetooth", Toast.LENGTH_LONG)
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"Error - this app requires bluetooth",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +346,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
val pager = findViewById<ViewPager2>(R.id.pager)
|
val pager = findViewById<ViewPager2>(R.id.pager)
|
||||||
pager.adapter = tabsAdapter
|
pager.adapter = tabsAdapter
|
||||||
TabLayoutMediator(tab_layout, pager) { tab, position ->
|
TabLayoutMediator(tab_layout, pager) { tab, position ->
|
||||||
tab.text = "OBJECT ${(position + 1)}"
|
tab.text = tabInfos[position].text
|
||||||
|
tab.icon = getDrawable(tabInfos[position].icon)
|
||||||
}.attach()
|
}.attach()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +381,11 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
/**
|
/**
|
||||||
* Dispatch incoming result to the correct fragment.
|
* 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)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
|
||||||
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
|
// 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() {
|
private fun registerMeshReceiver() {
|
||||||
logAssert(!receiverRegistered)
|
logAssert(!receiverRegistered)
|
||||||
|
@ -418,14 +481,17 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val meshServiceReceiver = object : BroadcastReceiver() {
|
private
|
||||||
|
val meshServiceReceiver = object : BroadcastReceiver() {
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) = exceptionReporter {
|
override fun onReceive(context: Context, intent: Intent) =
|
||||||
|
exceptionReporter {
|
||||||
debug("Received from mesh service $intent")
|
debug("Received from mesh service $intent")
|
||||||
|
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
MeshService.ACTION_NODE_CHANGE -> {
|
MeshService.ACTION_NODE_CHANGE -> {
|
||||||
val info: NodeInfo = intent.getParcelableExtra(EXTRA_NODEINFO)!!
|
val info: NodeInfo =
|
||||||
|
intent.getParcelableExtra(EXTRA_NODEINFO)!!
|
||||||
debug("UI nodechange $info")
|
debug("UI nodechange $info")
|
||||||
|
|
||||||
// We only care about nodes that have user info
|
// We only care about nodes that have user info
|
||||||
|
@ -436,15 +502,20 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
|
|
||||||
MeshService.ACTION_RECEIVED_DATA -> {
|
MeshService.ACTION_RECEIVED_DATA -> {
|
||||||
debug("TODO rxdata")
|
debug("TODO rxdata")
|
||||||
val sender = intent.getStringExtra(EXTRA_SENDER)!!
|
val sender =
|
||||||
val payload = intent.getByteArrayExtra(EXTRA_PAYLOAD)!!
|
intent.getStringExtra(EXTRA_SENDER)!!
|
||||||
|
val payload =
|
||||||
|
intent.getByteArrayExtra(EXTRA_PAYLOAD)!!
|
||||||
val typ = intent.getIntExtra(EXTRA_TYP, -1)
|
val typ = intent.getIntExtra(EXTRA_TYP, -1)
|
||||||
|
|
||||||
when (typ) {
|
when (typ) {
|
||||||
MeshProtos.Data.Type.CLEAR_TEXT_VALUE -> {
|
MeshProtos.Data.Type.CLEAR_TEXT_VALUE -> {
|
||||||
// FIXME - use the real time from the packet
|
// 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...
|
// 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))
|
val msg = TextMessage(
|
||||||
|
sender,
|
||||||
|
payload.toString(utf8)
|
||||||
|
)
|
||||||
|
|
||||||
MessagesState.addMessage(msg)
|
MessagesState.addMessage(msg)
|
||||||
}
|
}
|
||||||
|
@ -466,7 +537,9 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val mesh = object : ServiceClient<com.geeksville.mesh.IMeshService>({
|
private
|
||||||
|
val mesh = object :
|
||||||
|
ServiceClient<com.geeksville.mesh.IMeshService>({
|
||||||
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
|
com.geeksville.mesh.IMeshService.Stub.asInterface(it)
|
||||||
}) {
|
}) {
|
||||||
override fun onConnected(service: com.geeksville.mesh.IMeshService) {
|
override fun onConnected(service: com.geeksville.mesh.IMeshService) {
|
||||||
|
@ -476,7 +549,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
registerMeshReceiver()
|
registerMeshReceiver()
|
||||||
|
|
||||||
// We won't receive a notify for the initial state of connection, so we force an update here
|
// 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)
|
onMeshConnectionChanged(connectionState)
|
||||||
|
|
||||||
debug("connected to mesh service, isConnected=${UIState.isConnected.value}")
|
debug("connected to mesh service, isConnected=${UIState.isConnected.value}")
|
||||||
|
@ -522,7 +596,8 @@ class MainActivity : AppCompatActivity(), Logging,
|
||||||
|
|
||||||
bindMeshService()
|
bindMeshService()
|
||||||
|
|
||||||
val bonded = RadioInterfaceService.getBondedDeviceAddress(this) != null
|
val bonded =
|
||||||
|
RadioInterfaceService.getBondedDeviceAddress(this) != null
|
||||||
/* FIXME - not yet working
|
/* FIXME - not yet working
|
||||||
if (!bonded)
|
if (!bonded)
|
||||||
AppStatus.currentScreen = Screen.settings
|
AppStatus.currentScreen = Screen.settings
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
package com.geeksville.mesh.ui
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
import androidx.compose.Composable
|
|
||||||
import androidx.compose.onCommit
|
|
||||||
import com.geeksville.android.GeeksvilleApplication
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track compose screen visibility
|
* Track compose screen visibility
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
@Composable
|
@Composable
|
||||||
fun analyticsScreen(name: String) {
|
fun analyticsScreen(name: String) {
|
||||||
onCommit(AppStatus.currentScreen) {
|
onCommit(AppStatus.currentScreen) {
|
||||||
|
@ -16,4 +14,4 @@ fun analyticsScreen(name: String) {
|
||||||
GeeksvilleApplication.analytics.endScreenView()
|
GeeksvilleApplication.analytics.endScreenView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} */
|
|
@ -1,21 +1,6 @@
|
||||||
package com.geeksville.mesh.ui
|
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
|
@Composable
|
||||||
fun AppDrawer(
|
fun AppDrawer(
|
||||||
currentScreen: ScreenInfo,
|
currentScreen: ScreenInfo,
|
||||||
|
@ -111,4 +96,4 @@ fun previewDrawer() {
|
||||||
currentScreen = AppStatus.currentScreen,
|
currentScreen = AppStatus.currentScreen,
|
||||||
closeDrawer = { }
|
closeDrawer = { }
|
||||||
)
|
)
|
||||||
}
|
} */
|
|
@ -73,8 +73,8 @@ fun BTScanScreen() {
|
||||||
val bluetoothAdapter =
|
val bluetoothAdapter =
|
||||||
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
|
(context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
|
||||||
|
|
||||||
analyticsScreen(name = "settings")
|
// FIXME - remove onCommit now that we have a fragement to run in
|
||||||
onCommit(AppStatus.currentScreen) {
|
onCommit() {
|
||||||
ScanState.debug("BTScan component active")
|
ScanState.debug("BTScan component active")
|
||||||
ScanUIState.selectedMacAddr = RadioInterfaceService.getBondedDeviceAddress(context)
|
ScanUIState.selectedMacAddr = RadioInterfaceService.getBondedDeviceAddress(context)
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,6 @@ object ChannelLog : Logging
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChannelContent(channel: Channel?) {
|
fun ChannelContent(channel: Channel?) {
|
||||||
analyticsScreen(name = "channel")
|
|
||||||
|
|
||||||
val typography = MaterialTheme.typography
|
val typography = MaterialTheme.typography
|
||||||
val context = ContextAmbient.current
|
val context = ContextAmbient.current
|
||||||
|
|
|
@ -75,11 +75,10 @@ private val mapLifecycleCallbacks = object : Application.ActivityLifecycleCallba
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MapContent() {
|
fun MapContent() {
|
||||||
analyticsScreen(name = "map")
|
|
||||||
|
|
||||||
val context = ContextAmbient.current
|
val context = ContextAmbient.current
|
||||||
|
|
||||||
onCommit(AppStatus.currentScreen) {
|
// FIXME - remove onCommit
|
||||||
|
onCommit() {
|
||||||
onDispose {
|
onDispose {
|
||||||
// We no longer care about activity lifecycle
|
// We no longer care about activity lifecycle
|
||||||
(context.applicationContext as Application).unregisterActivityLifecycleCallbacks(
|
(context.applicationContext as Application).unregisterActivityLifecycleCallbacks(
|
||||||
|
|
|
@ -1,19 +1,14 @@
|
||||||
package com.geeksville.mesh.ui
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
import androidx.compose.Composable
|
import androidx.ui.material.lightColorPalette
|
||||||
import androidx.compose.state
|
|
||||||
import androidx.ui.foundation.Text
|
|
||||||
import androidx.ui.material.*
|
|
||||||
import androidx.ui.tooling.preview.Preview
|
|
||||||
import com.geeksville.android.Logging
|
import com.geeksville.android.Logging
|
||||||
import com.geeksville.mesh.R
|
|
||||||
import com.geeksville.mesh.model.UIState
|
|
||||||
|
|
||||||
|
|
||||||
object UILog : Logging
|
object UILog : Logging
|
||||||
|
|
||||||
val palette = lightColorPalette() // darkColorPalette()
|
val palette = lightColorPalette() // darkColorPalette()
|
||||||
|
|
||||||
|
/*
|
||||||
@Composable
|
@Composable
|
||||||
fun MeshApp() {
|
fun MeshApp() {
|
||||||
val (drawerState, onDrawerStateChange) = state { DrawerState.Closed }
|
val (drawerState, onDrawerStateChange) = state { DrawerState.Closed }
|
||||||
|
@ -73,3 +68,4 @@ private fun AppContent(openDrawer: () -> Unit) {
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
*/
|
|
@ -67,8 +67,6 @@ fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MessagesContent() {
|
fun MessagesContent() {
|
||||||
analyticsScreen(name = "messages")
|
|
||||||
|
|
||||||
Column(modifier = LayoutSize.Fill) {
|
Column(modifier = LayoutSize.Fill) {
|
||||||
|
|
||||||
val sidePad = 8.dp
|
val sidePad = 8.dp
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.geeksville.mesh.ui
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
import androidx.compose.Model
|
/*
|
||||||
import com.geeksville.mesh.R
|
|
||||||
|
|
||||||
|
|
||||||
data class ScreenInfo(val icon: Int, val label: String)
|
data class ScreenInfo(val icon: Int, val label: String)
|
||||||
|
|
||||||
// defines the screens we have in the app
|
// defines the screens we have in the app
|
||||||
|
@ -28,3 +25,4 @@ object AppStatus {
|
||||||
fun navigateTo(destination: ScreenInfo) {
|
fun navigateTo(destination: ScreenInfo) {
|
||||||
AppStatus.currentScreen = destination
|
AppStatus.currentScreen = destination
|
||||||
}
|
}
|
||||||
|
*/
|
|
@ -27,8 +27,6 @@ fun getInitials(name: String): String {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UsersContent() {
|
fun UsersContent() {
|
||||||
analyticsScreen(name = "users")
|
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
Row {
|
Row {
|
||||||
fun connected() = UIState.isConnected.value != MeshService.ConnectionState.DISCONNECTED
|
fun connected() = UIState.isConnected.value != MeshService.ConnectionState.DISCONNECTED
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
Screen.channel -> ChannelContent(UIState.getChannel())
|
Screen.channel -> ChannelContent(UIState.getChannel())
|
||||||
Screen.map -> MapContent() -->
|
Screen.map -> MapContent() -->
|
||||||
|
|
||||||
|
/--
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabItem
|
<com.google.android.material.tabs.TabItem
|
||||||
android:icon="@drawable/ic_twotone_message_24"
|
android:icon="@drawable/ic_twotone_message_24"
|
||||||
android:text="Messages"
|
android:text="Messages"
|
||||||
|
@ -43,6 +45,7 @@
|
||||||
android:text="Settings"
|
android:text="Settings"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content" />
|
android:layout_width="wrap_content" />
|
||||||
|
-->
|
||||||
|
|
||||||
</com.google.android.material.tabs.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue