Added BottomAppBar to several fragments, various ui changes

This commit is contained in:
Arty Bishop committed 2022-02-19 12:10:30 +00:00
1 parent 64b5010a44
commit bdc0000476
61 files changed
+626 -390

No files matched your search

@@ -24,8 +24,6 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.ActivityMainBinding
import dagger.hilt.android.AndroidEntryPoint
@@ -43,14 +41,14 @@ class MainActivity : AppCompatActivity() {
val binding = ActivityMainBinding.inflate(layoutInflater)
val host = supportFragmentManager.findFragmentById(R.id.navigation_host) as NavHostFragment
setContentView(binding.root)
binding.navigationBar.apply {
setupWithNavController(host.navController)
setOnItemSelectedListener { item ->
NavigationUI.onNavDestinationSelected(item, host.navController)
host.navController.popBackStack(item.itemId, inclusive = false)
true
}
}
// binding.navigationBar.apply {
// setupWithNavController(host.navController)
// setOnItemSelectedListener { item ->
// NavigationUI.onNavDestinationSelected(item, host.navController)
// host.navController.popBackStack(item.itemId, inclusive = false)
// true
// }
// }
mainViewModel.calculatePasses()
}
}
@@ -32,6 +32,7 @@ import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.presentation.setNavResult
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -59,11 +60,15 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) {
addItemDecoration(itemDecoration)
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
}
entriesBack.setOnClickListener { findNavController().navigateUp() }
entriesBackBtn.setOnClickListener { findNavController().navigateUp() }
entriesSearch.doOnTextChanged { text, _, _, _ -> viewModel.setQuery(text.toString()) }
entriesMode.setOnClickListener { showModesDialog() }
entriesSelectAll.setOnClickListener { viewModel.selectCurrentItems() }
entriesAccept.setOnClickListener { viewModel.saveSelection() }
entriesModesBtn.setOnClickListener { showModesDialog() }
entriesSelectBtn.setOnClickListener { viewModel.selectCurrentItems(true) }
entriesClearBtn.setOnClickListener { viewModel.selectCurrentItems(false) }
entriesAcceptBtn.setOnClickListener {
setNavResult("selection", viewModel.saveSelection())
findNavController().popBackStack()
}
}
viewModel.satData.observe(viewLifecycleOwner) { satData ->
handleSatData(satData, binding, adapter)
@@ -41,13 +41,13 @@ class EntriesViewModel @Inject constructor(
private val itemsWithQuery = currentQuery.switchMap { query ->
itemsWithModes.map { items -> filterByQuery(items, query) }
}
private var shouldSelectAll = true
// private var shouldSelectAll = true
val satData = itemsWithQuery.map { items -> DataState.Success(items) }
fun selectCurrentItems() {
fun selectCurrentItems(selectAll: Boolean) {
itemsWithQuery.value?.let { itemsWithQuery ->
updateSelection(itemsWithQuery.map { item -> item.catnum }, shouldSelectAll)
shouldSelectAll = shouldSelectAll.not()
updateSelection(itemsWithQuery.map { item -> item.catnum }, selectAll)
// shouldSelectAll = shouldSelectAll.not()
}
}
@@ -61,15 +61,16 @@ class EntriesViewModel @Inject constructor(
}
fun setQuery(query: String) {
shouldSelectAll = true
// shouldSelectAll = true
currentQuery.value = query
}
fun saveSelection() {
itemsFromRepo.value?.let { itemsAll ->
fun saveSelection(): List<Int> {
return itemsFromRepo.value?.let { itemsAll ->
val filteredItems = itemsAll.filter { item -> item.isSelected }
repository.setEntriesSelection(filteredItems.map { item -> item.catnum })
}
// repository.setEntriesSelection(filteredItems.map { item -> item.catnum })
filteredItems.map { item -> item.catnum }
} ?: emptyList()
}
override fun updateSelection(catNums: List<Int>, isSelected: Boolean) {
@@ -92,9 +92,9 @@ class MapFragment : Fragment(R.layout.fragment_map) {
// add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons
overlays.addAll(Array(4) { FolderOverlay() })
}
mapBack.setOnClickListener { findNavController().navigateUp() }
mapBtnPrev.setOnClickListener { viewModel.scrollSelection(true) }
mapBtnNext.setOnClickListener { viewModel.scrollSelection(false) }
mapBackBtn.setOnClickListener { findNavController().navigateUp() }
mapPrevBtn.setOnClickListener { viewModel.scrollSelection(true) }
mapNextBtn.setOnClickListener { viewModel.scrollSelection(false) }
}
}
@@ -24,6 +24,7 @@ import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.SimpleItemAnimator
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.FragmentPassesBinding
@@ -51,59 +52,59 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
val layoutManager = LinearLayoutManager(context)
val itemDecoration = DividerItemDecoration(context, layoutManager.orientation)
binding.run {
passesList.apply {
passesRecycler.apply {
setHasFixedSize(true)
this.adapter = adapter
this.layoutManager = layoutManager
addItemDecoration(itemDecoration)
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
if (dy > 0 && passesFab.visibility == View.VISIBLE) passesFab.hide()
else if (dy < 0 && passesFab.visibility != View.VISIBLE) passesFab.show()
}
})
}
passesSwipe.apply {
setColorSchemeResources(R.color.surfaceToolbar)
setProgressBackgroundColorSchemeResource(R.color.themeAccent)
setOnRefreshListener { passesViewModel.forceCalculation() }
}
passesFilter.setOnClickListener { navigateToPassPrefs() }
passesSettings.setOnClickListener { navigateToSettings() }
passesRefreshBtn.setOnClickListener { refreshPasses() }
passesMapBtn.setOnClickListener { navigateToMap() }
passesFilterBtn.setOnClickListener { navigateToPassPrefs() }
passesFab.setOnClickListener { navigateToEntries() }
passesSettingsBtn.setOnClickListener { navigateToSettings() }
}
passesViewModel.passes.observe(viewLifecycleOwner) { passesResult ->
handleNewPasses(passesResult, adapter, binding)
handleNewPasses(passesResult, adapter)
}
getNavResult<Pair<Int, Double>>(R.id.nav_passes, "prefs") { prefs ->
passesViewModel.saveCalculationPrefs(prefs.first, prefs.second)
passesViewModel.forceCalculation(prefs.first, prefs.second)
}
getNavResult<List<Int>>(R.id.nav_passes, "selection") { selection ->
passesViewModel.saveSelectionAndRecalc(selection)
}
}
private fun handleNewPasses(
dataState: DataState<List<SatPass>>,
passesAdapter: PassesAdapter,
binding: FragmentPassesBinding
) {
when (dataState) {
private fun handleNewPasses(state: DataState<List<SatPass>>, adapter: PassesAdapter) {
when (state) {
is DataState.Success -> {
passesAdapter.submitList(dataState.data)
adapter.submitList(state.data)
binding.apply {
passesSwipe.isRefreshing = false
passesList.visibility = View.VISIBLE
passesError.visibility = View.INVISIBLE
passesRecycler.visibility = View.VISIBLE
passesErrorMsg.visibility = View.INVISIBLE
}
tickMainTimer(dataState.data, binding)
tickMainTimer(state.data, binding)
}
is DataState.Loading -> {
binding.apply {
passesTimer.text = 0L.toTimerString()
passesSwipe.isRefreshing = true
passesList.visibility = View.INVISIBLE
passesError.visibility = View.INVISIBLE
passesRecycler.visibility = View.INVISIBLE
passesErrorMsg.visibility = View.INVISIBLE
}
}
else -> {
binding.apply {
passesTimer.text = 0L.toTimerString()
passesSwipe.isRefreshing = false
passesList.visibility = View.INVISIBLE
passesError.visibility = View.VISIBLE
passesRecycler.visibility = View.INVISIBLE
passesErrorMsg.visibility = View.VISIBLE
}
}
}
@@ -126,11 +127,25 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC
}
}
private fun refreshPasses() {
passesViewModel.forceCalculation()
}
private fun navigateToMap() {
val direction = PassesFragmentDirections.actionGlobalMapFragment()
findNavController().navigate(direction)
}
private fun navigateToPassPrefs() {
val direction = PassesFragmentDirections.actionPassesToPassPrefs()
findNavController().navigate(direction)
}
private fun navigateToEntries() {
val direction = PassesFragmentDirections.actionGlobalEntriesFragment()
findNavController().navigate(direction)
}
private fun navigateToSettings() {
val direction = PassesFragmentDirections.actionGlobalSettingsFragment()
findNavController().navigate(direction)
@@ -57,6 +57,13 @@ class PassesViewModel @Inject constructor(
}
}
fun saveSelectionAndRecalc(selection: List<Int>) {
viewModelScope.launch {
repository.setEntriesSelection(selection)
forceCalculation()
}
}
fun forceCalculation(
hoursAhead: Int = settings.getHoursAhead(),
minElevation: Double = settings.getMinElevation(),
@@ -53,7 +53,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
private fun setupViews() {
val context = requireContext()
val adapter = RadiosAdapter()
val adapter = RadioAdapter()
val layoutManager = LinearLayoutManager(context)
val itemDecoration = DividerItemDecoration(context, layoutManager.orientation)
binding.run {
@@ -68,7 +68,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
}
}
private fun setupObservers(radiosAdapter: RadiosAdapter) {
private fun setupObservers(radioAdapter: RadioAdapter) {
viewModel.getPass(args.catNum, args.aosTime).observe(viewLifecycleOwner) { pass ->
radarView = RadarView(requireContext()).apply {
setShowAim(preferences.getUseCompass())
@@ -82,7 +82,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
}
viewModel.transmitters.observe(viewLifecycleOwner) { list ->
if (list.isNotEmpty()) {
radiosAdapter.submitList(list)
radioAdapter.submitList(list)
binding.radarRecyclerMsg.text = getString(R.string.trans_data)
} else {
binding.radarRecyclerMsg.text = getString(R.string.trans_no_data)
@@ -23,11 +23,11 @@ import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.ItemTransBinding
import com.rtbishop.look4sat.databinding.ItemRadioBinding
import com.rtbishop.look4sat.domain.model.SatRadio
import java.util.*
class RadiosAdapter : RecyclerView.Adapter<RadiosAdapter.TransHolder>() {
class RadioAdapter : RecyclerView.Adapter<RadioAdapter.TransHolder>() {
private val diffCallback = object : DiffUtil.ItemCallback<SatRadio>() {
override fun areItemsTheSame(oldItem: SatRadio, newItem: SatRadio): Boolean {
@@ -40,9 +40,7 @@ class RadiosAdapter : RecyclerView.Adapter<RadiosAdapter.TransHolder>() {
}
private val differ = AsyncListDiffer(this, diffCallback)
fun submitList(radios: List<SatRadio>) {
differ.submitList(radios)
}
fun submitList(items: List<SatRadio>) = differ.submitList(items)
override fun getItemCount() = differ.currentList.size
@@ -54,56 +52,51 @@ class RadiosAdapter : RecyclerView.Adapter<RadiosAdapter.TransHolder>() {
holder.bind(differ.currentList[position])
}
class TransHolder private constructor(private val binding: ItemTransBinding) :
class TransHolder private constructor(private val binding: ItemRadioBinding) :
RecyclerView.ViewHolder(binding.root) {
private val divider = 1000000f
private val strNo = itemView.context.getString(R.string.no)
private val strYes = itemView.context.getString(R.string.yes)
private val stringYes = itemView.context.getString(R.string.yes)
private val stringNo = itemView.context.getString(R.string.no)
private val link = itemView.context.getString(R.string.trans_link_low)
private val linkNull = itemView.context.getString(R.string.trans_no_link)
private val mode = itemView.context.getString(R.string.trans_mode)
private val formatLink = itemView.context.getString(R.string.trans_link_low)
private val formatLinkNull = itemView.context.getString(R.string.trans_no_link)
private val isInverted = itemView.context.getString(R.string.trans_inverted)
private val inverted = itemView.context.getString(R.string.trans_inverted)
fun bind(radio: SatRadio) {
binding.transDesc.text = radio.info
radio.downlink.let { downlink ->
if (downlink != null) {
val downlinkFreq = downlink / divider
binding.transDownlink.text =
String.format(Locale.ENGLISH, formatLink, downlinkFreq)
} else {
binding.transDownlink.text = formatLinkNull
binding.run {
radioInfo.text = radio.info
radio.downlink.let { downlink ->
if (downlink != null) {
radioDownlink.text = String.format(Locale.ENGLISH, link, downlink / divider)
} else {
radioDownlink.text = linkNull
}
}
}
radio.uplink.let { uplink ->
if (uplink != null) {
val uplinkFreq = uplink / divider
binding.transUplink.text = String.format(Locale.ENGLISH, formatLink, uplinkFreq)
} else {
binding.transUplink.text = formatLinkNull
radio.uplink.let { uplink ->
if (uplink != null) {
radioUplink.text = String.format(Locale.ENGLISH, link, uplink / divider)
} else {
radioUplink.text = linkNull
}
}
if (radio.mode != null) {
radioMode.text = String.format(mode, radio.mode)
} else {
radioMode.text = String.format(mode, stringNo)
}
if (radio.isInverted) {
radioInverted.text = String.format(inverted, stringYes)
} else {
radioInverted.text = String.format(inverted, stringNo)
}
}
if (radio.mode != null) {
binding.transMode.text = String.format(mode, radio.mode)
} else {
binding.transMode.text = String.format(mode, strNo)
}
if (radio.isInverted) {
binding.transInverted.text = String.format(isInverted, strYes)
} else {
binding.transInverted.text = String.format(isInverted, strNo)
}
}
companion object {
fun from(parent: ViewGroup): TransHolder {
val inflater = LayoutInflater.from(parent.context)
return TransHolder(ItemTransBinding.inflate(inflater, parent, false))
return TransHolder(ItemRadioBinding.inflate(inflater, parent, false))
}
}
}
@@ -27,6 +27,7 @@ import android.widget.EditText
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.NestedScrollView
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
@@ -71,6 +72,11 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
}
private fun setupViews() {
binding.settingsScroll.apply {
setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, y, _, newY ->
if (y > newY) binding.settingsFab.hide() else binding.settingsFab.show()
})
}
binding.prefsBack.setOnClickListener { findNavController().navigateUp() }
setupAboutCard()
setupDataCard()