From 7e182b887f87f58195de243317b506a3bb90f656 Mon Sep 17 00:00:00 2001 From: ArctikCircle Date: Sun, 22 Dec 2024 16:42:35 +0530 Subject: [PATCH] fixed #851 - add filter by arrivals/departures feature in ArrivalsListFragment --- .../android/ui/ArrivalsListAdapterBase.java | 7 +- .../android/ui/ArrivalsListAdapterStyleA.java | 6 +- .../android/ui/ArrivalsListAdapterStyleB.java | 6 +- .../android/ui/ArrivalsListFragment.java | 71 ++++++++++++++++--- .../android/util/ArrivalInfoUtils.java | 46 +++++++++++- .../src/main/res/menu-v14/arrivals_list.xml | 3 + .../src/main/res/menu/arrivals_list.xml | 3 + .../src/main/res/values/arrays.xml | 6 ++ .../src/main/res/values/strings.xml | 1 + 9 files changed, 131 insertions(+), 18 deletions(-) diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterBase.java b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterBase.java index d623fd7f4..f2470e64d 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterBase.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterBase.java @@ -17,6 +17,7 @@ import org.onebusaway.android.io.elements.ObaArrivalInfo; import org.onebusaway.android.util.ArrayAdapter; +import org.onebusaway.android.util.ArrivalInfoUtils.ArrivalFilter; import android.content.ContentQueryMap; import android.content.Context; @@ -41,5 +42,9 @@ public void setTripsForStop(ContentQueryMap tripsForStop) { notifyDataSetChanged(); } - abstract public void setData(ObaArrivalInfo[] arrivals, ArrayList routesFilter, long currentTime); + abstract public void setData(ObaArrivalInfo[] arrivals, ArrayList routesFilter, long currentTime, ArrivalFilter arrivalFilter); + public void setData(ObaArrivalInfo[] arrivals, ArrayList routesFilter, long currentTime) { + setData(arrivals, routesFilter, currentTime, ArrivalFilter.BOTH); + } + } diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleA.java b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleA.java index a2a1de1c4..00bcfc485 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleA.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleA.java @@ -33,6 +33,7 @@ import org.onebusaway.android.io.elements.Status; import org.onebusaway.android.provider.ObaContract; import org.onebusaway.android.util.ArrivalInfoUtils; +import org.onebusaway.android.util.ArrivalInfoUtils.ArrivalFilter; import org.onebusaway.android.util.UIUtils; import java.util.ArrayList; @@ -53,11 +54,12 @@ public ArrivalsListAdapterStyleA(Context context) { * @param currentTime current time in milliseconds */ public void setData(ObaArrivalInfo[] arrivals, ArrayList routesFilter, - long currentTime) { + long currentTime, ArrivalFilter arrivalFilter) { if (arrivals != null) { ArrayList list = ArrivalInfoUtils.convertObaArrivalInfo(getContext(), - arrivals, routesFilter, currentTime, false); + arrivals, routesFilter, currentTime, false, + arrivalFilter); setData(list); } else { setData(null); diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleB.java b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleB.java index f0150efa9..74143aa37 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleB.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListAdapterStyleB.java @@ -42,6 +42,7 @@ import org.onebusaway.android.io.elements.Status; import org.onebusaway.android.provider.ObaContract; import org.onebusaway.android.util.ArrivalInfoUtils; +import org.onebusaway.android.util.ArrivalInfoUtils.ArrivalFilter; import org.onebusaway.android.util.UIUtils; import org.onebusaway.util.comparators.AlphanumComparator; @@ -75,11 +76,12 @@ public void setFragment(ArrivalsListFragment fragment) { * @param currentTime current time in milliseconds */ public void setData(ObaArrivalInfo[] arrivals, ArrayList routesFilter, - long currentTime) { + long currentTime, ArrivalFilter arrivalFilter) { if (arrivals != null) { ArrayList list = ArrivalInfoUtils.convertObaArrivalInfo(getContext(), - arrivals, routesFilter, currentTime, true); + arrivals, routesFilter, currentTime, true, + arrivalFilter); // Sort list by route and headsign, in that order Collections.sort(list, new Comparator() { diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListFragment.java b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListFragment.java index 5b4350a74..8cdb30bcc 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListFragment.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/ui/ArrivalsListFragment.java @@ -47,6 +47,7 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.util.Pair; @@ -81,6 +82,7 @@ import org.onebusaway.android.io.request.survey.model.StudyResponse; import org.onebusaway.android.util.ArrayAdapterWithIcon; import org.onebusaway.android.util.ArrivalInfoUtils; +import org.onebusaway.android.util.ArrivalInfoUtils.ArrivalFilter; import org.onebusaway.android.util.BuildFlavorUtils; import org.onebusaway.android.util.DBUtil; import org.onebusaway.android.util.FragmentUtils; @@ -182,6 +184,8 @@ public class ArrivalsListFragment extends ListFragment implements LoaderManager. private SurveyManager surveyManager; + private ArrivalFilter mArrivalFilter = ArrivalFilterDialog.arrivalFilter; + public interface Listener { /** @@ -641,6 +645,8 @@ public boolean onOptionsItemSelected(MenuItem item) { if (mStop != null) { showRoutesFilterDialog(); } + } else if (id == R.id.filter_arrivals_departures) { + new ArrivalFilterDialog().show(getActivity().getSupportFragmentManager(), ".ArrivalFilterDialog"); } else if (id == R.id.show_header_arrivals) { doShowHideHeaderArrivals(); } else if (id == R.id.edit_name) { @@ -1381,15 +1387,7 @@ public void onSaveInstanceState(Bundle outState) { @Override public void onClick(DialogInterface dialog, int which) { Activity act = getActivity(); - ArrivalsListFragment frag = null; - - // Get the fragment we want... - if (act instanceof ArrivalsListActivity) { - frag = ((ArrivalsListActivity) act).getArrivalsListFragment(); - } else if (act instanceof HomeActivity) { - frag = ((HomeActivity) act).getArrivalsListFragment(); - } - + ArrivalsListFragment frag = getArrivalsListFragment(act); frag.setRoutesFilter(mChecks); dialog.dismiss(); } @@ -1400,6 +1398,59 @@ public void onClick(DialogInterface arg0, int which, boolean isChecked) { } } + public static class ArrivalFilterDialog extends DialogFragment + implements DialogInterface.OnClickListener { + private static ArrivalFilter arrivalFilter = ArrivalFilter.BOTH; + + @NonNull + @Override + public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { + return new AlertDialog.Builder(getActivity()) + .setSingleChoiceItems(ArrivalFilter.getOptionsArray(getResources()), arrivalFilter.arrayResourceIndex, this) + .setPositiveButton(R.string.stop_info_save, this) + .setNegativeButton(R.string.stop_info_cancel, null) + .create(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + arrivalFilter = ArrivalFilter.BOTH; + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == ArrivalFilter.BOTH.arrayResourceIndex) { + arrivalFilter = ArrivalFilter.BOTH; + } else if (which == ArrivalFilter.ARRIVALS_ONLY.arrayResourceIndex) { + arrivalFilter = ArrivalFilter.ARRIVALS_ONLY; + } else if (which == ArrivalFilter.DEPARTURES_ONLY.arrayResourceIndex) { + arrivalFilter = ArrivalFilter.DEPARTURES_ONLY; + } else if (which == DialogInterface.BUTTON_POSITIVE) { + getArrivalsListFragment(getActivity()).setArrivalFilter(arrivalFilter); + dialog.dismiss(); + } + } + } + + @Nullable + private static ArrivalsListFragment getArrivalsListFragment(Activity act) { + ArrivalsListFragment frag = null; + + // Get the fragment we want... + if (act instanceof ArrivalsListActivity) { + frag = ((ArrivalsListActivity) act).getArrivalsListFragment(); + } else if (act instanceof HomeActivity) { + frag = ((HomeActivity) act).getArrivalsListFragment(); + } + return frag; + } + + private void setArrivalFilter(ArrivalFilter arrivalFilter) { + mArrivalFilter = arrivalFilter; + refreshLocal(); + } + private void setRoutesFilter(boolean[] checks) { final int len = checks.length; final ArrayList newFilter = new ArrayList(len); @@ -1518,7 +1569,7 @@ public void refreshLocal() { // Nothing to refresh yet return; } - mAdapter.setData(response.getArrivalInfo(), mRoutesFilter, System.currentTimeMillis()); + mAdapter.setData(response.getArrivalInfo(), mRoutesFilter, System.currentTimeMillis(), mArrivalFilter); } if (mHeader != null) { mHeader.refresh(); diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/util/ArrivalInfoUtils.java b/onebusaway-android/src/main/java/org/onebusaway/android/util/ArrivalInfoUtils.java index ba3679810..5ac640bb0 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/util/ArrivalInfoUtils.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/util/ArrivalInfoUtils.java @@ -19,6 +19,8 @@ import android.content.Context; import android.content.res.Resources; +import androidx.annotation.NonNull; + import org.onebusaway.android.R; import org.onebusaway.android.app.Application; import org.onebusaway.android.io.elements.ObaArrivalInfo; @@ -52,7 +54,8 @@ public int compare(ArrivalInfo lhs, ArrivalInfo rhs) { public static ArrayList convertObaArrivalInfo(Context context, ObaArrivalInfo[] arrivalInfo, ArrayList filter, long ms, - boolean includeArrivalDepartureInStatusLabel) { + boolean includeArrivalDepartureInStatusLabel, + ArrivalFilter arrivalFilter) { final int len = arrivalInfo.length; ArrayList result = new ArrayList(len); if (filter != null && filter.size() > 0) { @@ -61,7 +64,7 @@ public static ArrayList convertObaArrivalInfo(Context context, if (filter.contains(arrival.getRouteId())) { ArrivalInfo info = new ArrivalInfo(context, arrival, ms, includeArrivalDepartureInStatusLabel); - if (shouldAddEta(info)) { + if (shouldAddEta(info) && shouldAddArrivalFilter(info, arrivalFilter)) { result.add(info); } } @@ -71,7 +74,7 @@ public static ArrayList convertObaArrivalInfo(Context context, for (ObaArrivalInfo obaArrivalInfo : arrivalInfo) { ArrivalInfo info = new ArrivalInfo(context, obaArrivalInfo, ms, includeArrivalDepartureInStatusLabel); - if (shouldAddEta(info)) { + if (shouldAddEta(info) && shouldAddArrivalFilter(info, arrivalFilter)) { result.add(info); } } @@ -82,6 +85,34 @@ public static ArrayList convertObaArrivalInfo(Context context, return result; } + public static ArrayList convertObaArrivalInfo(Context context, + ObaArrivalInfo[] arrivalInfo, + ArrayList filter, long ms, + boolean includeArrivalDepartureInStatusLabel) { + return convertObaArrivalInfo(context, arrivalInfo, filter, ms, includeArrivalDepartureInStatusLabel, ArrivalFilter.BOTH); + } + + // This enum class represents the string array resource R.array.stop_info_arrival_filter_options + public enum ArrivalFilter { + BOTH(0), + ARRIVALS_ONLY(1), + DEPARTURES_ONLY(2); + + public final int arrayResourceIndex; + + ArrivalFilter(int arrayResourceIndex) { + this.arrayResourceIndex = arrayResourceIndex; + } + + public String getOptionString(Resources appResources) { + return appResources.getStringArray(R.array.stop_info_arrival_filter_options)[arrayResourceIndex]; + } + + public static String[] getOptionsArray(Resources appResources) { + return appResources.getStringArray(R.array.stop_info_arrival_filter_options); + } + } + /** * Returns true if this ETA should be added based on the user preference for adding negative * arrival times, and false if it should not @@ -106,6 +137,15 @@ private static boolean shouldAddEta(ArrivalInfo info) { return false; } + private static boolean shouldAddArrivalFilter(ArrivalInfo info, @NonNull ArrivalFilter arrivalFilter) { + switch (arrivalFilter) { + case BOTH: return true; + case ARRIVALS_ONLY: return info.isArrival(); + case DEPARTURES_ONLY: return !info.isArrival(); + default: throw new IllegalArgumentException(); + } + } + /** * Returns the index in the provided infoList for the first non-negative arrival ETA in the * list, or -1 if no non-negative ETAs exist in the list diff --git a/onebusaway-android/src/main/res/menu-v14/arrivals_list.xml b/onebusaway-android/src/main/res/menu-v14/arrivals_list.xml index 85ea84fa2..9d57f52b2 100644 --- a/onebusaway-android/src/main/res/menu-v14/arrivals_list.xml +++ b/onebusaway-android/src/main/res/menu-v14/arrivals_list.xml @@ -36,6 +36,9 @@ + diff --git a/onebusaway-android/src/main/res/menu/arrivals_list.xml b/onebusaway-android/src/main/res/menu/arrivals_list.xml index fdf4b680e..442b19b9a 100644 --- a/onebusaway-android/src/main/res/menu/arrivals_list.xml +++ b/onebusaway-android/src/main/res/menu/arrivals_list.xml @@ -33,6 +33,9 @@ + diff --git a/onebusaway-android/src/main/res/values/arrays.xml b/onebusaway-android/src/main/res/values/arrays.xml index 30a40f8f5..c9d0fad62 100644 --- a/onebusaway-android/src/main/res/values/arrays.xml +++ b/onebusaway-android/src/main/res/values/arrays.xml @@ -227,4 +227,10 @@ @string/trip_plan_arriving + + Both + Arrivals only + Departures only + + diff --git a/onebusaway-android/src/main/res/values/strings.xml b/onebusaway-android/src/main/res/values/strings.xml index dfc8cdfbc..72c5c78a6 100644 --- a/onebusaway-android/src/main/res/values/strings.xml +++ b/onebusaway-android/src/main/res/values/strings.xml @@ -1278,4 +1278,5 @@ More Info Display test alerts Display test-wide alerts for regions + Filter arrivals/departures