Feature: Jump to node info from message (#844)

* Highlight the node in the node list tab when the user taps on the node chip in messages

* Represent main tabs as enum for more reliable referencing

* Extract tab labels to string resources for easier translation
Annotate resource IDs with their corresponding Android types

* Index off nodes actually in the adapter since they are sorted

* Update viewmodel when tab changes to prevent jumping to other tabs in onResume

* Mark strings as non-translatable for now
This commit is contained in:
Davis 2024-02-13 14:32:52 -07:00 committed by GitHub
parent a88ffbc0fb
commit 2bfda9784f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 167 additions and 37 deletions

View file

@ -39,12 +39,12 @@ import com.geeksville.mesh.model.toChannelSet
import com.geeksville.mesh.repository.radio.BluetoothInterface
import com.geeksville.mesh.service.*
import com.geeksville.mesh.ui.*
import com.geeksville.mesh.ui.map.MapFragment
import com.geeksville.mesh.util.Exceptions
import com.geeksville.mesh.util.LanguageUtils
import com.geeksville.mesh.util.getPackageInfoCompat
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
@ -140,40 +140,9 @@ class MainActivity : AppCompatActivity(), Logging {
}
}
data class TabInfo(val text: String, val icon: Int, val content: Fragment)
private val tabInfos = arrayOf(
TabInfo(
"Messages",
R.drawable.ic_twotone_message_24,
ContactsFragment()
),
TabInfo(
"Users",
R.drawable.ic_twotone_people_24,
UsersFragment()
),
TabInfo(
"Map",
R.drawable.ic_twotone_map_24,
MapFragment()
),
TabInfo(
"Channel",
R.drawable.ic_twotone_contactless_24,
ChannelFragment()
),
TabInfo(
"Settings",
R.drawable.ic_twotone_settings_applications_24,
SettingsFragment()
)
)
private val tabsAdapter = object : FragmentStateAdapter(supportFragmentManager, lifecycle) {
override fun getItemCount(): Int = tabInfos.size
override fun createFragment(position: Int): Fragment = tabInfos[position].content
override fun getItemCount(): Int = MainTab.entries.size
override fun createFragment(position: Int): Fragment = MainTab.entries[position].content
}
override fun onCreate(savedInstanceState: Bundle?) {
@ -209,9 +178,18 @@ class MainActivity : AppCompatActivity(), Logging {
// pager.offscreenPageLimit = 0 // Don't keep any offscreen pages around, because we want to make sure our bluetooth scanning stops
TabLayoutMediator(binding.tabLayout, binding.pager, false, false) { tab, position ->
// tab.text = tabInfos[position].text // I think it looks better with icons only
tab.icon = ContextCompat.getDrawable(this, tabInfos[position].icon)
tab.icon = ContextCompat.getDrawable(this, MainTab.entries[position].icon)
}.attach()
binding.tabLayout.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
val mainTab = MainTab.entries[tab?.position ?: 0]
model.setCurrentTab(mainTab)
}
override fun onTabUnselected(tab: TabLayout.Tab?) { }
override fun onTabReselected(tab: TabLayout.Tab?) { }
})
// Handle any intent
handleIntent(intent)
}
@ -514,6 +492,7 @@ class MainActivity : AppCompatActivity(), Logging {
bluetoothViewModel.enabled.removeObservers(this)
model.requestChannelUrl.removeObservers(this)
model.snackbarText.removeObservers(this)
model.currentTab.removeObservers(this)
super.onStop()
}
@ -557,6 +536,10 @@ class MainActivity : AppCompatActivity(), Logging {
if (text != null) model.clearSnackbarText()
}
model.currentTab.observe(this) {
binding.tabLayout.getTabAt(it.ordinal)?.select()
}
try {
bindMeshService()
} catch (ex: BindFailedException) {