mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Added map in compose, removed MapFragment
This commit is contained in:
1 parent
acb851d4f6
commit
c592b8d3ce
23 files changed
+333
-737
No files matched your search
@@ -3,7 +3,6 @@ plugins {
|
|||||||
id "org.jetbrains.kotlin.android"
|
id "org.jetbrains.kotlin.android"
|
||||||
id "org.jetbrains.kotlin.kapt"
|
id "org.jetbrains.kotlin.kapt"
|
||||||
id "dagger.hilt.android.plugin"
|
id "dagger.hilt.android.plugin"
|
||||||
id "androidx.navigation.safeargs.kotlin"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -26,12 +26,7 @@ import android.os.SystemClock
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.annotation.IdRes
|
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.rtbishop.look4sat.presentation.bottomNav.MainScreenView
|
import com.rtbishop.look4sat.presentation.bottomNav.MainScreenView
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@@ -54,24 +49,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> Fragment.getNavResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
|
|
||||||
val backStackEntry = findNavController().getBackStackEntry(id)
|
|
||||||
val observer = LifecycleEventObserver { _, event ->
|
|
||||||
if (event == Lifecycle.Event.ON_RESUME && backStackEntry.savedStateHandle.contains(key)) {
|
|
||||||
backStackEntry.savedStateHandle.get<T>(key)?.let(onResult)
|
|
||||||
backStackEntry.savedStateHandle.remove<T>(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
backStackEntry.lifecycle.addObserver(observer)
|
|
||||||
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
|
|
||||||
if (event == Lifecycle.Event.ON_DESTROY) backStackEntry.lifecycle.removeObserver(observer)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> Fragment.setNavResult(key: String, value: T) {
|
|
||||||
findNavController().previousBackStackEntry?.savedStateHandle?.set(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.clickWithDebounce(debounceTime: Long = 875L, action: () -> Unit) {
|
fun View.clickWithDebounce(debounceTime: Long = 875L, action: () -> Unit) {
|
||||||
this.setOnClickListener(object : View.OnClickListener {
|
this.setOnClickListener(object : View.OnClickListener {
|
||||||
private var lastClickTime: Long = 0
|
private var lastClickTime: Long = 0
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import androidx.navigation.compose.rememberNavController
|
|||||||
import com.rtbishop.look4sat.presentation.MainTheme
|
import com.rtbishop.look4sat.presentation.MainTheme
|
||||||
import com.rtbishop.look4sat.presentation.aboutScreen.AboutScreen
|
import com.rtbishop.look4sat.presentation.aboutScreen.AboutScreen
|
||||||
import com.rtbishop.look4sat.presentation.entriesScreen.EntriesScreen
|
import com.rtbishop.look4sat.presentation.entriesScreen.EntriesScreen
|
||||||
|
import com.rtbishop.look4sat.presentation.mapScreen.MapScreen
|
||||||
import com.rtbishop.look4sat.presentation.passesScreen.PassesScreen
|
import com.rtbishop.look4sat.presentation.passesScreen.PassesScreen
|
||||||
import com.rtbishop.look4sat.presentation.passesScreen.PassesViewModel
|
import com.rtbishop.look4sat.presentation.passesScreen.PassesViewModel
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ fun NavigationGraph(navController: NavHostController) {
|
|||||||
EntriesScreen(navToPasses, passesViewModel = passesViewModel)
|
EntriesScreen(navToPasses, passesViewModel = passesViewModel)
|
||||||
}
|
}
|
||||||
composable(BottomNavItem.Passes.screen_route) { PassesScreen(viewModel = passesViewModel) }
|
composable(BottomNavItem.Passes.screen_route) { PassesScreen(viewModel = passesViewModel) }
|
||||||
composable(BottomNavItem.WorldMap.screen_route) {}
|
composable(BottomNavItem.WorldMap.screen_route) { MapScreen() }
|
||||||
composable(BottomNavItem.Settings.screen_route) {}
|
composable(BottomNavItem.Settings.screen_route) {}
|
||||||
composable(BottomNavItem.About.screen_route) { AboutScreen() }
|
composable(BottomNavItem.About.screen_route) { AboutScreen() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import androidx.recyclerview.widget.SimpleItemAnimator
|
|||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.databinding.DialogModesBinding
|
import com.rtbishop.look4sat.databinding.DialogModesBinding
|
||||||
import com.rtbishop.look4sat.domain.ISettingsManager
|
import com.rtbishop.look4sat.domain.ISettingsManager
|
||||||
import com.rtbishop.look4sat.presentation.setNavResult
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -74,7 +73,7 @@ class ModesDialog : AppCompatDialogFragment(), ModesAdapter.ModesClickListener {
|
|||||||
}
|
}
|
||||||
modesBtnNeg.setOnClickListener { dismiss() }
|
modesBtnNeg.setOnClickListener { dismiss() }
|
||||||
modesBtnPos.setOnClickListener {
|
modesBtnPos.setOnClickListener {
|
||||||
setNavResult("modes", selectedModes.toList())
|
// setNavResult("modes", selectedModes.toList())
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,240 +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.mapScreen
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.*
|
|
||||||
import android.graphics.drawable.BitmapDrawable
|
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.fragment.app.viewModels
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import androidx.navigation.fragment.navArgs
|
|
||||||
import com.rtbishop.look4sat.R
|
|
||||||
import com.rtbishop.look4sat.databinding.FragmentMapBinding
|
|
||||||
import com.rtbishop.look4sat.domain.predict.GeoPos
|
|
||||||
import com.rtbishop.look4sat.domain.predict.SatPos
|
|
||||||
import com.rtbishop.look4sat.domain.predict.Satellite
|
|
||||||
import com.rtbishop.look4sat.presentation.clickWithDebounce
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import org.osmdroid.config.Configuration
|
|
||||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
|
||||||
import org.osmdroid.util.GeoPoint
|
|
||||||
import org.osmdroid.views.CustomZoomButtonsController
|
|
||||||
import org.osmdroid.views.MapView
|
|
||||||
import org.osmdroid.views.overlay.FolderOverlay
|
|
||||||
import org.osmdroid.views.overlay.Marker
|
|
||||||
import org.osmdroid.views.overlay.Polyline
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
|
||||||
class MapFragment : Fragment(R.layout.fragment_map) {
|
|
||||||
|
|
||||||
private val viewModel: MapViewModel by viewModels()
|
|
||||||
private val navArgs: MapFragmentArgs by navArgs()
|
|
||||||
private val minLat = MapView.getTileSystem().minLatitude
|
|
||||||
private val maxLat = MapView.getTileSystem().maxLatitude
|
|
||||||
private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
||||||
strokeWidth = 3f
|
|
||||||
style = Paint.Style.STROKE
|
|
||||||
color = Color.RED
|
|
||||||
strokeCap = Paint.Cap.ROUND
|
|
||||||
strokeJoin = Paint.Join.ROUND
|
|
||||||
}
|
|
||||||
private val footprintPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
||||||
strokeWidth = 3f
|
|
||||||
style = Paint.Style.FILL_AND_STROKE
|
|
||||||
color = Color.parseColor("#FFE082")
|
|
||||||
}
|
|
||||||
private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
||||||
textSize = 36f
|
|
||||||
style = Paint.Style.FILL
|
|
||||||
color = Color.parseColor("#CCFFFFFF")
|
|
||||||
setShadowLayer(3f, 3f, 3f, Color.BLACK)
|
|
||||||
}
|
|
||||||
private val labelRect = Rect()
|
|
||||||
private lateinit var binding: FragmentMapBinding
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
binding = FragmentMapBinding.bind(view)
|
|
||||||
setupComponents()
|
|
||||||
setupObservers()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupComponents() {
|
|
||||||
val context = requireContext()
|
|
||||||
val preferences = context.getSharedPreferences("default", Context.MODE_PRIVATE)
|
|
||||||
Configuration.getInstance().load(context, preferences)
|
|
||||||
binding.run {
|
|
||||||
mapView.apply {
|
|
||||||
setMultiTouchControls(true)
|
|
||||||
setTileSource(TileSourceFactory.WIKIMEDIA)
|
|
||||||
minZoomLevel = getMinZoom(resources.displayMetrics.heightPixels) + 0.25
|
|
||||||
maxZoomLevel = 5.75
|
|
||||||
controller.setZoom(minZoomLevel + 0.25)
|
|
||||||
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
|
|
||||||
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
|
|
||||||
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
|
|
||||||
overlayManager.tilesOverlay.setColorFilter(getColorFilter())
|
|
||||||
setScrollableAreaLimitLatitude(maxLat, minLat, 0)
|
|
||||||
// add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons
|
|
||||||
overlays.addAll(Array(4) { FolderOverlay() })
|
|
||||||
}
|
|
||||||
mapBtnBack.clickWithDebounce { findNavController().navigateUp() }
|
|
||||||
mapBtnPrev.setOnClickListener { viewModel.scrollSelection(true) }
|
|
||||||
mapBtnNext.setOnClickListener { viewModel.scrollSelection(false) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupObservers() {
|
|
||||||
viewModel.selectDefaultSatellite(navArgs.catNum)
|
|
||||||
viewModel.stationPos.observe(viewLifecycleOwner) { handleStationPos(it) }
|
|
||||||
viewModel.positions.observe(viewLifecycleOwner) { handlePositions(it) }
|
|
||||||
viewModel.track.observe(viewLifecycleOwner) { handleTrack(it) }
|
|
||||||
viewModel.footprint.observe(viewLifecycleOwner) { handleFootprint(it) }
|
|
||||||
viewModel.mapData.observe(viewLifecycleOwner) { handleMapData(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleStationPos(stationPos: GeoPos) {
|
|
||||||
binding.apply {
|
|
||||||
Marker(mapView).apply {
|
|
||||||
setInfoWindow(null)
|
|
||||||
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
|
|
||||||
icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_position)
|
|
||||||
position = GeoPoint(stationPos.lat, stationPos.lon)
|
|
||||||
mapView.overlays[0] = this
|
|
||||||
mapView.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handlePositions(posMap: Map<Satellite, GeoPos>) {
|
|
||||||
binding.apply {
|
|
||||||
val markers = FolderOverlay()
|
|
||||||
posMap.entries.forEach {
|
|
||||||
Marker(mapView).apply {
|
|
||||||
setInfoWindow(null)
|
|
||||||
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
|
|
||||||
icon = getCustomTextIcon(it.key.data.name)
|
|
||||||
try {
|
|
||||||
position = GeoPoint(it.value.lat, it.value.lon)
|
|
||||||
} catch (exception: IllegalArgumentException) {
|
|
||||||
println(exception.stackTraceToString())
|
|
||||||
}
|
|
||||||
setOnMarkerClickListener { _, _ ->
|
|
||||||
viewModel.selectSatellite(it.key)
|
|
||||||
return@setOnMarkerClickListener true
|
|
||||||
}
|
|
||||||
markers.add(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mapView.overlays[3] = markers
|
|
||||||
mapView.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getCustomTextIcon(textLabel: String): Drawable {
|
|
||||||
textPaint.getTextBounds(textLabel, 0, textLabel.length, labelRect)
|
|
||||||
val iconSize = 8f
|
|
||||||
val width = labelRect.width() + iconSize * 2f
|
|
||||||
val height = textPaint.textSize * 3f + iconSize * 2f
|
|
||||||
val bitmap = Bitmap.createBitmap(width.toInt(), height.toInt(), Bitmap.Config.ARGB_8888)
|
|
||||||
Canvas(bitmap).run {
|
|
||||||
drawCircle(width / 2f, height / 2f, iconSize, textPaint)
|
|
||||||
drawText(textLabel, iconSize / 2f, height - iconSize, textPaint)
|
|
||||||
}
|
|
||||||
return BitmapDrawable(binding.mapView.context.resources, bitmap)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleTrack(satTrack: List<List<GeoPos>>) {
|
|
||||||
val center = GeoPoint(satTrack[0][0].lat, satTrack[0][0].lon)
|
|
||||||
val trackOverlay = FolderOverlay()
|
|
||||||
satTrack.forEach { track ->
|
|
||||||
val trackPoints = track.map { GeoPoint(it.lat, it.lon) }
|
|
||||||
Polyline().apply {
|
|
||||||
try {
|
|
||||||
setPoints(trackPoints)
|
|
||||||
outlinePaint.set(trackPaint)
|
|
||||||
trackOverlay.add(this)
|
|
||||||
} catch (exception: IllegalArgumentException) {
|
|
||||||
println(exception.stackTraceToString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.mapView.overlays[1] = trackOverlay
|
|
||||||
binding.mapView.controller.animateTo(center)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleFootprint(satPos: SatPos) {
|
|
||||||
val footprintPoints = satPos.getRangeCircle().map { GeoPoint(it.lat, it.lon) }
|
|
||||||
val footprintOverlay = Polyline().apply {
|
|
||||||
outlinePaint.set(footprintPaint)
|
|
||||||
try {
|
|
||||||
setPoints(footprintPoints)
|
|
||||||
} catch (exception: IllegalArgumentException) {
|
|
||||||
println(exception.stackTraceToString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.mapView.overlays[2] = footprintOverlay
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleMapData(mapData: MapData) {
|
|
||||||
binding.apply {
|
|
||||||
mapTimer.text = mapData.aosTime
|
|
||||||
mapDataPeriod.text = String.format(getString(R.string.map_period, mapData.period))
|
|
||||||
mapDataPhase.text = String.format(getString(R.string.map_phase), mapData.phase)
|
|
||||||
mapAzimuth.text = String.format(getString(R.string.map_azimuth), mapData.azimuth)
|
|
||||||
mapElevation.text = String.format(getString(R.string.map_elevation), mapData.elevation)
|
|
||||||
mapDataAlt.text = String.format(getString(R.string.map_altitude), mapData.altitude)
|
|
||||||
mapDataDst.text = String.format(getString(R.string.map_distance), mapData.range)
|
|
||||||
mapDataLat.text =
|
|
||||||
String.format(getString(R.string.map_latitude), mapData.osmPos.lat)
|
|
||||||
mapDataLon.text =
|
|
||||||
String.format(getString(R.string.map_longitude), mapData.osmPos.lon)
|
|
||||||
mapDataQth.text = String.format(getString(R.string.map_qth), mapData.qthLoc)
|
|
||||||
mapDataVel.text = String.format(getString(R.string.map_velocity), mapData.velocity)
|
|
||||||
if (mapData.eclipsed) {
|
|
||||||
mapDataVisibility.text = getString(R.string.map_eclipsed)
|
|
||||||
} else {
|
|
||||||
mapDataVisibility.text = getString(R.string.map_visible)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.mapView.invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getColorFilter(): ColorMatrixColorFilter {
|
|
||||||
val grayScaleMatrix = ColorMatrix().apply { setSaturation(0f) }
|
|
||||||
val negativeMatrix = ColorMatrix(
|
|
||||||
floatArrayOf(
|
|
||||||
-1f, 0f, 0f, 0f, 255f,
|
|
||||||
0f, -1f, 0f, 0f, 255f,
|
|
||||||
0f, 0f, -1f, 0f, 255f,
|
|
||||||
0f, 0f, 0f, 1f, 0f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
negativeMatrix.preConcat(grayScaleMatrix)
|
|
||||||
return ColorMatrixColorFilter(negativeMatrix)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getMinZoom(screenHeight: Int): Double {
|
|
||||||
return MapView.getTileSystem().getLatitudeZoom(maxLat, minLat, screenHeight)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
package com.rtbishop.look4sat.presentation.mapScreen
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.ElevatedCard
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import com.rtbishop.look4sat.R
|
||||||
|
import com.rtbishop.look4sat.domain.predict.GeoPos
|
||||||
|
import com.rtbishop.look4sat.domain.predict.SatPos
|
||||||
|
import com.rtbishop.look4sat.domain.predict.Satellite
|
||||||
|
import org.osmdroid.config.Configuration
|
||||||
|
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
|
||||||
|
import org.osmdroid.util.GeoPoint
|
||||||
|
import org.osmdroid.views.CustomZoomButtonsController
|
||||||
|
import org.osmdroid.views.MapView
|
||||||
|
import org.osmdroid.views.overlay.FolderOverlay
|
||||||
|
import org.osmdroid.views.overlay.Marker
|
||||||
|
import org.osmdroid.views.overlay.Polyline
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
private val minLat = MapView.getTileSystem().minLatitude
|
||||||
|
private val maxLat = MapView.getTileSystem().maxLatitude
|
||||||
|
private val trackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
strokeWidth = 3f
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
color = Color.RED
|
||||||
|
strokeCap = Paint.Cap.ROUND
|
||||||
|
strokeJoin = Paint.Join.ROUND
|
||||||
|
}
|
||||||
|
private val footprintPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
strokeWidth = 3f
|
||||||
|
style = Paint.Style.FILL_AND_STROKE
|
||||||
|
color = Color.parseColor("#FFE082")
|
||||||
|
}
|
||||||
|
private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
textSize = 36f
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
color = Color.parseColor("#CCFFFFFF")
|
||||||
|
setShadowLayer(3f, 3f, 3f, Color.BLACK)
|
||||||
|
}
|
||||||
|
private val labelRect = Rect()
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MapScreen(viewModel: MapViewModel = hiltViewModel()) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
Configuration.getInstance().load(context, viewModel.getPreferences())
|
||||||
|
viewModel.selectDefaultSatellite(-1)
|
||||||
|
val stationPos = viewModel.stationPos.observeAsState()
|
||||||
|
val positions = viewModel.positions.observeAsState()
|
||||||
|
val satTrack = viewModel.track.observeAsState()
|
||||||
|
val footprint = viewModel.footprint.observeAsState()
|
||||||
|
val positionClick = { satellite: Satellite -> viewModel.selectSatellite(satellite) }
|
||||||
|
Timber.d("MapScreen recomposition")
|
||||||
|
Column(modifier = Modifier.padding(6.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
|
||||||
|
ElevatedCard(modifier = Modifier.fillMaxSize()) {
|
||||||
|
MapView(modifier = Modifier.fillMaxSize()) { mapView ->
|
||||||
|
Timber.d("MapView recomposition")
|
||||||
|
stationPos.value?.let { setStationPosition(it, mapView) }
|
||||||
|
positions.value?.let { setPositions(it, mapView, positionClick) }
|
||||||
|
satTrack.value?.let { setSatelliteTrack(it, mapView) }
|
||||||
|
footprint.value?.let { setFootprint(it, mapView) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setStationPosition(stationPos: GeoPos, mapView: MapView) {
|
||||||
|
Marker(mapView).apply {
|
||||||
|
setInfoWindow(null)
|
||||||
|
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
|
||||||
|
icon = ContextCompat.getDrawable(mapView.context, R.drawable.ic_position)
|
||||||
|
position = GeoPoint(stationPos.lat, stationPos.lon)
|
||||||
|
mapView.overlays[0] = this
|
||||||
|
mapView.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPositions(
|
||||||
|
posMap: Map<Satellite, GeoPos>, mapView: MapView, action: (Satellite) -> Unit
|
||||||
|
) {
|
||||||
|
val markers = FolderOverlay()
|
||||||
|
posMap.entries.forEach {
|
||||||
|
Marker(mapView).apply {
|
||||||
|
setInfoWindow(null)
|
||||||
|
setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER)
|
||||||
|
icon = getCustomTextIcon(it.key.data.name, mapView)
|
||||||
|
try {
|
||||||
|
position = GeoPoint(it.value.lat, it.value.lon)
|
||||||
|
} catch (exception: IllegalArgumentException) {
|
||||||
|
println(exception.stackTraceToString())
|
||||||
|
}
|
||||||
|
setOnMarkerClickListener { _, _ ->
|
||||||
|
action(it.key)
|
||||||
|
return@setOnMarkerClickListener true
|
||||||
|
}
|
||||||
|
markers.add(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapView.overlays[3] = markers
|
||||||
|
mapView.invalidate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCustomTextIcon(textLabel: String, mapView: MapView): Drawable {
|
||||||
|
textPaint.getTextBounds(textLabel, 0, textLabel.length, labelRect)
|
||||||
|
val iconSize = 8f
|
||||||
|
val width = labelRect.width() + iconSize * 2f
|
||||||
|
val height = textPaint.textSize * 3f + iconSize * 2f
|
||||||
|
val bitmap = Bitmap.createBitmap(width.toInt(), height.toInt(), Bitmap.Config.ARGB_8888)
|
||||||
|
Canvas(bitmap).run {
|
||||||
|
drawCircle(width / 2f, height / 2f, iconSize, textPaint)
|
||||||
|
drawText(textLabel, iconSize / 2f, height - iconSize, textPaint)
|
||||||
|
}
|
||||||
|
return BitmapDrawable(mapView.context.resources, bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setSatelliteTrack(satTrack: List<List<GeoPos>>, mapView: MapView) {
|
||||||
|
// val center = GeoPoint(satTrack[0][0].lat, satTrack[0][0].lon)
|
||||||
|
val trackOverlay = FolderOverlay()
|
||||||
|
satTrack.forEach { track ->
|
||||||
|
val trackPoints = track.map { GeoPoint(it.lat, it.lon) }
|
||||||
|
Polyline().apply {
|
||||||
|
try {
|
||||||
|
setPoints(trackPoints)
|
||||||
|
outlinePaint.set(trackPaint)
|
||||||
|
trackOverlay.add(this)
|
||||||
|
} catch (exception: IllegalArgumentException) {
|
||||||
|
println(exception.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapView.overlays[1] = trackOverlay
|
||||||
|
// mapView.controller.animateTo(center)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setFootprint(satPos: SatPos, mapView: MapView) {
|
||||||
|
val footprintPoints = satPos.getRangeCircle().map { GeoPoint(it.lat, it.lon) }
|
||||||
|
val footprintOverlay = Polyline().apply {
|
||||||
|
outlinePaint.set(footprintPaint)
|
||||||
|
try {
|
||||||
|
setPoints(footprintPoints)
|
||||||
|
} catch (exception: IllegalArgumentException) {
|
||||||
|
println(exception.stackTraceToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapView.overlays[2] = footprintOverlay
|
||||||
|
}
|
||||||
|
|
||||||
|
//private fun handleMapData(mapData: MapData) {
|
||||||
|
// binding.apply {
|
||||||
|
// mapTimer.text = mapData.aosTime
|
||||||
|
// mapDataPeriod.text = String.format(getString(R.string.map_period, mapData.period))
|
||||||
|
// mapDataPhase.text = String.format(getString(R.string.map_phase), mapData.phase)
|
||||||
|
// mapAzimuth.text = String.format(getString(R.string.map_azimuth), mapData.azimuth)
|
||||||
|
// mapElevation.text = String.format(getString(R.string.map_elevation), mapData.elevation)
|
||||||
|
// mapDataAlt.text = String.format(getString(R.string.map_altitude), mapData.altitude)
|
||||||
|
// mapDataDst.text = String.format(getString(R.string.map_distance), mapData.range)
|
||||||
|
// mapDataLat.text =
|
||||||
|
// String.format(getString(R.string.map_latitude), mapData.osmPos.lat)
|
||||||
|
// mapDataLon.text =
|
||||||
|
// String.format(getString(R.string.map_longitude), mapData.osmPos.lon)
|
||||||
|
// mapDataQth.text = String.format(getString(R.string.map_qth), mapData.qthLoc)
|
||||||
|
// mapDataVel.text = String.format(getString(R.string.map_velocity), mapData.velocity)
|
||||||
|
// if (mapData.eclipsed) {
|
||||||
|
// mapDataVisibility.text = getString(R.string.map_eclipsed)
|
||||||
|
// } else {
|
||||||
|
// mapDataVisibility.text = getString(R.string.map_visible)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// binding.mapView.invalidate()
|
||||||
|
//}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MapView(modifier: Modifier = Modifier, update: ((map: MapView) -> Unit)? = null) {
|
||||||
|
val mapView = rememberMapViewWithLifecycle()
|
||||||
|
AndroidView({ mapView }, modifier) { update?.invoke(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun rememberMapViewWithLifecycle(context: Context = LocalContext.current): MapView {
|
||||||
|
// add clipToOutline = true if needed
|
||||||
|
val mapView = remember { MapView(context).apply { id = R.id.osm_map_view } }.apply {
|
||||||
|
setMultiTouchControls(true)
|
||||||
|
setTileSource(TileSourceFactory.WIKIMEDIA)
|
||||||
|
minZoomLevel = getMinZoom(resources.displayMetrics.heightPixels) + 0.25
|
||||||
|
maxZoomLevel = 5.75
|
||||||
|
controller.setZoom(minZoomLevel + 0.25)
|
||||||
|
zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER)
|
||||||
|
overlayManager.tilesOverlay.loadingBackgroundColor = Color.TRANSPARENT
|
||||||
|
overlayManager.tilesOverlay.loadingLineColor = Color.TRANSPARENT
|
||||||
|
overlayManager.tilesOverlay.setColorFilter(getColorFilter())
|
||||||
|
setScrollableAreaLimitLatitude(maxLat, minLat, 0)
|
||||||
|
// add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons
|
||||||
|
overlays.addAll(Array(4) { FolderOverlay() })
|
||||||
|
}
|
||||||
|
// Makes MapView follow the lifecycle of this composable
|
||||||
|
val lifecycleObserver = rememberMapViewLifecycleObserver(mapView)
|
||||||
|
val lifecycle = LocalLifecycleOwner.current.lifecycle
|
||||||
|
DisposableEffect(lifecycle) {
|
||||||
|
lifecycle.addObserver(lifecycleObserver)
|
||||||
|
onDispose { lifecycle.removeObserver(lifecycleObserver) }
|
||||||
|
}
|
||||||
|
return mapView
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun rememberMapViewLifecycleObserver(mapView: MapView) = remember(mapView) {
|
||||||
|
LifecycleEventObserver { _, event ->
|
||||||
|
when (event) {
|
||||||
|
Lifecycle.Event.ON_RESUME -> mapView.onResume()
|
||||||
|
Lifecycle.Event.ON_PAUSE -> mapView.onPause()
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getColorFilter(): ColorMatrixColorFilter {
|
||||||
|
val grayScaleMatrix = ColorMatrix().apply { setSaturation(0f) }
|
||||||
|
val negativeMatrix = ColorMatrix(
|
||||||
|
floatArrayOf(
|
||||||
|
-1f, 0f, 0f, 0f, 255f, 0f, -1f, 0f, 0f, 255f, 0f, 0f, -1f, 0f, 255f, 0f, 0f, 0f, 1f, 0f
|
||||||
|
)
|
||||||
|
)
|
||||||
|
negativeMatrix.preConcat(grayScaleMatrix)
|
||||||
|
return ColorMatrixColorFilter(negativeMatrix)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getMinZoom(screenHeight: Int): Double {
|
||||||
|
return MapView.getTileSystem().getLatitudeZoom(maxLat, minLat, screenHeight)
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.presentation.mapScreen
|
package com.rtbishop.look4sat.presentation.mapScreen
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
import com.rtbishop.look4sat.domain.IDataRepository
|
import com.rtbishop.look4sat.domain.IDataRepository
|
||||||
import com.rtbishop.look4sat.domain.ISatelliteManager
|
import com.rtbishop.look4sat.domain.ISatelliteManager
|
||||||
@@ -36,9 +37,10 @@ import kotlin.math.min
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class MapViewModel @Inject constructor(
|
class MapViewModel @Inject constructor(
|
||||||
private val satelliteManager: ISatelliteManager,
|
private val preferences: SharedPreferences,
|
||||||
private val repository: IDataRepository,
|
private val repository: IDataRepository,
|
||||||
private val settings: ISettingsManager,
|
private val satelliteManager: ISatelliteManager,
|
||||||
|
private val settings: ISettingsManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val stationPosition = settings.loadStationPosition()
|
private val stationPosition = settings.loadStationPosition()
|
||||||
@@ -66,6 +68,8 @@ class MapViewModel @Inject constructor(
|
|||||||
private val _positions = MutableLiveData<Map<Satellite, GeoPos>>()
|
private val _positions = MutableLiveData<Map<Satellite, GeoPos>>()
|
||||||
val positions: LiveData<Map<Satellite, GeoPos>> = _positions
|
val positions: LiveData<Map<Satellite, GeoPos>> = _positions
|
||||||
|
|
||||||
|
fun getPreferences() = preferences
|
||||||
|
|
||||||
fun scrollSelection(decrement: Boolean) {
|
fun scrollSelection(decrement: Boolean) {
|
||||||
if (allSatellites.isNotEmpty()) {
|
if (allSatellites.isNotEmpty()) {
|
||||||
val index = allSatellites.indexOf(selectedSatellite)
|
val index = allSatellites.indexOf(selectedSatellite)
|
||||||
@@ -184,8 +188,19 @@ class MapViewModel @Inject constructor(
|
|||||||
val phase = satPos.phase.toDegrees()
|
val phase = satPos.phase.toDegrees()
|
||||||
val visibility = satPos.eclipsed
|
val visibility = satPos.eclipsed
|
||||||
val satData = MapData(
|
val satData = MapData(
|
||||||
sat.data.catnum, sat.data.name, aosTime, azimuth, elevation, satPos.distance,
|
sat.data.catnum,
|
||||||
satPos.altitude, velocity, qthLoc, osmPos, sat.data.orbitalPeriod, phase, visibility
|
sat.data.name,
|
||||||
|
aosTime,
|
||||||
|
azimuth,
|
||||||
|
elevation,
|
||||||
|
satPos.distance,
|
||||||
|
satPos.altitude,
|
||||||
|
velocity,
|
||||||
|
qthLoc,
|
||||||
|
osmPos,
|
||||||
|
sat.data.orbitalPeriod,
|
||||||
|
phase,
|
||||||
|
visibility
|
||||||
)
|
)
|
||||||
_mapData.postValue(satData)
|
_mapData.postValue(satData)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.presentation.radarScreen
|
package com.rtbishop.look4sat.presentation.radarScreen
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.CalendarContract
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import androidx.navigation.fragment.navArgs
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.SimpleItemAnimator
|
import androidx.recyclerview.widget.SimpleItemAnimator
|
||||||
@@ -32,7 +28,6 @@ import com.rtbishop.look4sat.R
|
|||||||
import com.rtbishop.look4sat.databinding.FragmentRadarBinding
|
import com.rtbishop.look4sat.databinding.FragmentRadarBinding
|
||||||
import com.rtbishop.look4sat.domain.predict.SatPass
|
import com.rtbishop.look4sat.domain.predict.SatPass
|
||||||
import com.rtbishop.look4sat.domain.predict.SatPos
|
import com.rtbishop.look4sat.domain.predict.SatPos
|
||||||
import com.rtbishop.look4sat.presentation.clickWithDebounce
|
|
||||||
import com.rtbishop.look4sat.utility.toDegrees
|
import com.rtbishop.look4sat.utility.toDegrees
|
||||||
import com.rtbishop.look4sat.utility.toTimerString
|
import com.rtbishop.look4sat.utility.toTimerString
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -41,7 +36,6 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||||||
class RadarFragment : Fragment(R.layout.fragment_radar) {
|
class RadarFragment : Fragment(R.layout.fragment_radar) {
|
||||||
|
|
||||||
private val viewModel: RadarViewModel by viewModels()
|
private val viewModel: RadarViewModel by viewModels()
|
||||||
private val navArgs: RadarFragmentArgs by navArgs()
|
|
||||||
private val radioAdapter = RadioAdapter()
|
private val radioAdapter = RadioAdapter()
|
||||||
private var binding: FragmentRadarBinding? = null
|
private var binding: FragmentRadarBinding? = null
|
||||||
private var radarView: RadarView? = null
|
private var radarView: RadarView? = null
|
||||||
@@ -78,7 +72,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupObservers() {
|
private fun setupObservers() {
|
||||||
viewModel.getPass(navArgs.catNum, navArgs.aosTime).observe(viewLifecycleOwner) { pass ->
|
viewModel.getPass(45000, System.currentTimeMillis()).observe(viewLifecycleOwner) { pass ->
|
||||||
binding?.run {
|
binding?.run {
|
||||||
radarView = RadarView(requireContext()).apply {
|
radarView = RadarView(requireContext()).apply {
|
||||||
setShowAim(viewModel.getUseCompass())
|
setShowAim(viewModel.getUseCompass())
|
||||||
@@ -103,24 +97,16 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
|
|||||||
viewModel.orientation.observe(viewLifecycleOwner) { value ->
|
viewModel.orientation.observe(viewLifecycleOwner) { value ->
|
||||||
radarView?.setOrientation(value.first, value.second, value.third)
|
radarView?.setOrientation(value.first, value.second, value.third)
|
||||||
}
|
}
|
||||||
radarBtnBack.clickWithDebounce { findNavController().navigateUp() }
|
// radarBtnBack.clickWithDebounce { findNavController().navigateUp() }
|
||||||
radarBtnMap.clickWithDebounce {
|
// radarBtnMap.clickWithDebounce {
|
||||||
val direction = RadarFragmentDirections.globalToMap(pass.catNum)
|
// val direction = RadarFragmentDirections.globalToMap(pass.catNum)
|
||||||
findNavController().navigate(direction)
|
// findNavController().navigate(direction)
|
||||||
}
|
// }
|
||||||
radarBtnNotify.clickWithDebounce {
|
// radarBtnNotify.isEnabled = false
|
||||||
val intent = Intent(Intent.ACTION_INSERT)
|
// radarBtnSettings.clickWithDebounce {
|
||||||
.setData(CalendarContract.Events.CONTENT_URI)
|
// val direction = RadarFragmentDirections.globalToSettings()
|
||||||
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, pass.aosTime)
|
// findNavController().navigate(direction)
|
||||||
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, pass.losTime)
|
// }
|
||||||
.putExtra(CalendarContract.Events.TITLE, pass.name)
|
|
||||||
.putExtra(CalendarContract.Events.DESCRIPTION, "Look4Sat")
|
|
||||||
startActivity(intent)
|
|
||||||
}
|
|
||||||
radarBtnSettings.clickWithDebounce {
|
|
||||||
val direction = RadarFragmentDirections.globalToSettings()
|
|
||||||
findNavController().navigate(direction)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,7 +136,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) {
|
|||||||
radarTimer.text = millisBeforeEnd.toTimerString()
|
radarTimer.text = millisBeforeEnd.toTimerString()
|
||||||
if (timeNow > satPass.losTime) {
|
if (timeNow > satPass.losTime) {
|
||||||
radarTimer.text = 0L.toTimerString()
|
radarTimer.text = 0L.toTimerString()
|
||||||
findNavController().navigateUp()
|
// findNavController().navigateUp()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else radarTimer.text = 0L.toTimerString()
|
} else radarTimer.text = 0L.toTimerString()
|
||||||
|
|||||||
+1
-2
@@ -26,7 +26,6 @@ import androidx.appcompat.app.AppCompatDialogFragment
|
|||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.databinding.DialogLocatorBinding
|
import com.rtbishop.look4sat.databinding.DialogLocatorBinding
|
||||||
import com.rtbishop.look4sat.domain.ISettingsManager
|
import com.rtbishop.look4sat.domain.ISettingsManager
|
||||||
import com.rtbishop.look4sat.presentation.setNavResult
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -50,7 +49,7 @@ class LocatorDialog : AppCompatDialogFragment() {
|
|||||||
)
|
)
|
||||||
locatorEdit.setText(preferences.loadStationLocator())
|
locatorEdit.setText(preferences.loadStationLocator())
|
||||||
locatorBtnPos.setOnClickListener {
|
locatorBtnPos.setOnClickListener {
|
||||||
setNavResult("locator", locatorEdit.text.toString())
|
// setNavResult("locator", locatorEdit.text.toString())
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
locatorBtnNeg.setOnClickListener { dismiss() }
|
locatorBtnNeg.setOnClickListener { dismiss() }
|
||||||
|
|||||||
+11
-12
@@ -26,7 +26,6 @@ import androidx.appcompat.app.AppCompatDialogFragment
|
|||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.databinding.DialogPositionBinding
|
import com.rtbishop.look4sat.databinding.DialogPositionBinding
|
||||||
import com.rtbishop.look4sat.domain.ISettingsManager
|
import com.rtbishop.look4sat.domain.ISettingsManager
|
||||||
import com.rtbishop.look4sat.presentation.setNavResult
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -52,17 +51,17 @@ class PositionDialog : AppCompatDialogFragment() {
|
|||||||
positionLatEdit.setText(location.lat.toString())
|
positionLatEdit.setText(location.lat.toString())
|
||||||
positionLonEdit.setText(location.lon.toString())
|
positionLonEdit.setText(location.lon.toString())
|
||||||
positionBtnPos.setOnClickListener {
|
positionBtnPos.setOnClickListener {
|
||||||
val latitude = try {
|
// val latitude = try {
|
||||||
positionLatEdit.text.toString().toDouble()
|
// positionLatEdit.text.toString().toDouble()
|
||||||
} catch (exception: Exception) {
|
// } catch (exception: Exception) {
|
||||||
180.0
|
// 180.0
|
||||||
}
|
// }
|
||||||
val longitude = try {
|
// val longitude = try {
|
||||||
positionLonEdit.text.toString().toDouble()
|
// positionLonEdit.text.toString().toDouble()
|
||||||
} catch (exception: Exception) {
|
// } catch (exception: Exception) {
|
||||||
400.0
|
// 400.0
|
||||||
}
|
// }
|
||||||
setNavResult("position", Pair(latitude, longitude))
|
// setNavResult("position", Pair(latitude, longitude))
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
positionBtnNeg.setOnClickListener { dismiss() }
|
positionBtnNeg.setOnClickListener { dismiss() }
|
||||||
|
|||||||
+18
-20
@@ -31,14 +31,12 @@ import androidx.core.widget.doOnTextChanged
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.asLiveData
|
import androidx.lifecycle.asLiveData
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.rtbishop.look4sat.BuildConfig
|
import com.rtbishop.look4sat.BuildConfig
|
||||||
import com.rtbishop.look4sat.R
|
import com.rtbishop.look4sat.R
|
||||||
import com.rtbishop.look4sat.databinding.FragmentSettingsBinding
|
import com.rtbishop.look4sat.databinding.FragmentSettingsBinding
|
||||||
import com.rtbishop.look4sat.domain.model.DataState
|
import com.rtbishop.look4sat.domain.model.DataState
|
||||||
import com.rtbishop.look4sat.domain.predict.GeoPos
|
import com.rtbishop.look4sat.domain.predict.GeoPos
|
||||||
import com.rtbishop.look4sat.presentation.clickWithDebounce
|
import com.rtbishop.look4sat.presentation.clickWithDebounce
|
||||||
import com.rtbishop.look4sat.presentation.getNavResult
|
|
||||||
import com.rtbishop.look4sat.utility.isValidIPv4
|
import com.rtbishop.look4sat.utility.isValidIPv4
|
||||||
import com.rtbishop.look4sat.utility.isValidPort
|
import com.rtbishop.look4sat.utility.isValidPort
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -79,7 +77,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
binding = FragmentSettingsBinding.bind(view).apply {
|
binding = FragmentSettingsBinding.bind(view).apply {
|
||||||
settingsBtnBack.clickWithDebounce { findNavController().navigateUp() }
|
// settingsBtnBack.clickWithDebounce { findNavController().navigateUp() }
|
||||||
settingsScroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, y, _, newY ->
|
settingsScroll.setOnScrollChangeListener(NestedScrollView.OnScrollChangeListener { _, _, y, _, newY ->
|
||||||
if (y > newY) settingsFab.hide() else settingsFab.show()
|
if (y > newY) settingsFab.hide() else settingsFab.show()
|
||||||
})
|
})
|
||||||
@@ -115,20 +113,20 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||||||
settingsLocation.locationBtnGps.clickWithDebounce {
|
settingsLocation.locationBtnGps.clickWithDebounce {
|
||||||
locationRequest.launch(arrayOf(locationFine, locationCoarse))
|
locationRequest.launch(arrayOf(locationFine, locationCoarse))
|
||||||
}
|
}
|
||||||
settingsLocation.locationBtnManual.clickWithDebounce {
|
// settingsLocation.locationBtnManual.clickWithDebounce {
|
||||||
val action = SettingsFragmentDirections.globalToPosition()
|
// val action = SettingsFragmentDirections.globalToPosition()
|
||||||
findNavController().navigate(action)
|
// findNavController().navigate(action)
|
||||||
}
|
// }
|
||||||
settingsLocation.locationBtnQth.clickWithDebounce {
|
// settingsLocation.locationBtnQth.clickWithDebounce {
|
||||||
val action = SettingsFragmentDirections.globalToLocator()
|
// val action = SettingsFragmentDirections.globalToLocator()
|
||||||
findNavController().navigate(action)
|
// findNavController().navigate(action)
|
||||||
}
|
// }
|
||||||
getNavResult<Pair<Double, Double>>(R.id.nav_settings, "position") { position ->
|
// getNavResult<Pair<Double, Double>>(R.id.nav_settings, "position") { position ->
|
||||||
viewModel.setStationPosition(position.first, position.second)
|
// viewModel.setStationPosition(position.first, position.second)
|
||||||
}
|
// }
|
||||||
getNavResult<String>(R.id.nav_settings, "locator") { locator ->
|
// getNavResult<String>(R.id.nav_settings, "locator") { locator ->
|
||||||
viewModel.setPositionFromQth(locator)
|
// viewModel.setPositionFromQth(locator)
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,9 +144,9 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) {
|
|||||||
val radiosFormat = getString(R.string.data_radios)
|
val radiosFormat = getString(R.string.data_radios)
|
||||||
settingsData.dataRadios.text = String.format(radiosFormat, number)
|
settingsData.dataRadios.text = String.format(radiosFormat, number)
|
||||||
}
|
}
|
||||||
getNavResult<List<String>>(R.id.nav_settings, "sources") {
|
// getNavResult<List<String>>(R.id.nav_settings, "sources") {
|
||||||
viewModel.updateFromWeb()
|
// viewModel.updateFromWeb()
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#000000"
|
android:autoMirrored="true"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#000000"
|
android:autoMirrored="true"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
<vector android:height="24dp" android:viewportHeight="512"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:viewportWidth="512" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
android:width="24dp"
|
||||||
<path android:fillColor="#000000" android:pathData="M495.3,425.74H255.18c-3.58,-52 -23.78,-100.69 -58.12,-140.07L401.37,81.37c6.52,-6.52 6.52,-17.09 0,-23.61c-6.52,-6.52 -17.09,-6.52 -23.61,0L162.23,273.29L4.89,430.63c-4.77,4.77 -6.21,11.96 -3.62,18.2s8.67,10.3 15.42,10.3h222.61h256c9.22,0 16.7,-7.47 16.7,-16.7C512,433.21 504.52,425.74 495.3,425.74z"/>
|
android:height="24dp"
|
||||||
|
android:autoMirrored="true"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="512"
|
||||||
|
android:viewportHeight="512">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000000"
|
||||||
|
android:pathData="M495.3,425.74H255.18c-3.58,-52 -23.78,-100.69 -58.12,-140.07L401.37,81.37c6.52,-6.52 6.52,-17.09 0,-23.61c-6.52,-6.52 -17.09,-6.52 -23.61,0L162.23,273.29L4.89,430.63c-4.77,4.77 -6.21,11.96 -3.62,18.2s8.67,10.3 15.42,10.3h222.61h256c9.22,0 16.7,-7.47 16.7,-16.7C512,433.21 504.52,425.74 495.3,425.74z" />
|
||||||
</vector>
|
</vector>
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:tint="#000000"
|
android:autoMirrored="true"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="24"
|
android:viewportWidth="24"
|
||||||
android:viewportHeight="24">
|
android:viewportHeight="24">
|
||||||
<path
|
<path
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:tint="#000000"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M4.25,5.61C6.27,8.2 10,13 10,13v6c0,0.55 0.45,1 1,1h2c0.55,0 1,-0.45 1,-1v-6c0,0 3.72,-4.8 5.74,-7.39C20.25,4.95 19.78,4 18.95,4H5.04C4.21,4 3.74,4.95 4.25,5.61z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:tint="?attr/colorControlNormal"
|
|
||||||
android:viewportWidth="512"
|
|
||||||
android:viewportHeight="512">
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M437.02,74.98C388.67,26.63 324.38,0 256,0S123.33,26.63 74.98,74.98C26.63,123.33 0,187.62 0,256S26.63,388.67 74.98,437.02C123.33,485.37 187.62,512 256,512c68.38,0 132.67,-26.63 181.02,-74.98C485.37,388.67 512,324.38 512,256S485.37,123.33 437.02,74.98zM415.51,415.51c-42.61,42.61 -99.26,66.07 -159.51,66.07c-60.26,0 -116.9,-23.47 -159.51,-66.07C53.88,372.9 30.42,316.26 30.42,256S53.88,139.1 96.49,96.49C139.1,53.88 195.74,30.42 256,30.42c55.16,0 107.29,19.67 148.39,55.68l-41.21,41.21C333.14,102.2 295.63,88.52 256,88.52c-92.35,0 -167.48,75.13 -167.48,167.48S163.65,423.48 256,423.48s167.48,-75.13 167.48,-167.48h-30.42c0,75.57 -61.49,137.06 -137.06,137.06S118.94,331.58 118.94,256S180.43,118.94 256,118.94c31.49,0 61.35,10.56 85.57,29.98l-41.53,41.53c-12.91,-8.72 -28.12,-13.4 -44.04,-13.4c-43.53,0 -78.95,35.42 -78.95,78.95c0,43.53 35.42,78.95 78.95,78.95s78.95,-35.42 78.95,-78.95h-30.42c0,26.76 -21.77,48.54 -48.54,48.54S207.46,282.76 207.46,256c0,-26.76 21.77,-48.54 48.54,-48.54c7.72,0 15.15,1.8 21.84,5.18l-32.6,32.6l21.51,21.51l159.15,-159.15c36.01,41.11 55.68,93.24 55.68,148.39C481.58,316.26 458.12,372.9 415.51,415.51z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M396.71,197.71m-18.42,0a18.42,18.42 0,1 1,36.85 0a18.42,18.42 0,1 1,-36.85 0" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
|
android:autoMirrored="true"
|
||||||
android:tint="?attr/colorControlNormal"
|
android:tint="?attr/colorControlNormal"
|
||||||
android:viewportWidth="287.97"
|
android:viewportWidth="287.97"
|
||||||
android:viewportHeight="287.97">
|
android:viewportHeight="287.97">
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:tint="?attr/colorControlNormal"
|
|
||||||
android:viewportWidth="503.61"
|
|
||||||
android:viewportHeight="503.61">
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M251.8,0C113.31,0 0,112.47 0,251.8s113.31,251.8 251.8,251.8s251.8,-113.31 251.8,-251.8S390.3,0 251.8,0zM251.8,486.82c-129.26,0 -235.02,-105.76 -235.02,-235.02S122.54,16.79 251.8,16.79S486.82,122.54 486.82,251.8S381.06,486.82 251.8,486.82z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M251.8,83.93c-92.33,0 -167.87,75.54 -167.87,167.87c0,9.23 0.84,18.47 2.52,26.86c0,4.2 5.04,7.55 9.23,6.72c4.2,0 7.55,-5.04 6.72,-9.23c-0.84,-7.55 -1.68,-15.95 -1.68,-24.34c0,-83.1 67.99,-151.08 151.08,-151.08s151.08,67.99 151.08,151.08s-67.99,151.08 -151.08,151.08c-37.55,0 -72.9,-13.13 -100.64,-38.69l47.21,-47.21c15.02,12.31 33.58,18.75 53.43,18.75c46.16,0 83.93,-37.77 83.93,-83.93s-37.77,-83.93 -83.93,-83.93s-83.93,37.77 -83.93,83.93c0,5.04 0,9.23 1.68,13.43c0,4.2 5.04,7.55 9.23,6.72c4.2,0 7.55,-5.04 6.72,-9.23c-0.84,-3.36 -0.84,-7.55 -0.84,-10.91c0,-36.93 30.22,-67.15 67.15,-67.15s67.15,30.22 67.15,67.15c0,36.93 -30.22,67.15 -67.15,67.15c-15.56,0 -29.91,-4.78 -41.58,-13.81l24.48,-24.48c5.02,2.99 10.87,4.72 17.1,4.72c18.47,0 33.57,-15.11 33.57,-33.57s-15.11,-33.57 -33.57,-33.57s-33.57,15.11 -33.57,33.57c0,6.24 1.73,12.09 4.72,17.1l-30.74,30.74c0,0 0,0 0,0s0,0 0,0l-58.75,58.75c0,0 0,0 0,0s0,0 0,0l-30.22,30.22c-3.36,3.36 -3.36,8.39 0,11.75c1.68,1.68 3.36,2.52 5.88,2.52c2.52,0 4.2,-0.84 5.88,-2.52l24.41,-24.41c30.46,28.22 70.69,43.72 112.4,43.72c92.33,0 167.87,-74.7 167.87,-167.87C419.67,159.48 344.13,83.93 251.8,83.93zM251.8,235.02c9.23,0 16.79,7.55 16.79,16.79c0,9.23 -7.55,16.79 -16.79,16.79c-4.18,0 -8.01,-1.56 -10.95,-4.11c-0.24,-0.32 -0.5,-0.63 -0.8,-0.93s-0.61,-0.56 -0.93,-0.8c-2.55,-2.95 -4.11,-6.77 -4.11,-10.95C235.02,242.57 242.57,235.02 251.8,235.02z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M92.33,159.48c0,-9.23 -7.55,-16.79 -16.79,-16.79s-16.79,7.55 -16.79,16.79s7.55,16.79 16.79,16.79S92.33,168.71 92.33,159.48z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M318.95,327.34c0,9.23 7.55,16.79 16.79,16.79c9.23,0 16.79,-7.55 16.79,-16.79c0,-9.23 -7.55,-16.79 -16.79,-16.79C326.51,310.56 318.95,318.11 318.95,327.34z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#000000"
|
|
||||||
android:pathData="M360.92,109.11c9.23,0 16.79,-7.55 16.79,-16.79s-7.55,-16.79 -16.79,-16.79s-16.79,7.55 -16.79,16.79S351.68,109.11 360.92,109.11z" />
|
|
||||||
</vector>
|
|
||||||
@@ -1,242 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:transitionGroup="true"
|
|
||||||
android:keepScreenOn="true">
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:id="@+id/map_toolbar"
|
|
||||||
style="@style/Toolbar"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/map_btn_back"
|
|
||||||
style="@style/ToolbarButton"
|
|
||||||
android:layout_gravity="start|center_vertical"
|
|
||||||
android:contentDescription="@string/btn_back"
|
|
||||||
android:src="@drawable/ic_back" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_timer"
|
|
||||||
style="@style/ToolbarTimer" />
|
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:id="@+id/map_card"
|
|
||||||
style="@style/SurfaceCard"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_marginStart="@dimen/view_default_margin"
|
|
||||||
android:layout_marginTop="@dimen/view_default_margin"
|
|
||||||
android:layout_marginEnd="@dimen/view_default_margin"
|
|
||||||
android:layout_marginBottom="@dimen/view_default_margin"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_card_info"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_toolbar">
|
|
||||||
|
|
||||||
<org.osmdroid.views.MapView
|
|
||||||
android:id="@+id/map_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent" />
|
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_copyright"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="2dp"
|
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:layout_marginEnd="2dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center"
|
|
||||||
android:includeFontPadding="false"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/map_copyright"
|
|
||||||
android:textColor="@color/textMain"
|
|
||||||
android:textSize="@dimen/text_size_copyright"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_card"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_card"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/map_card" />
|
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
android:id="@+id/map_card_info"
|
|
||||||
style="@style/SurfaceCard"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/view_default_margin"
|
|
||||||
android:layout_marginEnd="@dimen/view_default_margin"
|
|
||||||
android:layout_marginBottom="@dimen/view_default_margin"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_coordinator"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_azimuth"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="@string/map_azimuth"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_data_alt"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_data_period"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_data_period" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_lat"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="@string/map_latitude"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_data_qth"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_data_alt"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_data_alt" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_lon"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/map_longitude"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_data_lat"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_data_dst" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_alt"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:text="@string/map_altitude"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_data_lat"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_azimuth"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_azimuth" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_dst"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/map_distance"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_data_alt"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_elevation" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_elevation"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/map_elevation"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_azimuth"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_data_phase" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_period"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:text="@string/map_period"
|
|
||||||
app:layout_constraintBottom_toTopOf="@+id/map_azimuth"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_phase"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
android:text="@string/map_phase"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_data_period"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_qth"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/map_qth"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_data_lat"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/map_data_lat" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_vel"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/map_velocity"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_data_qth"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_data_lon" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
android:id="@+id/map_coordinator"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
|
||||||
|
|
||||||
<com.google.android.material.bottomappbar.BottomAppBar
|
|
||||||
android:id="@+id/map_bottom_bar"
|
|
||||||
style="@style/BottomBar" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/map_btn_prev"
|
|
||||||
style="@style/NormalButton"
|
|
||||||
android:layout_width="@dimen/button_width_max"
|
|
||||||
android:layout_marginStart="@dimen/button_margin_side"
|
|
||||||
android:text="@string/btn_prev"
|
|
||||||
app:icon="@drawable/ic_prev"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/map_coordinator"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/map_coordinator"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/map_coordinator" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/map_data_visibility"
|
|
||||||
style="@style/WorldMapText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center_horizontal"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:text="@string/map_visible"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_btn_prev"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/map_btn_next"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/map_btn_prev" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/map_btn_next"
|
|
||||||
style="@style/NormalButton"
|
|
||||||
android:layout_width="@dimen/button_width_max"
|
|
||||||
android:layout_marginEnd="@dimen/button_margin_side"
|
|
||||||
android:text="@string/btn_next"
|
|
||||||
app:icon="@drawable/ic_next"
|
|
||||||
app:iconGravity="end"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@+id/map_btn_prev"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+id/map_coordinator" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.osmdroid.views.MapView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/osm_map_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_entries"
|
|
||||||
android:icon="@drawable/ic_satellite"
|
|
||||||
android:title="@string/menu_satellites" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_passes"
|
|
||||||
android:icon="@drawable/ic_list"
|
|
||||||
android:title="@string/menu_passes" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_map"
|
|
||||||
android:icon="@drawable/ic_map"
|
|
||||||
android:title="@string/menu_map" />
|
|
||||||
<item
|
|
||||||
android:id="@+id/nav_settings"
|
|
||||||
android:icon="@drawable/ic_settings"
|
|
||||||
android:title="@string/menu_settings" />
|
|
||||||
</menu>
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<navigation 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:id="@+id/nav_root"
|
|
||||||
app:startDestination="@id/nav_radar">
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_radar"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.radarScreen.RadarFragment"
|
|
||||||
tools:layout="@layout/fragment_radar">
|
|
||||||
<argument
|
|
||||||
android:name="catNum"
|
|
||||||
android:defaultValue="-1"
|
|
||||||
app:argType="integer" />
|
|
||||||
<argument
|
|
||||||
android:name="aosTime"
|
|
||||||
android:defaultValue="0L"
|
|
||||||
app:argType="long" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_map"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.mapScreen.MapFragment"
|
|
||||||
tools:layout="@layout/fragment_map">
|
|
||||||
<argument
|
|
||||||
android:name="catNum"
|
|
||||||
android:defaultValue="-1"
|
|
||||||
app:argType="integer" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
|
||||||
android:id="@+id/nav_settings"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.settingsScreen.SettingsFragment"
|
|
||||||
tools:layout="@layout/fragment_settings" />
|
|
||||||
<dialog
|
|
||||||
android:id="@+id/nav_modes"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.entriesScreen.ModesDialog"
|
|
||||||
tools:layout="@layout/dialog_modes" />
|
|
||||||
<dialog
|
|
||||||
android:id="@+id/nav_position"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.settingsScreen.PositionDialog"
|
|
||||||
tools:layout="@layout/dialog_position" />
|
|
||||||
<dialog
|
|
||||||
android:id="@+id/nav_locator"
|
|
||||||
android:name="com.rtbishop.look4sat.presentation.settingsScreen.LocatorDialog"
|
|
||||||
tools:layout="@layout/dialog_locator" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_entries"
|
|
||||||
app:destination="@id/nav_entries"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_passes"
|
|
||||||
app:destination="@id/nav_passes"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_radar"
|
|
||||||
app:destination="@id/nav_radar"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_map"
|
|
||||||
app:destination="@id/nav_map"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_settings"
|
|
||||||
app:destination="@id/nav_settings"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_position"
|
|
||||||
app:destination="@id/nav_position"
|
|
||||||
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" />
|
|
||||||
<action
|
|
||||||
android:id="@+id/global_to_locator"
|
|
||||||
app:destination="@id/nav_locator"
|
|
||||||
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" />
|
|
||||||
</navigation>
|
|
||||||
Reference in new issue
Block a user