Changeset View
Changeset View
Standalone View
Standalone View
app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
Show All 22 Lines | |||||
import android.content.SharedPreferences | import android.content.SharedPreferences | ||||
import android.graphics.Paint | import android.graphics.Paint | ||||
import android.os.Bundle | import android.os.Bundle | ||||
import android.util.Log | import android.util.Log | ||||
import android.view.LayoutInflater | import android.view.LayoutInflater | ||||
import android.view.View | import android.view.View | ||||
import android.view.ViewGroup | import android.view.ViewGroup | ||||
import android.widget.* | import android.widget.* | ||||
import androidx.activity.result.contract.ActivityResultContracts | |||||
import androidx.appcompat.content.res.AppCompatResources | import androidx.appcompat.content.res.AppCompatResources | ||||
import androidx.core.content.ContextCompat | import androidx.core.content.ContextCompat | ||||
import androidx.core.content.res.ResourcesCompat | import androidx.core.content.res.ResourcesCompat | ||||
import androidx.fragment.app.viewModels | import androidx.fragment.app.viewModels | ||||
import androidx.lifecycle.lifecycleScope | import androidx.lifecycle.lifecycleScope | ||||
import androidx.preference.PreferenceManager | import androidx.preference.PreferenceManager | ||||
import androidx.recyclerview.widget.LinearLayoutManager | import androidx.recyclerview.widget.LinearLayoutManager | ||||
import androidx.recyclerview.widget.RecyclerView | import androidx.recyclerview.widget.RecyclerView | ||||
Show All 9 Lines | |||||
import it.reyboz.bustorino.backend.utils | import it.reyboz.bustorino.backend.utils | ||||
import it.reyboz.bustorino.data.MatoTripsDownloadWorker | import it.reyboz.bustorino.data.MatoTripsDownloadWorker | ||||
import it.reyboz.bustorino.data.PreferencesHolder | import it.reyboz.bustorino.data.PreferencesHolder | ||||
import it.reyboz.bustorino.data.gtfs.MatoPattern | import it.reyboz.bustorino.data.gtfs.MatoPattern | ||||
import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops | import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops | ||||
import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops | import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops | ||||
import it.reyboz.bustorino.map.* | import it.reyboz.bustorino.map.* | ||||
import it.reyboz.bustorino.map.CustomInfoWindow.TouchResponder | import it.reyboz.bustorino.map.CustomInfoWindow.TouchResponder | ||||
import it.reyboz.bustorino.middleware.LocationUtils | |||||
import it.reyboz.bustorino.util.Permissions | |||||
import it.reyboz.bustorino.viewmodels.LinesViewModel | import it.reyboz.bustorino.viewmodels.LinesViewModel | ||||
import it.reyboz.bustorino.viewmodels.LivePositionsViewModel | import it.reyboz.bustorino.viewmodels.LivePositionsViewModel | ||||
import kotlinx.coroutines.delay | import kotlinx.coroutines.delay | ||||
import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||
import org.osmdroid.config.Configuration | import org.osmdroid.config.Configuration | ||||
import org.osmdroid.tileprovider.tilesource.TileSourceFactory | import org.osmdroid.tileprovider.tilesource.TileSourceFactory | ||||
import org.osmdroid.util.BoundingBox | import org.osmdroid.util.BoundingBox | ||||
import org.osmdroid.util.GeoPoint | import org.osmdroid.util.GeoPoint | ||||
Show All 19 Lines | class LinesDetailFragment() : ScreenBaseFragment() { | ||||
private val viewModel: LinesViewModel by viewModels() | private val viewModel: LinesViewModel by viewModels() | ||||
private val mapViewModel: MapViewModel by viewModels() | private val mapViewModel: MapViewModel by viewModels() | ||||
private var firstInit = true | private var firstInit = true | ||||
private var pausedFragment = false | private var pausedFragment = false | ||||
private lateinit var switchButton: ImageButton | private lateinit var switchButton: ImageButton | ||||
private var favoritesButton: ImageButton? = null | private var favoritesButton: ImageButton? = null | ||||
private lateinit var locationIcon: ImageButton | private var locationIcon: ImageButton? = null | ||||
private var isLineInFavorite = false | private var isLineInFavorite = false | ||||
private var appContext: Context? = null | private var appContext: Context? = null | ||||
private var isLocationPermissionOK = false | |||||
private val lineSharedPrefMonitor = SharedPreferences.OnSharedPreferenceChangeListener { pref, keychanged -> | private val lineSharedPrefMonitor = SharedPreferences.OnSharedPreferenceChangeListener { pref, keychanged -> | ||||
if(keychanged!=PreferencesHolder.PREF_FAVORITE_LINES || lineID.isEmpty()) return@OnSharedPreferenceChangeListener | if(keychanged!=PreferencesHolder.PREF_FAVORITE_LINES || lineID.isEmpty()) return@OnSharedPreferenceChangeListener | ||||
val newFavorites = pref.getStringSet(PreferencesHolder.PREF_FAVORITE_LINES, HashSet()) | val newFavorites = pref.getStringSet(PreferencesHolder.PREF_FAVORITE_LINES, HashSet()) | ||||
newFavorites?.let {favorites-> | newFavorites?.let {favorites-> | ||||
isLineInFavorite = favorites.contains(lineID) | isLineInFavorite = favorites.contains(lineID) | ||||
//if the button has been intialized, change the icon accordingly | //if the button has been intialized, change the icon accordingly | ||||
favoritesButton?.let { button-> | favoritesButton?.let { button-> | ||||
//avoid crashes if fragment not attached | //avoid crashes if fragment not attached | ||||
Show All 39 Lines | class LinesDetailFragment() : ScreenBaseFragment() { | ||||
} | } | ||||
private var polyline: Polyline? = null | private var polyline: Polyline? = null | ||||
//private var stopPosList = ArrayList<GeoPoint>() | //private var stopPosList = ArrayList<GeoPoint>() | ||||
private lateinit var stopsOverlay: FolderOverlay | private lateinit var stopsOverlay: FolderOverlay | ||||
private lateinit var locationOverlay: LocationOverlay | private lateinit var locationOverlay: LocationOverlay | ||||
private val locationOverlayResponder = object : LocationOverlay.OverlayCallbacks{ | |||||
override fun onDisableFollowMyLocation() { | |||||
Log.d(DEBUG_TAG, "Follow location disabled") | |||||
} | |||||
override fun onEnableFollowMyLocation() { | |||||
Log.d(DEBUG_TAG, "Follow location enabled") | |||||
} | |||||
} | |||||
//location request responder | |||||
private val locationRequestResLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){ res -> | |||||
//onActivityResult(res: map<String,Boolean>) | |||||
if(res[Permissions.LOCATION_PERMISSIONS[0]] ==true || res[Permissions.LOCATION_PERMISSIONS[1]] ==true) | |||||
locationIcon?.let { onPositionIconButtonClick(it) } | |||||
else{ | |||||
context?.let { Toast.makeText(it,R.string.location_permission_not_granted, Toast.LENGTH_SHORT).show() } | |||||
} | |||||
} | |||||
//fragment actions | //fragment actions | ||||
private lateinit var fragmentListener: CommonFragmentListener | private lateinit var fragmentListener: CommonFragmentListener | ||||
private val stopTouchResponder = TouchResponder { stopID, stopName -> | private val stopTouchResponder = TouchResponder { stopID, stopName -> | ||||
Log.d(DEBUG_TAG, "Asked to show arrivals for stop ID: $stopID") | Log.d(DEBUG_TAG, "Asked to show arrivals for stop ID: $stopID") | ||||
fragmentListener.requestArrivalsForStopID(stopID) | fragmentListener.requestArrivalsForStopID(stopID) | ||||
} | } | ||||
private var showOnTopOfLine = true | private var showOnTopOfLine = true | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | ): View? { | ||||
initializeMap(rootView) | initializeMap(rootView) | ||||
initializeRecyclerView() | initializeRecyclerView() | ||||
switchButton.setOnClickListener{ | switchButton.setOnClickListener{ | ||||
if(map.visibility == View.VISIBLE){ | if(map.visibility == View.VISIBLE){ | ||||
map.visibility = View.GONE | map.visibility = View.GONE | ||||
stopsRecyclerView.visibility = View.VISIBLE | stopsRecyclerView.visibility = View.VISIBLE | ||||
locationIcon.visibility = View.GONE | locationIcon?.visibility = View.GONE | ||||
viewModel.setMapShowing(false) | viewModel.setMapShowing(false) | ||||
liveBusViewModel.stopMatoUpdates() | liveBusViewModel.stopMatoUpdates() | ||||
//map.overlayManager.remove(busPositionsOverlay) | //map.overlayManager.remove(busPositionsOverlay) | ||||
switchButton.setImageDrawable(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_map_white_30)) | switchButton.setImageDrawable(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_map_white_30)) | ||||
} else{ | } else{ | ||||
stopsRecyclerView.visibility = View.GONE | stopsRecyclerView.visibility = View.GONE | ||||
map.visibility = View.VISIBLE | map.visibility = View.VISIBLE | ||||
locationIcon.visibility = View.VISIBLE | locationIcon?.visibility = View.VISIBLE | ||||
viewModel.setMapShowing(true) | viewModel.setMapShowing(true) | ||||
//map.overlayManager.add(busPositionsOverlay) | //map.overlayManager.add(busPositionsOverlay) | ||||
//map. | //map. | ||||
if(useMQTTPositions) | if(useMQTTPositions) | ||||
liveBusViewModel.requestMatoPosUpdates(GtfsUtils.getLineNameFromGtfsID(lineID)) | liveBusViewModel.requestMatoPosUpdates(GtfsUtils.getLineNameFromGtfsID(lineID)) | ||||
else | else | ||||
liveBusViewModel.requestGTFSUpdates() | liveBusViewModel.requestGTFSUpdates() | ||||
switchButton.setImageDrawable(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_list_30)) | switchButton.setImageDrawable(AppCompatResources.getDrawable(requireContext(), R.drawable.ic_list_30)) | ||||
} | } | ||||
} | } | ||||
locationIcon.setOnClickListener { | locationIcon?.let {view -> | ||||
if(locationOverlay.isMyLocationEnabled){ | if(!LocationUtils.isLocationEnabled(requireContext()) || !Permissions.anyLocationPermissionsGranted(requireContext())) | ||||
//switch off | setLocationIconEnabled(false) | ||||
locationOverlay.disableMyLocation() | //set click Listener | ||||
locationIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.location_circlew_grey)) | view.setOnClickListener(this::onPositionIconButtonClick) | ||||
//show message | |||||
Toast.makeText(requireContext(),R.string.location_disabled,Toast.LENGTH_SHORT).show() | |||||
} else{ | |||||
//switch on | |||||
locationOverlay.enableMyLocation() | |||||
locationIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.location_circlew_red)) | |||||
//show message | |||||
Toast.makeText(requireContext(),R.string.location_enabled,Toast.LENGTH_SHORT).show() | |||||
} | |||||
} | } | ||||
//set | |||||
viewModel.setRouteIDQuery(lineID) | viewModel.setRouteIDQuery(lineID) | ||||
val keySourcePositions = getString(R.string.pref_positions_source) | val keySourcePositions = getString(R.string.pref_positions_source) | ||||
useMQTTPositions = PreferenceManager.getDefaultSharedPreferences(requireContext()) | useMQTTPositions = PreferenceManager.getDefaultSharedPreferences(requireContext()) | ||||
.getString(keySourcePositions, "mqtt").contentEquals("mqtt") | .getString(keySourcePositions, "mqtt").contentEquals("mqtt") | ||||
viewModel.patternsWithStopsByRouteLiveData.observe(viewLifecycleOwner){ | viewModel.patternsWithStopsByRouteLiveData.observe(viewLifecycleOwner){ | ||||
patterns -> savePatternsToShow(patterns) | patterns -> savePatternsToShow(patterns) | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | ): View? { | ||||
"BusTO-MatoTripDownload" | "BusTO-MatoTripDownload" | ||||
) | ) | ||||
} | } | ||||
return rootView | return rootView | ||||
} | } | ||||
private fun setLocationIconEnabled(setTrue: Boolean){ | |||||
if(setTrue) | |||||
locationIcon?.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.location_circlew_red)) | |||||
else | |||||
locationIcon?.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.location_circlew_grey)) | |||||
} | |||||
/** | |||||
* Switch position icon from activ | |||||
*/ | |||||
private fun onPositionIconButtonClick(view: View){ | |||||
if(locationOverlay.isMyLocationEnabled){ | |||||
//switch off | |||||
locationOverlay.disableMyLocation() | |||||
//set image on respective button | |||||
setLocationIconEnabled(false) | |||||
if(context!=null) { | |||||
if (LocationUtils.isLocationEnabled(context)) { | |||||
//show message | |||||
Toast.makeText(context, R.string.location_disabled, Toast.LENGTH_SHORT).show() | |||||
} | |||||
} | |||||
} else{ | |||||
//switch on | |||||
locationOverlay.enableMyLocation() | |||||
if(context!=null) { | |||||
if(!Permissions.anyLocationPermissionsGranted(context)) { | |||||
locationRequestResLauncher.launch(Permissions.LOCATION_PERMISSIONS) | |||||
Toast.makeText(context, R.string.enable_position_message_map, Toast.LENGTH_SHORT).show() | |||||
} | |||||
else if (LocationUtils.isLocationEnabled(context)) { | |||||
//set image on button | |||||
setLocationIconEnabled(true) | |||||
//show message | |||||
Toast.makeText(context, R.string.location_enabled, Toast.LENGTH_SHORT).show() | |||||
} else{ | |||||
Toast.makeText(context, R.string.map_location_disabled_device, Toast.LENGTH_SHORT).show() | |||||
} | |||||
} | |||||
} | |||||
} | |||||
private fun initializeMap(rootView : View){ | private fun initializeMap(rootView : View){ | ||||
val ctx = requireContext().applicationContext | val ctx = requireContext().applicationContext | ||||
Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx)) | Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx)) | ||||
map = rootView.findViewById(R.id.lineMap) | map = rootView.findViewById(R.id.lineMap) | ||||
map.let { | map.let { | ||||
it.setTileSource(TileSourceFactory.MAPNIK) | it.setTileSource(TileSourceFactory.MAPNIK) | ||||
locationOverlay = LocationOverlay.createLocationOverlay(true, it, requireContext(), object : LocationOverlay.OverlayCallbacks{ | locationOverlay = LocationOverlay.createLocationOverlay(true, it, requireContext(), locationOverlayResponder) | ||||
override fun onDisableFollowMyLocation() { | |||||
Log.d(DEBUG_TAG, "Follow location disabled") | |||||
} | |||||
override fun onEnableFollowMyLocation() { | |||||
Log.d(DEBUG_TAG, "Follow location enabled") | |||||
} | |||||
}) | |||||
locationOverlay.disableFollowLocation() | locationOverlay.disableFollowLocation() | ||||
stopsOverlay = FolderOverlay() | stopsOverlay = FolderOverlay() | ||||
busPositionsOverlay = FolderOverlay() | busPositionsOverlay = FolderOverlay() | ||||
//map.setTilesScaledToDpi(true); | //map.setTilesScaledToDpi(true); | ||||
//map.setTilesScaledToDpi(true); | //map.setTilesScaledToDpi(true); | ||||
Show All 15 Lines | private fun initializeMap(rootView : View){ | ||||
centerMap = GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!) | centerMap = GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!) | ||||
/*viewLifecycleOwner.lifecycleScope.launch { | /*viewLifecycleOwner.lifecycleScope.launch { | ||||
delay(100) | delay(100) | ||||
Log.d(DEBUG_TAG, "zooming back to point") | Log.d(DEBUG_TAG, "zooming back to point") | ||||
controller.animateTo(GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!), | controller.animateTo(GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!), | ||||
mapViewModel.currentZoom.value!!,null,null) | mapViewModel.currentZoom.value!!,null,null) | ||||
//controller.setCenter(GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!)) | //controller.setCenter(GeoPoint(mapViewModel.currentLat.value!!, mapViewModel.currentLong.value!!)) | ||||
//controller.setZoom(mapViewModel.currentZoom.value!!) | //controller.setZoom(mapViewModel.currentZoom.value!!) | ||||
*/ | */ | ||||
} | } | ||||
mapController.setZoom(zoom) | mapController.setZoom(zoom) | ||||
mapController.setCenter(centerMap) | mapController.setCenter(centerMap) | ||||
Log.d(DEBUG_TAG, "Initializing map, first init $firstInit") | Log.d(DEBUG_TAG, "Initializing map, first init $firstInit") | ||||
//map.invalidate() | //map.invalidate() | ||||
it.overlayManager.add(stopsOverlay) | it.overlayManager.add(stopsOverlay) | ||||
it.overlayManager.add(locationOverlay) | it.overlayManager.add(locationOverlay) | ||||
it.overlayManager.add(busPositionsOverlay) | it.overlayManager.add(busPositionsOverlay) | ||||
zoomToCurrentPattern() | zoomToCurrentPattern() | ||||
firstInit = false | firstInit = false | ||||
} | } | ||||
} | } | ||||
override fun onAttach(context: Context) { | override fun onAttach(context: Context) { | ||||
super.onAttach(context) | super.onAttach(context) | ||||
if(context is CommonFragmentListener){ | if(context is CommonFragmentListener){ | ||||
▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | companion object { | ||||
//Log.d(DEBUG_TAG,"Stop ${stop.ID} old pos: ($sLat, $sLong), new pos ($latNew,$longNew)") | //Log.d(DEBUG_TAG,"Stop ${stop.ID} old pos: ($sLat, $sLong), new pos ($latNew,$longNew)") | ||||
return GeoPoint(latNew,longNew) | return GeoPoint(latNew,longNew) | ||||
} | } | ||||
private const val DEFAULT_CENTER_LAT = 45.12 | private const val DEFAULT_CENTER_LAT = 45.12 | ||||
private const val DEFAULT_CENTER_LON = 7.6858 | private const val DEFAULT_CENTER_LON = 7.6858 | ||||
} | } | ||||
} | } | ||||
No newline at end of file | No newline at end of file |
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register