Added filter dialog, removed PassesFragment

This commit is contained in:
Arty Bishop committed 2025-12-27 15:01:32 +00:00
1 parent a08cfc7fb8
commit acb851d4f6
11 files changed
+74 -816

No files matched your search

@@ -1,20 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.framework.model
data class DataSource(var url: String = String())
@@ -17,54 +17,70 @@
*/
package com.rtbishop.look4sat.presentation.passesScreen
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.app.AppCompatDialogFragment
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.DialogFilterBinding
import com.rtbishop.look4sat.domain.ISettingsManager
import com.rtbishop.look4sat.presentation.setNavResult
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.presentation.CardButton
import com.rtbishop.look4sat.presentation.MainTheme
@AndroidEntryPoint
class FilterDialog : AppCompatDialogFragment() {
@Preview(showBackground = true)
@Composable
private fun FilterDialogPreview() {
MainTheme { FilterDialog(8, 16.0, {}) { _, _ -> } }
}
@Inject
lateinit var preferences: ISettingsManager
override fun onCreateView(inflater: LayoutInflater, group: ViewGroup?, state: Bundle?): View? {
return inflater.inflate(R.layout.dialog_filter, group, false)
}
override fun onViewCreated(view: View, state: Bundle?) {
super.onViewCreated(view, state)
DialogFilterBinding.bind(view).apply {
dialog?.window?.setBackgroundDrawableResource(R.color.transparent)
dialog?.window?.setLayout(
(resources.displayMetrics.widthPixels * 0.94).toInt(),
WindowManager.LayoutParams.WRAP_CONTENT
)
filterHoursEdit.setText(preferences.getHoursAhead().toString())
filterElevEdit.setText(preferences.getMinElevation().toString())
filterBtnPos.setOnClickListener {
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun FilterDialog(hours: Int, elevation: Double, toggle: () -> Unit, save: (Int, Double) -> Unit) {
val hoursValue = rememberSaveable { mutableStateOf(hours) }
val elevValue = rememberSaveable { mutableStateOf(elevation) }
Dialog(onDismissRequest = { toggle() }) {
ElevatedCard {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth(1f)
) {
Text(text = "Filter passes", color = MaterialTheme.colorScheme.primary)
Text(text = "Show passes that occur within X hours")
OutlinedTextField(value = hoursValue.value.toString(), onValueChange = { newValue ->
val hoursAhead = try {
filterHoursEdit.text.toString().toInt()
newValue.toInt()
} catch (exception: Exception) {
24
12
}
val minElevation = try {
filterElevEdit.text.toString().toDouble()
hoursValue.value = hoursAhead
})
Text(text = "Show passes with max elevation above")
OutlinedTextField(value = elevValue.value.toString(), onValueChange = { newValue ->
val maxElevation = try {
newValue.toDouble()
} catch (exception: Exception) {
16.0
}
setNavResult("prefs", Pair(hoursAhead, minElevation))
dismiss()
elevValue.value = maxElevation
})
Row(
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth()
) {
CardButton(onClick = { toggle() }, text = "Cancel")
CardButton(
onClick = {
save(hoursValue.value, elevValue.value)
toggle()
}, text = "Accept"
)
}
}
filterBtnNeg.setOnClickListener { dismiss() }
}
}
}
@@ -1,124 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.presentation.passesScreen
import android.view.LayoutInflater
import android.view.ViewGroup
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.ItemPassBinding
import com.rtbishop.look4sat.domain.predict.SatPass
import java.text.SimpleDateFormat
import java.util.*
class PassesAdapter(private val clickListener: PassesClickListener) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val diffCallback = object : DiffUtil.ItemCallback<SatPass>() {
override fun areItemsTheSame(oldItem: SatPass, newItem: SatPass): Boolean {
return oldItem.catNum == newItem.catNum && oldItem.aosTime == newItem.aosTime
}
override fun areContentsTheSame(oldItem: SatPass, newItem: SatPass): Boolean {
return oldItem.progress == newItem.progress
}
}
private val differ = AsyncListDiffer(this, diffCallback)
private var isUTC: Boolean = false
interface PassesClickListener {
fun navigateToPass(satPass: SatPass)
}
fun submitList(passes: List<SatPass>) {
differ.submitList(passes)
}
fun setUTC(isUTC: Boolean) {
this.isUTC = isUTC
}
override fun getItemCount() = differ.currentList.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return PassHolder.from(parent)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
(holder as PassHolder).bind(differ.currentList[position], clickListener, isUTC)
}
class PassHolder private constructor(private val binding: ItemPassBinding) :
RecyclerView.ViewHolder(binding.root) {
private val satIdFormat = itemView.context.getString(R.string.pass_satId)
private val aosAzFormat = itemView.context.getString(R.string.pass_aosAz)
private val altFormat = itemView.context.getString(R.string.pass_altitude)
private val losAzFormat = itemView.context.getString(R.string.pass_losAz)
private val startTimeFormat = itemView.context.getString(R.string.pass_startTime)
private val elevFormat = itemView.context.getString(R.string.pass_elevation)
private val endTimeFormat = itemView.context.getString(R.string.pass_endTime)
private val placeholder = itemView.context.getString(R.string.pass_placeholder)
private val timeZoneUTC = TimeZone.getTimeZone("UTC")
private val startFormat = SimpleDateFormat(startTimeFormat, Locale.getDefault())
private val endFormat = SimpleDateFormat(endTimeFormat, Locale.getDefault())
fun bind(satPass: SatPass, listener: PassesClickListener, shouldUseUTC: Boolean) {
binding.apply {
if (satPass.isDeepSpace) {
passName.text = satPass.name
passId.text = String.format(satIdFormat, satPass.catNum)
passAos.text = String.format(aosAzFormat, satPass.aosAzimuth)
passAltitude.text = String.format(altFormat, satPass.altitude)
passLos.text = String.format(losAzFormat, satPass.losAzimuth)
passStart.text = placeholder
passElev.text = String.format(elevFormat, satPass.maxElevation)
passEnd.text = placeholder
passProgress.progress = 100
} else {
if (shouldUseUTC) {
startFormat.timeZone = timeZoneUTC
endFormat.timeZone = timeZoneUTC
}
passName.text = satPass.name
passId.text = String.format(satIdFormat, satPass.catNum)
passAos.text = String.format(aosAzFormat, satPass.aosAzimuth)
passAltitude.text = String.format(altFormat, satPass.altitude)
passLos.text = String.format(losAzFormat, satPass.losAzimuth)
passStart.text = startFormat.format(Date(satPass.aosTime))
passElev.text = String.format(elevFormat, satPass.maxElevation)
passEnd.text = endFormat.format(Date(satPass.losTime))
passProgress.progress = satPass.progress.toInt()
}
}
itemView.setOnClickListener {
listener.navigateToPass(satPass)
}
}
companion object {
fun from(parent: ViewGroup): PassHolder {
val inflater = LayoutInflater.from(parent.context)
return PassHolder(ItemPassBinding.inflate(inflater, parent, false))
}
}
}
}
@@ -1,167 +0,0 @@
/*
* Look4Sat. Amateur radio satellite tracker and pass predictor.
* Copyright (C) 2019-2022 Arty Bishop (bishop.arty@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.rtbishop.look4sat.presentation.passesScreen
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.fragment.app.Fragment
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
import com.rtbishop.look4sat.domain.model.DataState
import com.rtbishop.look4sat.domain.predict.SatPass
import com.rtbishop.look4sat.presentation.clickWithDebounce
import com.rtbishop.look4sat.presentation.getNavResult
import com.rtbishop.look4sat.utility.toTimerString
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesClickListener {
private val viewModel: PassesViewModel by viewModels()
private val passesAdapter = PassesAdapter(this)
private var binding: FragmentPassesBinding? = null
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentPassesBinding.bind(view).apply {
passesAdapter.setUTC(viewModel.shouldUseUTC())
passesRecycler.apply {
setHasFixedSize(true)
adapter = passesAdapter
layoutManager = LinearLayoutManager(requireContext())
(itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
addItemDecoration(DividerItemDecoration(requireContext(), 1))
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()
}
})
}
passesBtnRefresh.clickWithDebounce { viewModel.calculatePasses() }
passesBtnMap.clickWithDebounce {
val dir = PassesFragmentDirections.globalToMap()
findNavController().navigate(dir)
}
passesBtnFilter.clickWithDebounce {
val dir = PassesFragmentDirections.passesToFilter()
findNavController().navigate(dir)
}
passesBtnSettings.clickWithDebounce {
val dir = PassesFragmentDirections.globalToSettings()
findNavController().navigate(dir)
}
setupObservers()
}
}
override fun navigateToPass(satPass: SatPass) {
if (satPass.progress < 100) satPass.run {
val dir = PassesFragmentDirections.globalToRadar(this.catNum, this.aosTime)
findNavController().navigate(dir)
}
}
override fun onDestroyView() {
binding?.passesRecycler?.adapter = null
binding = null
super.onDestroyView()
}
private fun setupObservers() {
viewModel.entriesTotal.observe(viewLifecycleOwner) { number ->
handleEntriesTotal(number)
}
viewModel.passes.observe(viewLifecycleOwner) { passesResult ->
handleNewPasses(passesResult)
}
getNavResult<Pair<Int, Double>>(R.id.nav_passes, "prefs") { prefs ->
viewModel.calculatePasses(prefs.first, prefs.second)
}
getNavResult<List<Int>>(R.id.nav_passes, "selection") { items ->
viewModel.calculatePasses(selection = items)
}
}
private fun handleEntriesTotal(number: Int) {
binding?.run {
if (number > 0) {
passesFab.clickWithDebounce {
val direction = PassesFragmentDirections.globalToEntries()
findNavController().navigate(direction)
}
} else {
passesFab.clickWithDebounce {
val errorMessage = getString(R.string.passes_empty_db)
Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_SHORT).show()
}
}
}
}
private fun handleNewPasses(state: DataState<List<SatPass>>) {
binding?.run {
when (state) {
is DataState.Success -> {
passesAdapter.submitList(state.data)
tickMainTimer(state.data)
if (state.data.isNotEmpty()) { // show new passes list
passesEmpty.visibility = View.INVISIBLE
passesProgress.visibility = View.INVISIBLE
} else { // show no passes message
passesEmpty.visibility = View.VISIBLE
passesProgress.visibility = View.INVISIBLE
}
}
is DataState.Loading -> {
passesEmpty.visibility = View.INVISIBLE
passesProgress.visibility = View.VISIBLE
passesTimer.text = 0L.toTimerString()
}
else -> {}
}
}
}
private fun tickMainTimer(passes: List<SatPass>) {
binding?.run {
if (passes.isNotEmpty()) {
val timeNow = System.currentTimeMillis()
try {
val nextPass = passes.first { it.aosTime.minus(timeNow) > 0 }
val millisBeforeStart = nextPass.aosTime.minus(timeNow)
passesTimer.text = millisBeforeStart.toTimerString()
} catch (e: NoSuchElementException) {
val lastPass = passes.last()
val millisBeforeEnd = lastPass.losTime.minus(timeNow)
passesTimer.text = millisBeforeEnd.toTimerString()
}
} else {
passesTimer.text = 0L.toTimerString()
}
passesBtnRefresh.isEnabled = true
}
}
}
@@ -15,6 +15,8 @@ import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -42,14 +44,23 @@ fun PassesScreen(viewModel: PassesViewModel = hiltViewModel()) {
val state = viewModel.passes.observeAsState()
val timerText = viewModel.timerText.observeAsState()
val isRefreshing = state.value is DataState.Loading
val refreshState = rememberPullRefreshState(
refreshing = isRefreshing,
val refreshState = rememberPullRefreshState(refreshing = isRefreshing,
onRefresh = { viewModel.calculatePasses() })
val value = state.value
var passes = emptyList<SatPass>()
if (value is DataState.Success) passes = value.data
val showDialog = rememberSaveable { mutableStateOf(false) }
val toggleDialog = { showDialog.value = showDialog.value.not() }
if (showDialog.value) {
FilterDialog(viewModel.getHoursAhead(),
viewModel.getMinElevation(),
{ toggleDialog() }) { hours, elev ->
viewModel.calculatePasses(hours, elev)
}
}
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
ElevatedCard(modifier = Modifier.height(52.dp)) {
Row(
@@ -57,7 +68,7 @@ fun PassesScreen(viewModel: PassesViewModel = hiltViewModel()) {
horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxSize()
) {
IconButton(onClick = {}) {
IconButton(onClick = { toggleDialog() }) {
Icon(
painter = painterResource(id = R.drawable.ic_filter),
contentDescription = null
@@ -43,6 +43,10 @@ class PassesViewModel @Inject constructor(
val passes: LiveData<DataState<List<SatPass>>> = _passes
val timerText: LiveData<Triple<String, String, String>> = _timerText
fun getHoursAhead() = settings.getHoursAhead()
fun getMinElevation() = settings.getMinElevation()
init {
viewModelScope.launch {
satelliteManager.calculatedPasses.collect { passes ->
-131
View File
@@ -1,131 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/SurfaceCard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/filter_title"
style="@style/DialogTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:minHeight="48dp"
android:text="@string/filter_title"
app:layout_constraintBottom_toTopOf="@+id/filter_hours_text"
app:layout_constraintEnd_toEndOf="@+id/filter_btn_pos"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/filter_btn_neg"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/filter_hours_text"
style="@style/DialogText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:text="@string/filter_hours_text"
app:layout_constraintBottom_toTopOf="@+id/filter_hours_layout"
app:layout_constraintEnd_toEndOf="@+id/filter_title"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/filter_title"
app:layout_constraintTop_toBottomOf="@+id/filter_title" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/filter_hours_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/filter_hours_hint"
android:importantForAutofill="no"
android:inputType="number"
android:minHeight="48dp"
app:endIconMode="clear_text"
app:layout_constraintBottom_toTopOf="@+id/filter_elev_text"
app:layout_constraintEnd_toEndOf="@+id/filter_hours_text"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/filter_hours_text"
app:layout_constraintTop_toBottomOf="@+id/filter_hours_text">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/filter_hours_edit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textUri" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/filter_elev_text"
style="@style/DialogText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/filter_elev_text"
app:layout_constraintBottom_toTopOf="@+id/filter_elev_layout"
app:layout_constraintEnd_toEndOf="@+id/filter_hours_text"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/filter_hours_text"
app:layout_constraintTop_toBottomOf="@+id/filter_hours_layout" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/filter_elev_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:hint="@string/filter_elev_hint"
android:importantForAutofill="no"
android:inputType="number|numberDecimal"
android:minHeight="48dp"
app:endIconMode="clear_text"
app:layout_constraintBottom_toTopOf="@+id/filter_btn_neg"
app:layout_constraintEnd_toEndOf="@+id/filter_hours_layout"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/filter_hours_layout"
app:layout_constraintTop_toBottomOf="@+id/filter_elev_text">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/filter_elev_edit"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:inputType="textUri" />
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/filter_btn_neg"
style="@style/NormalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
android:layout_marginBottom="6dp"
android:text="@string/btn_cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/filter_btn_pos"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/filter_elev_layout" />
<Button
android:id="@+id/filter_btn_pos"
style="@style/NormalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:text="@string/btn_accept"
app:layout_constraintBaseline_toBaselineOf="@+id/filter_btn_neg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/filter_btn_neg" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/SurfaceCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/sources_title"
style="@style/DialogTitle"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginStart="22dp"
android:layout_marginEnd="8dp"
android:text="@string/sources_title"
android:textSize="18sp"
app:layout_constraintBaseline_toBaselineOf="@+id/sources_btn_add"
app:layout_constraintEnd_toStartOf="@+id/sources_btn_add"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="@+id/sources_btn_neg" />
<Button
android:id="@+id/sources_btn_add"
style="@style/NormalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:text="@string/btn_add"
app:layout_constraintEnd_toEndOf="@+id/sources_btn_pos"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/sources_title"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/sources_recycler"
style="@style/Recycler"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="2dp"
android:layout_marginTop="2dp"
android:layout_marginEnd="2dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toTopOf="@+id/sources_btn_pos"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintEnd_toEndOf="@+id/sources_btn_pos"
app:layout_constraintStart_toStartOf="@+id/sources_btn_neg"
app:layout_constraintTop_toBottomOf="@+id/sources_btn_add" />
<Button
android:id="@+id/sources_btn_neg"
style="@style/NormalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginBottom="6dp"
android:text="@string/btn_cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/sources_btn_pos"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/sources_btn_pos"
style="@style/NormalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="6dp"
android:text="@string/btn_accept"
app:layout_constraintBaseline_toBaselineOf="@+id/sources_btn_neg"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/sources_btn_neg" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
-116
View File
@@ -1,116 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionGroup="true">
<androidx.cardview.widget.CardView
android:id="@+id/passes_toolbar"
style="@style/Toolbar">
<ImageButton
android:id="@+id/passes_btn_refresh"
style="@style/ToolbarButton"
android:rotation="45"
android:layout_gravity="start|center_vertical"
android:contentDescription="@string/btn_refresh"
android:src="@drawable/ic_refresh" />
<TextView
android:id="@+id/passes_timer"
style="@style/ToolbarTimer" />
<ImageButton
android:id="@+id/passes_btn_map"
style="@style/ToolbarButton"
android:layout_gravity="end|center_vertical"
android:contentDescription="@string/btn_map"
android:src="@drawable/ic_map" />
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
style="@style/SurfaceCard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/view_default_margin"
android:layout_marginTop="@dimen/surface_margin_top"
android:layout_marginEnd="@dimen/view_default_margin"
android:layout_marginBottom="@dimen/surface_margin_bot">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/passes_recycler"
style="@style/Recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ProgressBar
android:id="@+id/passes_progress"
style="@style/RecyclerProgress" />
<LinearLayout
android:id="@+id/passes_empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
android:layout_marginBottom="32dp"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/passes_empty_img"
android:layout_width="160dp"
android:layout_height="160dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="32dp"
android:contentDescription="@string/passes_error"
android:src="@drawable/ic_list"
app:tint="@color/textDisabled" />
<TextView
android:id="@+id/passes_empty_msg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:text="@string/passes_error"
android:textSize="@dimen/text_size_mediumLarge" />
</LinearLayout>
</androidx.cardview.widget.CardView>
<com.google.android.material.bottomappbar.BottomAppBar
android:id="@+id/passes_bottomBar"
style="@style/BottomBar">
<Button
android:id="@+id/passes_btn_filter"
style="@style/NormalButton"
android:layout_width="@dimen/button_width_max"
android:layout_marginStart="@dimen/button_margin_side"
android:layout_gravity="start|center_vertical"
android:text="@string/btn_filter" />
<Button
android:id="@+id/passes_btn_settings"
style="@style/NormalButton"
android:layout_width="@dimen/button_width_max"
android:layout_marginEnd="@dimen/button_margin_side"
android:layout_gravity="end|center_vertical"
android:text="@string/btn_settings" />
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/passes_fab"
style="@style/FloatingActionButton"
android:src="@drawable/ic_satellite"
android:contentDescription="@string/btn_satellites"
app:layout_anchor="@id/passes_bottomBar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
-115
View File
@@ -1,115 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/RecyclerItemCard">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/pass_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground">
<TextView
android:id="@+id/pass_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:text="@string/pass_satName"
android:textColor="@color/accent"
android:textSize="@dimen/text_size_small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/pass_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@string/pass_satId"
android:textColor="@color/accent"
android:textSize="@dimen/text_size_small"
app:layout_constraintBaseline_toBaselineOf="@+id/pass_name"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/pass_aos"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/pass_aosAz"
android:textSize="@dimen/text_size_small"
app:layout_constraintEnd_toStartOf="@+id/pass_los"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="@+id/pass_name"
app:layout_constraintTop_toBottomOf="@+id/pass_name" />
<TextView
android:id="@+id/pass_altitude"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pass_altitude"
android:textSize="@dimen/text_size_small"
app:layout_constraintBaseline_toBaselineOf="@+id/pass_aos"
app:layout_constraintEnd_toEndOf="@+id/pass_los"
app:layout_constraintStart_toStartOf="@+id/pass_aos" />
<TextView
android:id="@+id/pass_los"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pass_losAz"
android:textSize="@dimen/text_size_small"
app:layout_constraintBaseline_toBaselineOf="@+id/pass_aos"
app:layout_constraintEnd_toEndOf="@+id/pass_id"
app:layout_constraintStart_toEndOf="@+id/pass_aos" />
<TextView
android:id="@+id/pass_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/pass_startTime"
android:textSize="@dimen/text_size_small"
app:layout_constraintEnd_toStartOf="@+id/pass_end"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="@+id/pass_aos"
app:layout_constraintTop_toBottomOf="@+id/pass_aos" />
<TextView
android:id="@+id/pass_elev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pass_elevation"
android:textSize="@dimen/text_size_small"
app:layout_constraintBaseline_toBaselineOf="@+id/pass_start"
app:layout_constraintEnd_toEndOf="@+id/pass_end"
app:layout_constraintStart_toStartOf="@+id/pass_start" />
<TextView
android:id="@+id/pass_end"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pass_endTime"
android:textSize="@dimen/text_size_small"
app:layout_constraintBaseline_toBaselineOf="@+id/pass_start"
app:layout_constraintEnd_toEndOf="@+id/pass_los"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/pass_start" />
<ProgressBar
android:id="@+id/pass_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginBottom="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/pass_end"
app:layout_constraintStart_toStartOf="@+id/pass_start"
app:layout_constraintTop_toBottomOf="@+id/pass_elev" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
+1 -17
View File
@@ -3,19 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_root"
app:startDestination="@id/nav_passes">
<fragment
android:id="@+id/nav_passes"
android:name="com.rtbishop.look4sat.presentation.passesScreen.PassesFragment"
tools:layout="@layout/fragment_passes">
<action
android:id="@+id/passes_to_filter"
app:destination="@id/nav_filter"
app:enterAnim="@anim/nav_default_enter_anim"
app:exitAnim="@anim/nav_default_exit_anim"
app:popEnterAnim="@anim/nav_default_pop_enter_anim"
app:popExitAnim="@anim/nav_default_pop_exit_anim" />
</fragment>
app:startDestination="@id/nav_radar">
<fragment
android:id="@+id/nav_radar"
android:name="com.rtbishop.look4sat.presentation.radarScreen.RadarFragment"
@@ -46,10 +34,6 @@
android:id="@+id/nav_modes"
android:name="com.rtbishop.look4sat.presentation.entriesScreen.ModesDialog"
tools:layout="@layout/dialog_modes" />
<dialog
android:id="@+id/nav_filter"
android:name="com.rtbishop.look4sat.presentation.passesScreen.FilterDialog"
tools:layout="@layout/dialog_filter" />
<dialog
android:id="@+id/nav_position"
android:name="com.rtbishop.look4sat.presentation.settingsScreen.PositionDialog"