diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/NearbyStopsFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/NearbyStopsFragment.kt --- a/app/src/main/java/it/reyboz/bustorino/fragments/NearbyStopsFragment.kt +++ b/app/src/main/java/it/reyboz/bustorino/fragments/NearbyStopsFragment.kt @@ -27,7 +27,6 @@ import android.widget.ProgressBar import android.widget.TextView import androidx.appcompat.widget.AppCompatButton -import androidx.core.util.Pair import androidx.fragment.app.viewModels import androidx.preference.PreferenceManager import androidx.recyclerview.widget.RecyclerView @@ -69,12 +68,12 @@ } private enum class LocationShowingStatus { - SEARCHING, POSITION_FOUND, DISABLED, NO_PERMISSION + SEARCHING, LOCATION_FOUND, DISABLED, NO_PERMISSION //NO_STOPS_NEARBY } private var mListener: FragmentListenerMain? = null - private var fragment_type = FragType.STOPS + private var fragmentType = FragType.STOPS private lateinit var gridRecyclerView: RecyclerView @@ -100,7 +99,7 @@ //These are useful for the case of nearby arrivals private var arrivalsStopAdapter: ArrivalsStopAdapter? = null - private var currentNearbyStops = ArrayList() + private var currentNearbyStops: ArrayList? = null private var showingStatus = LocationShowingStatus.NO_PERMISSION private var isLocationEnabled = false @@ -113,11 +112,12 @@ override fun onFusedStatusChanged(isEnabled: Boolean) { Log.d(DEBUG_TAG, "Location provider is enabled: " + isEnabled) isLocationEnabled = isEnabled - if (isEnabled) { - setShowingStatus(LocationShowingStatus.SEARCHING) - } else { - setShowingStatus(LocationShowingStatus.DISABLED) - } + if(showingStatus != LocationShowingStatus.LOCATION_FOUND) + if (isEnabled) { + setShowingStatus(LocationShowingStatus.SEARCHING) + } else { + setShowingStatus(LocationShowingStatus.DISABLED) + } } } @@ -199,7 +199,7 @@ switchButton = root.findViewById(R.id.switchButton) scrollListener = CommonScrollListener(mListener, false) - switchButton!!.setOnClickListener(View.OnClickListener { v: View? -> switchFragmentType() }) + switchButton!!.setOnClickListener { v: View? -> switchFragmentType() } if (BuildConfig.DEBUG) Log.d(DEBUG_TAG, "onCreateView") val appContext = requireContext().applicationContext @@ -238,6 +238,8 @@ if (!locationProvider!!.isRunning()) { startLocationUpdatesByType() setShowingStatus(LocationShowingStatus.SEARCHING) + } else{ + Log.w(DEBUG_TAG, "Asked to check and start location updates, but provider is already running") } } else { setShowingStatus(LocationShowingStatus.NO_PERMISSION) @@ -263,10 +265,13 @@ //Log.d(DEBUG_TAG, "Doubling distance now!"); return@observe // THIS WORKS AS AN `else` } - if (!stops.isEmpty()) { - currentNearbyStops = stops - setShowingStatus(LocationShowingStatus.POSITION_FOUND) - showStopsInViews(currentNearbyStops, lastPosition) + setShowingStatus(LocationShowingStatus.LOCATION_FOUND) + displayStopsOrRequestArrivals(stops) + } + + viewModel.locationLiveData.observe(getViewLifecycleOwner()) {loc -> + if(loc!=null){ + setShowingStatus(LocationShowingStatus.LOCATION_FOUND) } } @@ -306,13 +311,37 @@ } //arrivalsStopAdapter.notifyDataSetChanged(); - setShowingStatus(LocationShowingStatus.POSITION_FOUND) + setShowingStatus(LocationShowingStatus.LOCATION_FOUND) showRecyclerHidingLoadMessage() //if (mListener != null) mListener!!.readyGUIfor(FragmentKind.NEARBY_ARRIVALS) } //added - checkPermissionLocationStart() + //checkPermissionLocationStart() + } + + private fun displayStopsOrRequestArrivals(stops: ArrayList){ + if (!stops.isEmpty()) { + currentNearbyStops = stops + //displayStopsOrLaunchArrivalsRequest(stops, lastPosition) + viewModel.locationLiveData.value?.let{loc -> + when(fragmentType){ + FragType.STOPS->{ + viewModel.locationLiveData.value?.let{loc -> + Collections.sort(stops, StopSorterByDistance(loc)) + showStopsInRecycler(stops,loc) + } + + } + FragType.ARRIVALS -> { + viewModel.requestArrivalsForStops(stops) + } + } + } + } else{ + showNoStopsMessage() + viewModel.cancelAllArrivalsRequests() + } } @@ -320,7 +349,7 @@ * Internal bit used to start location updates */ private fun startLocationUpdatesByType() { - when (fragment_type) { + when (fragmentType) { FragType.STOPS -> locationProvider!!.startUpdates(locationOptionsStops) FragType.ARRIVALS -> locationProvider!!.startUpdates(locationOptionsArrivals) } @@ -332,21 +361,11 @@ * @param type the type, TYPE_ARRIVALS or TYPE_STOPS */ private fun setFragmentType(type: FragType) { - val isChanged = fragment_type != type - this.fragment_type = type - /*switch(type){ - case ARRIVALS: - TIME_INTERVAL_REQUESTS = 5*1000; - break; - case STOPS: - TIME_INTERVAL_REQUESTS = 1000; - - } + val isChanged = fragmentType != type + this.fragmentType = type - */ if (isChanged) { startLocationUpdatesByType() - setShowingStatus(LocationShowingStatus.SEARCHING) } } @@ -375,7 +394,7 @@ } when (newStatus) { - LocationShowingStatus.POSITION_FOUND -> { + LocationShowingStatus.LOCATION_FOUND -> { circlingProgressBar!!.setVisibility(View.GONE) loadingTextView!!.setVisibility(View.GONE) gridRecyclerView.setVisibility(View.VISIBLE) @@ -401,7 +420,6 @@ messageTextView!!.setVisibility(View.VISIBLE) enableLocationButton.setVisibility(View.GONE) } - LocationShowingStatus.SEARCHING -> { circlingProgressBar!!.setVisibility(View.VISIBLE) loadingTextView!!.setVisibility(View.VISIBLE) @@ -440,8 +458,13 @@ override fun onResume() { super.onResume() //fix view if we were showing the stops or the arrivals - prepareForFragmentType() - when (fragment_type) { + if(viewModel.locationLiveData.value == null) { + //no location + checkPermissionLocationStart() + } + setupDataAndLayoutByFragmentType() + /* + when (fragmentType) { FragType.STOPS -> if (dataAdapter != null) { //gridRecyclerView.setAdapter(dataAdapter); circlingProgressBar!!.setVisibility(View.GONE) @@ -455,6 +478,8 @@ } } + */ + mListener!!.enableRefreshLayout(false) Log.d(DEBUG_TAG, "OnResume called") if (getContext() == null) { @@ -483,7 +508,6 @@ "Max distance for stops: $stopsMaxDistance, Min number of stops: $stopsMinNumber" ) - //checkPermissionLocationStart() } @@ -504,130 +528,126 @@ /** * Display the stops, or run new set of requests for arrivals */ - private fun showStopsInViews(stops: ArrayList, location: GPSPoint?) { + /*private fun displayStopsOrLaunchArrivalsRequest(stops: ArrayList, location: GPSPoint) { if (stops.isEmpty()) { setNoStopsLayout() return } - if (location == null) { - // we could do something better, but it's better to do this for now - return - } - - /*var minDistance = Double.POSITIVE_INFINITY - for (s in stops) { - minDistance = min(minDistance, s.getDistanceFromLocation(location.getLatitude(), location.getLongitude())) - } - - */ - - //quick trial to hopefully always get the stops in the correct order - Collections.sort(stops, StopSorterByDistance(location)) + when (fragment_type) { - FragType.STOPS -> showStopsInRecycler(stops) + FragType.STOPS -> { + setShowingStatus(LocationShowingStatus.STOPS_FOUND) + showStopsInRecycler(stops, location) + } FragType.ARRIVALS -> { - //don't do anything if we're not attached - /*context?.let{ - if (arrivalsManager == null) arrivalsManager = - NearbyArrivalsDownloader(it.applicationContext, arrivalsListener) - arrivalsManager!!.requestArrivalsForStops(stops) - } - - */ viewModel.requestArrivalsForStops(stops) + //setShowingStatus(LocationShowingStatus.SEARCHING) + viewModel.arrivalsDecoupled.value?.let{ + + } } } } - /** - * To enable targeting from the Button */ - fun switchFragmentType(v: View?) { - switchFragmentType() - } + /** * Call when you need to switch the type of fragment */ private fun switchFragmentType() { - when (fragment_type) { + when (fragmentType) { FragType.ARRIVALS -> setFragmentType(FragType.STOPS) FragType.STOPS -> setFragmentType(FragType.ARRIVALS) - else -> {} } - prepareForFragmentType() - //locManager.removeLocationRequestFor(fragmentLocationListener); - //locManager.addLocationRequestFor(fragmentLocationListener); - if (lastPosition != null) { - // we have at least one fix on the position - showStopsInViews(currentNearbyStops, lastPosition) + if(fragmentType == FragType.ARRIVALS) { + viewModel.stopsAtDistance.value?.let{ + viewModel.requestArrivalsForStops(it) + } } + // + setupDataAndLayoutByFragmentType() } + /** * Prepare the views for the set fragment type */ - private fun prepareForFragmentType() { - if (fragment_type == FragType.STOPS) { + private fun setupDataAndLayoutByFragmentType() { + + var dataAvailable = false + if (fragmentType == FragType.STOPS) { switchButton!!.text = getString(R.string.show_arrivals) titleTextView!!.text = getString(R.string.nearby_stops_message) - - dataAdapter?.let{ gridRecyclerView.adapter = it - + viewModel.stopsAtDistance.value?.let { stops-> + // if data adapter is not null set stops, otherwise + dataAdapter?.setStops(stops) ?: lastPosition?.let{ pos -> + dataAdapter = SquareStopAdapter(stops, mListener, pos) + } + Log.d(DEBUG_TAG, "Found ${stops.size} stops") + } + dataAdapter?.let{ + gridRecyclerView.adapter = it + dataAvailable = true } - mListener?.readyGUIfor(FragmentKind.NEARBY_STOPS) - } else if (fragment_type == FragType.ARRIVALS) { + } else if (fragmentType == FragType.ARRIVALS) { titleTextView!!.text = getString(R.string.nearby_arrivals_message) switchButton!!.text = getString(R.string.show_stops) val arrivalsSorted = viewModel.arrivalsDecoupled.value arrivalsSorted?.let{ - lastPosition?.let{pos -> - arrivalsStopAdapter = ArrivalsStopAdapter(it,mListener!!,requireContext(), pos ) - } + arrivalsStopAdapter?.setRoutesPairListAndPosition( + it, lastPosition) ?: lastPosition?.let{pos -> + arrivalsStopAdapter = ArrivalsStopAdapter(it, mListener!!, requireContext(), pos) + } } + arrivalsStopAdapter?.let{ gridRecyclerView.setAdapter(it) } - mListener?.readyGUIfor(FragmentKind.NEARBY_ARRIVALS) } + if(gridRecyclerView.adapter == null){ + flatProgressBar.isIndeterminate = true + flatProgressBar.visibility = View.VISIBLE + } else{ + flatProgressBar.visibility = View.GONE + flatProgressBar.isIndeterminate = false + } + } //useful methods /**//// GUI METHODS //////// */ - private fun showStopsInRecycler(stops: MutableList?) { + private fun showStopsInRecycler(stops: MutableList, location: GPSPoint) { + // hide the progress bar + flatProgressBar.visibility = View.GONE + + Collections.sort(stops, StopSorterByDistance(location)) if (dataAdapter == null) { dataAdapter = SquareStopAdapter(stops, mListener, lastPosition) - gridRecyclerView!!.setAdapter(dataAdapter) firstLocForStops = false } else { dataAdapter!!.setUserPosition(lastPosition) dataAdapter!!.setStops(stops) } + gridRecyclerView.setAdapter(dataAdapter) + + + setShowingStatus(LocationShowingStatus.LOCATION_FOUND) //showRecyclerHidingLoadMessage(); - if (gridRecyclerView!!.getVisibility() != View.VISIBLE) { + /*if (gridRecyclerView!!.getVisibility() != View.VISIBLE) { circlingProgressBar!!.setVisibility(View.GONE) loadingTextView!!.setVisibility(View.GONE) gridRecyclerView!!.setVisibility(View.VISIBLE) } messageTextView!!.setVisibility(View.GONE) - } - - private fun showArrivalsInRecycler(routesPairList: List>) { - - - } + */ - private fun setNoStopsLayout() { - messageTextView!!.setVisibility(View.VISIBLE) - messageTextView!!.setText(R.string.no_stops_nearby) - circlingProgressBar!!.setVisibility(View.GONE) - loadingTextView!!.setVisibility(View.GONE) } /** @@ -640,7 +660,17 @@ gridRecyclerView.setVisibility(View.VISIBLE) } messageTextView!!.setVisibility(View.GONE) - } /* + } + + private fun showNoStopsMessage(){ + messageTextView!!.setVisibility(View.VISIBLE) + messageTextView!!.setText(R.string.no_stops_nearby) + circlingProgressBar!!.setVisibility(View.GONE) + loadingTextView!!.setVisibility(View.GONE) + enableLocationButton.setVisibility(View.GONE) + } + + /* * Local locationListener, to use for the GPS */ /* diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/NearbyStopsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/NearbyStopsViewModel.kt --- a/app/src/main/java/it/reyboz/bustorino/viewmodels/NearbyStopsViewModel.kt +++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/NearbyStopsViewModel.kt @@ -54,6 +54,8 @@ val progressPerc = MutableLiveData() + //val fragmentType = MutableLiveData() + val downloadingArrivals = MutableLiveData() val lastTimeFinished = AtomicLong(0) private var job : Job? = null @@ -134,13 +136,16 @@ private val errorRequests = AtomicInteger(0) private val runningRequests = AtomicInteger(0) + fun cancelAllArrivalsRequests() { + volleyManager.requestQueue.cancelAll(REQUEST_TAG) + } /** * Run new batch of requests */ fun requestArrivalsForStops(stops: List) { //nearbyArrivalsDownloader.requestArrivalsForStops(stops) if(runningRequests.get() > 0) { - volleyManager.requestQueue.cancelAll(REQUEST_TAG) + cancelAllArrivalsRequests() } val currentDate = Date() val timeRange = 3600 @@ -339,7 +344,7 @@ } override fun onCleared() { - volleyManager.requestQueue.cancelAll(REQUEST_TAG) + cancelAllArrivalsRequests() super.onCleared() }