diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/EntriesDao.kt b/app/src/main/java/com/rtbishop/look4sat/framework/local/EntriesDao.kt index 147c224d..edbd4e84 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/local/EntriesDao.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/local/EntriesDao.kt @@ -39,26 +39,29 @@ interface EntriesDao { suspend fun insertEntries(entries: List) @Transaction - suspend fun updateEntries(entries: List, cleanup: Boolean = false) { + suspend fun updateEntries(entries: List) { val entriesSelection = getEntriesSelection() - if (cleanup) deleteEntries() insertEntries(entries) - restoreSelection(entriesSelection, true) - } - - @Query("UPDATE entries SET isSelected = :isSelected WHERE catnum = :catnum") - suspend fun updateEntrySelection(catnum: Int, isSelected: Boolean) - - @Transaction - suspend fun updateEntriesSelection(catnums: List, isSelected: Boolean) { - catnums.forEach { catnum -> updateEntrySelection(catnum, isSelected) } + restoreEntriesSelection(entriesSelection) } @Transaction - suspend fun restoreSelection(catnums: List, isSelected: Boolean) { - updateEntriesSelection(catnums, isSelected) + suspend fun restoreEntriesSelection(catnums: List) { + updateEntriesSelection(catnums) } + @Transaction + suspend fun updateEntriesSelection(catnums: List) { + clearEntriesSelection() + catnums.forEach { catnum -> updateEntrySelection(catnum) } + } + + @Query("UPDATE entries SET isSelected = 1 WHERE catnum = :catnum") + suspend fun updateEntrySelection(catnum: Int) + + @Query("UPDATE entries SET isSelected = 0") + suspend fun clearEntriesSelection() + @Query("DELETE FROM entries") suspend fun deleteEntries() } diff --git a/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt b/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt index 468a6026..fd4415a8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt +++ b/app/src/main/java/com/rtbishop/look4sat/framework/local/LocalSource.kt @@ -62,8 +62,8 @@ class LocalSource( entriesDao.updateEntries(entries.toFrameworkEntries()) } - override suspend fun updateEntriesSelection(catnums: List, isSelected: Boolean) { - entriesDao.updateEntriesSelection(catnums, isSelected) + override suspend fun updateEntriesSelection(catnums: List) { + entriesDao.updateEntriesSelection(catnums) } override suspend fun updateTransmitters(transmitters: List) { diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt index 24041794..3ffa5e8a 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesFragment.kt @@ -37,19 +37,21 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class EntriesFragment : Fragment(R.layout.fragment_entries) { + private lateinit var binding: FragmentEntriesBinding private val viewModel: EntriesViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupComponents(view) + binding = FragmentEntriesBinding.bind(view) + setupComponents() } - private fun setupComponents(view: View) { + private fun setupComponents() { val context = requireContext() val adapter = EntriesAdapter(viewModel) val layoutManager = GridLayoutManager(context, 2) val itemDecoration = DividerItemDecoration(context, layoutManager.orientation) - val binding = FragmentEntriesBinding.bind(view).apply { + binding.run { entriesRecycler.apply { setHasFixedSize(true) this.adapter = adapter @@ -61,6 +63,7 @@ class EntriesFragment : Fragment(R.layout.fragment_entries) { entriesSearch.doOnTextChanged { text, _, _, _ -> viewModel.setQuery(text.toString()) } entriesMode.setOnClickListener { showModesDialog() } entriesSelectAll.setOnClickListener { viewModel.selectCurrentItems() } + entriesAccept.setOnClickListener { viewModel.saveSelection() } } viewModel.satData.observe(viewLifecycleOwner) { satData -> handleSatData(satData, binding, adapter) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt index d898fe32..4b73e452 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/entriesScreen/EntriesViewModel.kt @@ -67,6 +67,13 @@ class EntriesViewModel @Inject constructor( currentQuery.value = query } + fun saveSelection() { + itemsFromRepo.value?.let { itemsAll -> + val selectedIds = itemsAll.filter { it.isSelected }.map { it.catnum } + repository.updateSelection(selectedIds) + } + } + override fun updateSelection(catNums: List, isSelected: Boolean) { itemsFromRepo.value?.let { itemsAll -> val copiedList = itemsAll.map { item -> item.copy() } diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt index 584e82c6..124347f7 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/mapScreen/MapFragment.kt @@ -50,6 +50,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { @Inject lateinit var sharedPreferences: SharedPreferences + private lateinit var binding: FragmentMapBinding private val args: MapFragmentArgs by navArgs() private val viewModel: MapViewModel by viewModels() @@ -69,8 +70,14 @@ class MapFragment : Fragment(R.layout.fragment_map) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding = FragmentMapBinding.bind(view) + setupComponents() + setupObservers() + } + + private fun setupComponents() { Configuration.getInstance().load(requireContext(), sharedPreferences) - val binding = FragmentMapBinding.bind(view).apply { + binding.run { mapView.apply { setMultiTouchControls(true) setTileSource(TileSourceFactory.WIKIMEDIA) @@ -85,23 +92,22 @@ class MapFragment : Fragment(R.layout.fragment_map) { // add overlays: 0 - GSP, 1 - SatTrack, 2 - SatFootprint, 3 - SatIcons overlays.addAll(Array(4) { FolderOverlay() }) } + mapBack.setOnClickListener { findNavController().navigateUp() } + mapBtnPrev.setOnClickListener { viewModel.scrollSelection(true) } + mapBtnNext.setOnClickListener { viewModel.scrollSelection(false) } } - binding.mapBack.setOnClickListener { findNavController().navigateUp() } - binding.mapBtnPrev.setOnClickListener { viewModel.scrollSelection(true) } - binding.mapBtnNext.setOnClickListener { viewModel.scrollSelection(false) } - setupObservers(binding) } - private fun setupObservers(binding: FragmentMapBinding) { + private fun setupObservers() { viewModel.selectDefaultSatellite(args.catNum) - viewModel.stationPosLiveData.observe(viewLifecycleOwner) { renderStationPos(it, binding) } - viewModel.satPositions.observe(viewLifecycleOwner) { renderSatPositions(it, binding) } - viewModel.satTrack.observe(viewLifecycleOwner) { renderSatTrack(it, binding) } - viewModel.satFootprint.observe(viewLifecycleOwner) { renderSatFootprint(it, binding) } - viewModel.mapData.observe(viewLifecycleOwner) { renderSatData(it, binding) } + viewModel.stationPosLiveData.observe(viewLifecycleOwner) { renderStationPos(it) } + viewModel.satPositions.observe(viewLifecycleOwner) { renderSatPositions(it) } + viewModel.satTrack.observe(viewLifecycleOwner) { renderSatTrack(it) } + viewModel.satFootprint.observe(viewLifecycleOwner) { renderSatFootprint(it) } + viewModel.mapData.observe(viewLifecycleOwner) { renderSatData(it) } } - private fun renderStationPos(stationPos: GeoPos, binding: FragmentMapBinding) { + private fun renderStationPos(stationPos: GeoPos) { binding.apply { Marker(mapView).apply { setInfoWindow(null) @@ -114,7 +120,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { } } - private fun renderSatPositions(posMap: Map, binding: FragmentMapBinding) { + private fun renderSatPositions(posMap: Map) { binding.apply { val markers = FolderOverlay() posMap.entries.forEach { @@ -143,7 +149,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { } } - private fun renderSatTrack(satTrack: List>, binding: FragmentMapBinding) { + private fun renderSatTrack(satTrack: List>) { val trackOverlay = FolderOverlay() satTrack.forEach { track -> val trackPoints = track.map { GeoPoint(it.latitude, it.longitude) } @@ -160,7 +166,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { binding.mapView.overlays[1] = trackOverlay } - private fun renderSatFootprint(satFootprint: List, binding: FragmentMapBinding) { + private fun renderSatFootprint(satFootprint: List) { val footprintPoints = satFootprint.map { GeoPoint(it.latitude, it.longitude) } val footprintOverlay = Polygon().apply { fillPaint.set(footprintPaint) @@ -174,7 +180,7 @@ class MapFragment : Fragment(R.layout.fragment_map) { binding.mapView.overlays[2] = footprintOverlay } - private fun renderSatData(mapData: MapData, binding: FragmentMapBinding) { + private fun renderSatData(mapData: MapData) { binding.apply { mapDataName.text = String.format(getString(R.string.pat_osm_idName), mapData.catNum, mapData.name) diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt index 80700f2b..00225c5d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/passesScreen/PassesFragment.kt @@ -36,19 +36,21 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesClickListener { + private lateinit var binding: FragmentPassesBinding private val passesViewModel: PassesViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupComponents(view) + binding = FragmentPassesBinding.bind(view) + setupComponents() } - private fun setupComponents(view: View) { + private fun setupComponents() { val context = requireContext() val adapter = PassesAdapter(passesViewModel.shouldUseUTC(), this) val layoutManager = LinearLayoutManager(context) val itemDecoration = DividerItemDecoration(context, layoutManager.orientation) - val binding = FragmentPassesBinding.bind(view).apply { + binding.run { passesList.apply { setHasFixedSize(true) this.adapter = adapter @@ -73,16 +75,6 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC } } - private fun navigateToPassPrefs() { - val direction = PassesFragmentDirections.actionPassesToPassPrefs() - findNavController().navigate(direction) - } - - private fun navigateToSettings() { - val direction = PassesFragmentDirections.actionGlobalSettingsFragment() - findNavController().navigate(direction) - } - private fun handleNewPasses( dataState: DataState>, passesAdapter: PassesAdapter, @@ -134,6 +126,16 @@ class PassesFragment : Fragment(R.layout.fragment_passes), PassesAdapter.PassesC } } + private fun navigateToPassPrefs() { + val direction = PassesFragmentDirections.actionPassesToPassPrefs() + findNavController().navigate(direction) + } + + private fun navigateToSettings() { + val direction = PassesFragmentDirections.actionGlobalSettingsFragment() + findNavController().navigate(direction) + } + override fun navigateToPass(satPass: SatPass) { if (satPass.progress < 100) { val catNum = satPass.catNum diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt index 98dc7fb5..620e0104 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/radarScreen/RadarFragment.kt @@ -40,21 +40,23 @@ class RadarFragment : Fragment(R.layout.fragment_radar) { @Inject lateinit var preferences: ISettingsHandler + private lateinit var binding: FragmentRadarBinding private val args: RadarFragmentArgs by navArgs() private val viewModel: RadarViewModel by viewModels() private var radarView: RadarView? = null override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupComponents(view) + binding = FragmentRadarBinding.bind(view) + setupViews() } - private fun setupComponents(view: View) { + private fun setupViews() { val context = requireContext() val adapter = TransmittersAdapter() val layoutManager = LinearLayoutManager(context) val itemDecoration = DividerItemDecoration(context, layoutManager.orientation) - FragmentRadarBinding.bind(view).apply { + binding.run { radarRecycler.apply { setHasFixedSize(true) this.adapter = adapter @@ -62,14 +64,11 @@ class RadarFragment : Fragment(R.layout.fragment_radar) { addItemDecoration(itemDecoration) (itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false } - setupObservers(adapter, this) + setupObservers(adapter) } } - private fun setupObservers( - transmittersAdapter: TransmittersAdapter, - binding: FragmentRadarBinding - ) { + private fun setupObservers(transmittersAdapter: TransmittersAdapter) { viewModel.getPass(args.catNum, args.aosTime).observe(viewLifecycleOwner) { pass -> radarView = RadarView(requireContext()).apply { setShowAim(preferences.getUseCompass()) @@ -79,7 +78,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) { viewModel.radarData.observe(viewLifecycleOwner) { passData -> radarView?.setPosition(passData.satPos) radarView?.setPositions(passData.satTrack) - setPassText(pass, passData.satPos, binding) + setPassText(pass, passData.satPos) } viewModel.transmitters.observe(viewLifecycleOwner) { list -> if (list.isNotEmpty()) { @@ -101,12 +100,7 @@ class RadarFragment : Fragment(R.layout.fragment_radar) { } } - private fun navigateToMap(catnum: Int) { - val direction = RadarFragmentDirections.actionGlobalMapFragment(catnum) - findNavController().navigate(direction) - } - - private fun setPassText(satPass: SatPass, satPos: SatPos, binding: FragmentRadarBinding) { + private fun setPassText(satPass: SatPass, satPos: SatPos) { val timeNow = System.currentTimeMillis() val polarAz = getString(R.string.pat_azimuth) val polarEl = getString(R.string.pat_elevation) @@ -135,6 +129,11 @@ class RadarFragment : Fragment(R.layout.fragment_radar) { } } + private fun navigateToMap(catnum: Int) { + val direction = RadarFragmentDirections.actionGlobalMapFragment(catnum) + findNavController().navigate(direction) + } + override fun onResume() { super.onResume() viewModel.enableSensor() diff --git a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt index a6816b70..9b6001fb 100644 --- a/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/presentation/settingsScreen/SettingsFragment.kt @@ -46,6 +46,7 @@ import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint class SettingsFragment : Fragment(R.layout.fragment_settings) { + private lateinit var binding: FragmentSettingsBinding private val viewModel: SettingsViewModel by viewModels() private val locationFine = Manifest.permission.ACCESS_FINE_LOCATION private val locationCoarse = Manifest.permission.ACCESS_COARSE_LOCATION @@ -64,23 +65,31 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val settingsBinding = FragmentSettingsBinding.bind(view) - settingsBinding.prefsBack.setOnClickListener { findNavController().navigateUp() } - setupAboutCard(settingsBinding) - setupDataCard(settingsBinding) - setupLocationCard(settingsBinding) - setupTrackingCard(settingsBinding) - setupOtherCard(settingsBinding) - setupWarrantyCard(settingsBinding) + binding = FragmentSettingsBinding.bind(view) + setupViews() + setupObservers() + } + + private fun setupViews() { + binding.prefsBack.setOnClickListener { findNavController().navigateUp() } + setupAboutCard() + setupDataCard() + setupLocationCard() + setupTrackingCard() + setupOtherCard() + setupWarrantyCard() + } + + private fun setupObservers() { viewModel.stationPosition.asLiveData().observe(viewLifecycleOwner) { stationPos -> - stationPos?.let { handleStationPosition(stationPos, settingsBinding) } + stationPos?.let { handleStationPosition(stationPos) } } viewModel.getUpdateState().asLiveData().observe(viewLifecycleOwner) { updateState -> - updateState?.let { handleSatState(updateState, settingsBinding) } + updateState?.let { handleSatState(updateState) } } } - private fun setupAboutCard(binding: FragmentSettingsBinding) { + private fun setupAboutCard() { binding.prefsInfo.aboutVersion.text = String.format(getString(R.string.about_version), BuildConfig.VERSION_NAME) binding.prefsInfo.aboutBtnGithub.setOnClickListener { @@ -94,8 +103,8 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun setupLocationCard(binding: FragmentSettingsBinding) { - setPositionText(viewModel.getStationPosition(), binding) + private fun setupLocationCard() { + setPositionText(viewModel.getStationPosition()) binding.prefsLocation.locationBtnGps.setOnClickListener { locationRequest.launch(arrayOf(locationFine, locationCoarse)) } @@ -114,7 +123,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun setupDataCard(binding: FragmentSettingsBinding) { + private fun setupDataCard() { binding.prefsData.updateBtnFile.setOnClickListener { contentRequest.launch("*/*") } binding.prefsData.updateBtnWeb.setOnClickListener { val action = SettingsFragmentDirections.actionPrefsToSources() @@ -126,7 +135,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun setupTrackingCard(binding: FragmentSettingsBinding) { + private fun setupTrackingCard() { binding.prefsTracking.trackingSwitch.apply { isChecked = viewModel.getRotatorEnabled() binding.prefsTracking.trackingIp.isEnabled = isChecked @@ -147,7 +156,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun setupOtherCard(binding: FragmentSettingsBinding) { + private fun setupOtherCard() { binding.prefsOther.otherSwitchUtc.apply { isChecked = viewModel.getUseUTC() setOnCheckedChangeListener { _, isChecked -> viewModel.setUseUTC(isChecked) } @@ -162,22 +171,22 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun setupWarrantyCard(binding: FragmentSettingsBinding) { + private fun setupWarrantyCard() { binding.prefsWarranty.warrantyThanks.movementMethod = LinkMovementMethod.getInstance() binding.prefsWarranty.warrantyLicense.movementMethod = LinkMovementMethod.getInstance() } - private fun setPositionText(geoPos: GeoPos, binding: FragmentSettingsBinding) { + private fun setPositionText(geoPos: GeoPos) { val latFormat = getString(R.string.location_lat) val lonFormat = getString(R.string.location_lon) binding.prefsLocation.locationLat.text = String.format(latFormat, geoPos.latitude) binding.prefsLocation.locationLon.text = String.format(lonFormat, geoPos.longitude) } - private fun handleStationPosition(pos: DataState, binding: FragmentSettingsBinding) { + private fun handleStationPosition(pos: DataState) { when (pos) { is DataState.Success -> { - setPositionText(pos.data, binding) + setPositionText(pos.data) binding.prefsLocation.locationProgress.isIndeterminate = false viewModel.setPositionHandled() showToast(getString(R.string.pref_pos_success)) @@ -194,7 +203,7 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } } - private fun handleSatState(state: DataState, binding: FragmentSettingsBinding) { + private fun handleSatState(state: DataState) { when (state) { is DataState.Success -> { binding.prefsData.updateProgress.isIndeterminate = false diff --git a/core/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt b/core/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt index 69f72db3..2439a932 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/DataRepository.kt @@ -116,8 +116,10 @@ class DataRepository( override suspend fun getTransmitters(catnum: Int) = localSource.getTransmitters(catnum) - override suspend fun updateSelection(catnums: List, isSelected: Boolean) { - localSource.updateEntriesSelection(catnums, isSelected) + override fun updateSelection(catnums: List) { + repositoryScope.launch { + localSource.updateEntriesSelection(catnums) + } } private suspend fun importSatellites(stream: InputStream): List { diff --git a/core/src/main/java/com/rtbishop/look4sat/data/ILocalSource.kt b/core/src/main/java/com/rtbishop/look4sat/data/ILocalSource.kt index 839714d7..5e8ebb45 100644 --- a/core/src/main/java/com/rtbishop/look4sat/data/ILocalSource.kt +++ b/core/src/main/java/com/rtbishop/look4sat/data/ILocalSource.kt @@ -36,7 +36,7 @@ interface ILocalSource { suspend fun updateEntries(entries: List) - suspend fun updateEntriesSelection(catnums: List, isSelected: Boolean) + suspend fun updateEntriesSelection(catnums: List) suspend fun updateTransmitters(transmitters: List) diff --git a/core/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt b/core/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt index 2eb2734d..280bb3f8 100644 --- a/core/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt +++ b/core/src/main/java/com/rtbishop/look4sat/domain/IDataRepository.kt @@ -42,5 +42,5 @@ interface IDataRepository { suspend fun getTransmitters(catnum: Int): List - suspend fun updateSelection(catnums: List, isSelected: Boolean = true) + fun updateSelection(catnums: List) }