v2.5.0 - Minor fixes, updated screenshots, version bumped

This commit is contained in:
Arty Bishop committed 2021-05-17 09:53:34 +01:00
1 parent 74528f4a14
commit fb2008b07a
15 files changed
+79 -76

No files matched your search

+2 -2
View File
@@ -13,8 +13,8 @@ android {
applicationId "com.rtbishop.look4sat" applicationId "com.rtbishop.look4sat"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 30 targetSdkVersion 30
versionCode 240 versionCode 250
versionName "2.4.0" versionName "2.5.0"
} }
buildTypes { buildTypes {
@@ -26,6 +26,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator import androidx.recyclerview.widget.SimpleItemAnimator
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.databinding.DialogSourceBinding import com.rtbishop.look4sat.databinding.DialogSourceBinding
import com.rtbishop.look4sat.databinding.FragmentEntriesBinding import com.rtbishop.look4sat.databinding.FragmentEntriesBinding
@@ -64,7 +65,7 @@ class SatItemFragment : Fragment(R.layout.fragment_entries) {
importWeb.setOnClickListener { viewModel.updateEntriesFromWeb(null) } importWeb.setOnClickListener { viewModel.updateEntriesFromWeb(null) }
importSource.setOnClickListener { showSourceDialog() } importSource.setOnClickListener { showSourceDialog() }
importFile.setOnClickListener { filePicker.launch("*/*") } importFile.setOnClickListener { filePicker.launch("*/*") }
selectMode.setOnClickListener { viewModel.createModesDialog(requireContext()).show() } selectMode.setOnClickListener { showModesDialog() }
selectAll.setOnClickListener { viewModel.selectCurrentItems() } selectAll.setOnClickListener { viewModel.selectCurrentItems() }
searchBar.setOnQueryTextListener(viewModel) searchBar.setOnQueryTextListener(viewModel)
} }
@@ -114,4 +115,33 @@ class SatItemFragment : Fragment(R.layout.fragment_entries) {
} }
dialogBuilder.create().show() dialogBuilder.create().show()
} }
private fun showModesDialog() {
val modes = arrayOf(
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
"CERTO", "CW", "DQPSK", "DSTAR", "DUV", "FFSK", "FM", "FMN", "FSK", "FSK AX.100 Mode 5",
"FSK AX.100 Mode 6", "FSK AX.25 G3RUH", "GFSK", "GFSK Rktr", "GMSK", "HRPT", "LoRa",
"LRPT", "LSB", "MFSK", "MSK", "MSK AX.100 Mode 5", "MSK AX.100 Mode 6", "OFDM", "OQPSK",
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
)
val savedModes = BooleanArray(modes.size)
val selectedModes = viewModel.loadSelectedModes().toMutableList()
selectedModes.forEach { savedModes[modes.indexOf(it)] = true }
val dialogBuilder = MaterialAlertDialogBuilder(requireContext()).apply {
setTitle(context.getString(R.string.modes_title))
setMultiChoiceItems(modes, savedModes) { _, which, isChecked ->
when {
isChecked -> selectedModes.add(modes[which])
selectedModes.contains(modes[which]) -> selectedModes.remove(modes[which])
}
}
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
viewModel.saveSelectedModes(selectedModes)
}
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
}
}
dialogBuilder.create().show()
}
} }
@@ -18,13 +18,9 @@
package com.rtbishop.look4sat.presentation.satItemScreen package com.rtbishop.look4sat.presentation.satItemScreen
import android.content.ContentResolver import android.content.ContentResolver
import android.content.Context
import android.net.Uri import android.net.Uri
import android.widget.SearchView import android.widget.SearchView
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.* import androidx.lifecycle.*
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.data.SatDataRepository import com.rtbishop.look4sat.data.SatDataRepository
import com.rtbishop.look4sat.domain.model.SatItem import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.framework.model.Result import com.rtbishop.look4sat.framework.model.Result
@@ -40,7 +36,7 @@ class SatItemViewModel @Inject constructor(
private val satDataRepository: SatDataRepository, private val satDataRepository: SatDataRepository,
) : ViewModel(), SatItemAdapter.EntriesClickListener, SearchView.OnQueryTextListener { ) : ViewModel(), SatItemAdapter.EntriesClickListener, SearchView.OnQueryTextListener {
private val transModes = MutableLiveData(satDataRepository.loadModesSelection()) private val transModes = MutableLiveData(satDataRepository.loadSelectedModes())
private val currentQuery = MutableLiveData(String()) private val currentQuery = MutableLiveData(String())
private val itemsWithModes = transModes.switchMap { modes -> private val itemsWithModes = transModes.switchMap { modes ->
liveData { satDataRepository.getSatItems().collect { emit(filterByModes(it, modes)) } } liveData { satDataRepository.getSatItems().collect { emit(filterByModes(it, modes)) } }
@@ -83,28 +79,13 @@ class SatItemViewModel @Inject constructor(
} }
} }
fun createModesDialog(context: Context): AlertDialog { fun loadSelectedModes(): List<String> {
val modes = satDataRepository.getAllModes() return satDataRepository.loadSelectedModes()
val savedModes = BooleanArray(modes.size) }
val selectedModes = satDataRepository.loadModesSelection().toMutableList()
selectedModes.forEach { savedModes[modes.indexOf(it)] = true } fun saveSelectedModes(modes: List<String>) {
val dialogBuilder = MaterialAlertDialogBuilder(context).apply { transModes.value = modes
setTitle(context.getString(R.string.modes_title)) satDataRepository.saveSelectedModes(modes)
setMultiChoiceItems(modes, savedModes) { _, which, isChecked ->
when {
isChecked -> selectedModes.add(modes[which])
selectedModes.contains(modes[which]) -> selectedModes.remove(modes[which])
}
}
setPositiveButton(context.getString(android.R.string.ok)) { _, _ ->
transModes.value = selectedModes
satDataRepository.saveModesSelection(selectedModes)
}
setNeutralButton(context.getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
}
}
return dialogBuilder.create()
} }
override fun onQueryTextSubmit(query: String): Boolean { override fun onQueryTextSubmit(query: String): Boolean {
@@ -49,21 +49,19 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
@Inject @Inject
lateinit var sharedPreferences: SharedPreferences lateinit var sharedPreferences: SharedPreferences
private val viewModelSat: SatMapViewModel by viewModels() private val viewModel: SatMapViewModel by viewModels()
private val minLat = MapView.getTileSystem().minLatitude private val minLat = MapView.getTileSystem().minLatitude
private val maxLat = MapView.getTileSystem().maxLatitude private val maxLat = MapView.getTileSystem().maxLatitude
private val trackPaint = Paint().apply { private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
strokeWidth = 2f strokeWidth = 2f
style = Paint.Style.STROKE style = Paint.Style.STROKE
color = Color.RED color = Color.RED
strokeCap = Paint.Cap.ROUND strokeCap = Paint.Cap.ROUND
strokeJoin = Paint.Join.ROUND strokeJoin = Paint.Join.ROUND
isAntiAlias = true
} }
private val footprintPaint = Paint().apply { private val footprintPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL_AND_STROKE style = Paint.Style.FILL_AND_STROKE
color = Color.parseColor("#26FFE082") color = Color.parseColor("#26FFE082")
isAntiAlias = true
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -73,10 +71,9 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
mapView.apply { mapView.apply {
setMultiTouchControls(true) setMultiTouchControls(true)
setTileSource(TileSourceFactory.WIKIMEDIA) setTileSource(TileSourceFactory.WIKIMEDIA)
val minZoom = getMinZoom(resources.displayMetrics.heightPixels) minZoomLevel = getMinZoom(resources.displayMetrics.heightPixels)
minZoomLevel = minZoom
maxZoomLevel = 6.0 maxZoomLevel = 6.0
controller.setZoom(minZoom + 0.5) controller.setZoom(minZoomLevel + 0.5)
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
@@ -86,17 +83,17 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
overlays.addAll(Array(4) { FolderOverlay() }) overlays.addAll(Array(4) { FolderOverlay() })
} }
} }
binding.fabPrev.setOnClickListener { viewModelSat.scrollSelection(true) } binding.fabPrev.setOnClickListener { viewModel.scrollSelection(true) }
binding.fabNext.setOnClickListener { viewModelSat.scrollSelection(false) } binding.fabNext.setOnClickListener { viewModel.scrollSelection(false) }
setupObservers(binding) setupObservers(binding)
} }
private fun setupObservers(binding: FragmentMapBinding) { private fun setupObservers(binding: FragmentMapBinding) {
viewModelSat.stationPos.observe(viewLifecycleOwner, { renderStationPos(it, binding) }) viewModel.stationPos.observe(viewLifecycleOwner, { renderStationPos(it, binding) })
viewModelSat.allSatPositions.observe(viewLifecycleOwner, { renderSatPositions(it, binding) }) viewModel.satPositions.observe(viewLifecycleOwner, { renderSatPositions(it, binding) })
viewModelSat.satTrack.observe(viewLifecycleOwner, { renderSatTrack(it, binding) }) viewModel.satTrack.observe(viewLifecycleOwner, { renderSatTrack(it, binding) })
viewModelSat.satFootprint.observe(viewLifecycleOwner, { renderSatFootprint(it, binding) }) viewModel.satFootprint.observe(viewLifecycleOwner, { renderSatFootprint(it, binding) })
viewModelSat.satData.observe(viewLifecycleOwner, { renderSatData(it, binding) }) viewModel.satData.observe(viewLifecycleOwner, { renderSatData(it, binding) })
} }
private fun renderStationPos(stationPos: Position, binding: FragmentMapBinding) { private fun renderStationPos(stationPos: Position, binding: FragmentMapBinding) {
@@ -116,7 +113,7 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
binding.apply { binding.apply {
val markers = FolderOverlay() val markers = FolderOverlay()
posMap.entries.forEach { posMap.entries.forEach {
if (viewModelSat.shouldUseTextLabels()) { if (viewModel.shouldUseTextLabels()) {
Marker(mapView).apply { Marker(mapView).apply {
setInfoWindow(null) setInfoWindow(null)
textLabelFontSize = 24 textLabelFontSize = 24
@@ -131,7 +128,7 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
Timber.d(exception) Timber.d(exception)
} }
setOnMarkerClickListener { _, _ -> setOnMarkerClickListener { _, _ ->
viewModelSat.selectSatellite(it.key) viewModel.selectSatellite(it.key)
return@setOnMarkerClickListener true return@setOnMarkerClickListener true
} }
markers.add(this) markers.add(this)
@@ -147,7 +144,7 @@ class SatMapFragment : Fragment(R.layout.fragment_map) {
Timber.d(exception) Timber.d(exception)
} }
setOnMarkerClickListener { _, _ -> setOnMarkerClickListener { _, _ ->
viewModelSat.selectSatellite(it.key) viewModel.selectSatellite(it.key)
return@setOnMarkerClickListener true return@setOnMarkerClickListener true
} }
markers.add(this) markers.add(this)
@@ -60,8 +60,8 @@ class SatMapViewModel @Inject constructor(
private val _satData = MutableLiveData<SatData>() private val _satData = MutableLiveData<SatData>()
val satData: LiveData<SatData> = this._satData val satData: LiveData<SatData> = this._satData
private val _allSatPositions = MutableLiveData<Map<Satellite, Position>>() private val _satPositions = MutableLiveData<Map<Satellite, Position>>()
val allSatPositions: LiveData<Map<Satellite, Position>> = _allSatPositions val satPositions: LiveData<Map<Satellite, Position>> = _satPositions
init { init {
viewModelScope.launch { viewModelScope.launch {
@@ -118,7 +118,7 @@ class SatMapViewModel @Inject constructor(
val osmLon = clipLon(Math.toDegrees(satPos.longitude)) val osmLon = clipLon(Math.toDegrees(satPos.longitude))
satPositions[satellite] = Position(osmLat, osmLon) satPositions[satellite] = Position(osmLat, osmLon)
} }
_allSatPositions.postValue(satPositions) _satPositions.postValue(satPositions)
} }
} }
+3 -3
View File
@@ -44,7 +44,7 @@
<string name="pref_gsp_title">Местоположение наземной станции</string> <string name="pref_gsp_title">Местоположение наземной станции</string>
<string name="pref_pos_gps">Установить позицию по данным GPS</string> <string name="pref_pos_gps">Установить позицию по данным GPS</string>
<string name="pref_pos_gps_null">Местоположение отключено</string> <string name="pref_pos_gps_null">Нет данных геолокации</string>
<string name="pref_pos_gps_error">Нет разрешения использовать геоданные</string> <string name="pref_pos_gps_error">Нет разрешения использовать геоданные</string>
<string name="pref_pos_qth">Установить позицию по локатору QTH</string> <string name="pref_pos_qth">Установить позицию по локатору QTH</string>
<string name="pref_pos_qth_error">Неправильный локатор QTH</string> <string name="pref_pos_qth_error">Неправильный локатор QTH</string>
@@ -72,11 +72,11 @@
\n— Вам за использование этого приложения! \nЖелаю всегда чистого неба над головой! \n— Вам за использование этого приложения! \nЖелаю всегда чистого неба над головой!
\n— <a href="https://github.com/g4dpz">David A. B. Johnson</a> и \n— <a href="https://github.com/g4dpz">David A. B. Johnson</a> и
<a href="https://github.com/davidmoten">Dave Moten</a> за работу над библиотекой predict4java и <a href="https://github.com/davidmoten">Dave Moten</a> за работу над библиотекой predict4java и
открытие доступа к ней по лицензии <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a> за доступ к ней по лицензии <a href="https://gnu.org/licenses/old-licenses/gpl-2.0.en.html">GNU GPLv2</a>
\n— <a href="https://github.com/csete">Alexandru Csete</a> за его замечательную \n— <a href="https://github.com/csete">Alexandru Csete</a> за его замечательную
программу Gpredict, которая вдохновила меня на создание Look4Sat. программу Gpredict, которая вдохновила меня на создание Look4Sat.
\n— <a href="https://celestrak.com/webmaster.php">Доктору T.S. Kelso</a> за его сайт \n— <a href="https://celestrak.com/webmaster.php">Доктору T.S. Kelso</a> за его сайт
<a href="https://celestrak.com/">Celestrak</a>, который предоставляет доступ к файлам орбит Two-Line Element. <a href="https://celestrak.com/">Celestrak</a> и доступ к файлам орбит Two-Line Element.
\n— <a href="https://libre.space/">Libre Space Foundation</a> за проект \n— <a href="https://libre.space/">Libre Space Foundation</a> за проект
<a href="https://db.satnogs.org/">SatNOGS</a>, API и базу данных с огромным количеством информации о спутниках. <a href="https://db.satnogs.org/">SatNOGS</a>, API и базу данных с огромным количеством информации о спутниках.
\n— <a href="https://square.github.io/">Square</a> за библиотеки OkHttp, Retrofit, Moshi и доступ \n— <a href="https://square.github.io/">Square</a> за библиотеки OkHttp, Retrofit, Moshi и доступ
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="app_name" translatable="false">Look4Sat</string> <string name="app_name" translatable="false">Look4Sat</string>
<string name="placeholder" translatable="false">Placeholder</string> <string name="placeholder" translatable="false">dummy</string>
<string name="no">No</string> <string name="no">No</string>
<string name="yes">Yes</string> <string name="yes">Yes</string>
@@ -60,7 +60,7 @@
<string name="pref_gsp_title">Ground station position</string> <string name="pref_gsp_title">Ground station position</string>
<string name="pref_pos_gps">Set position from GPS data</string> <string name="pref_pos_gps">Set position from GPS data</string>
<string name="pref_pos_gps_null">Location is switched off</string> <string name="pref_pos_gps_null">No geolocation data</string>
<string name="pref_pos_gps_error">Check your location permissions</string> <string name="pref_pos_gps_error">Check your location permissions</string>
<string name="pref_pos_qth">Set position from QTH locator</string> <string name="pref_pos_qth">Set position from QTH locator</string>
<string name="pref_pos_qth_error">Invalid QTH locator</string> <string name="pref_pos_qth_error">Invalid QTH locator</string>
+1 -1
View File
@@ -61,7 +61,7 @@
android:title="@string/pref_map_labels_title" android:title="@string/pref_map_labels_title"
app:iconSpaceReserved="false"> app:iconSpaceReserved="false">
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="false" android:defaultValue="true"
android:key="shouldUseTextLabels" android:key="shouldUseTextLabels"
android:title="@string/pref_map_labels" android:title="@string/pref_map_labels"
app:iconSpaceReserved="false" /> app:iconSpaceReserved="false" />
@@ -42,23 +42,11 @@ class SatDataRepository(
"https://www.prismnet.com/~mmccants/tles/inttles.zip" "https://www.prismnet.com/~mmccants/tles/inttles.zip"
) )
private val transmittersModes = arrayOf( fun saveSelectedModes(modes: List<String>) {
"AFSK", "AFSK S-Net", "AFSK SALSAT", "AHRPT", "AM", "APT", "BPSK", "BPSK PMT-A3",
"CERTO", "CW", "DQPSK", "DSTAR", "DUV", "FFSK", "FM", "FMN", "FSK", "FSK AX.100 Mode 5",
"FSK AX.100 Mode 6", "FSK AX.25 G3RUH", "GFSK", "GFSK Rktr", "GMSK", "HRPT", "LoRa",
"LRPT", "LSB", "MFSK", "MSK", "MSK AX.100 Mode 5", "MSK AX.100 Mode 6", "OFDM", "OQPSK",
"PSK", "PSK31", "PSK63", "QPSK", "QPSK31", "QPSK63", "SSTV", "USB", "WSJT"
)
fun getAllModes(): Array<String> {
return transmittersModes
}
fun saveModesSelection(modes: List<String>) {
preferencesSource.saveModesSelection(modes) preferencesSource.saveModesSelection(modes)
} }
fun loadModesSelection(): List<String> { fun loadSelectedModes(): List<String> {
return preferencesSource.loadModesSelection() return preferencesSource.loadModesSelection()
} }
@@ -0,0 +1,6 @@
Added simple custom source TLE update dialog
Added immediate initial setup
Added pass direction arrow to radar view #52
Added orientation pointer to radar view
Fixed radar view update bug #51
Switched to modular architecture
Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 430 KiB

After

Width:  |  Height:  |  Size: 592 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 KiB

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 794 KiB

After

Width:  |  Height:  |  Size: 795 KiB

@@ -1,5 +1,6 @@
Removed hardcoded screen orientation Added simple custom source TLE update dialog
Removed redundant permission from manifest Added immediate initial setup
Added antenna rotator control via socket Added pass direction arrow to radar view #52
Showing azimuth for respective maxElevation Added orientation pointer to radar view
Showing satellite name on the polar screen Fixed radar view update bug #51
Switched to modular architecture