Page MenuHomeGitPull.it

D259.1790904070.diff
No OneTemporary

Authored By
Unknown
Size
49 KB
Referenced Files
None
Subscribers
None

D259.1790904070.diff

diff --git a/app/src/main/java/it/reyboz/bustorino/adapters/SquareStopAdapter.java b/app/src/main/java/it/reyboz/bustorino/adapters/SquareStopAdapter.java
--- a/app/src/main/java/it/reyboz/bustorino/adapters/SquareStopAdapter.java
+++ b/app/src/main/java/it/reyboz/bustorino/adapters/SquareStopAdapter.java
@@ -31,7 +31,9 @@
import it.reyboz.bustorino.backend.Stop;
import it.reyboz.bustorino.util.StopSorterByDistance;
import it.reyboz.bustorino.fragments.FragmentListenerMain;
+import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -40,12 +42,14 @@
//private List<Stop> stops;
private @Nullable GPSPoint userPosition;
private FragmentListenerMain listener;
- private List<Stop> stops;
+ private boolean showLocation;
+ private ArrayList<Stop> stops;
- public SquareStopAdapter(@Nullable List<Stop> stopList, FragmentListenerMain fragmentListener, @Nullable GPSPoint pos) {
+ public SquareStopAdapter(@NotNull ArrayList<Stop> stopList, FragmentListenerMain fragmentListener, @Nullable GPSPoint pos, boolean showLocation) {
listener = fragmentListener;
userPosition = pos;
stops = stopList;
+ this.showLocation = showLocation;
}
@@ -54,21 +58,24 @@
public SquareViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false);
//sort the stops by distance
- if(stops != null && stops.size() > 0)
- Collections.sort(stops,new StopSorterByDistance(userPosition));
+ if (userPosition!=null) {
+ if (stops != null && stops.size() > 0)
+ stops.sort(new StopSorterByDistance(userPosition));
+ }
return new SquareViewHolder(view);
}
@Override
public void onBindViewHolder(SquareViewHolder holder, int position) {
//DO THE ACTUAL WORK TO PUT THE DATA
- if(stops==null || stops.size() == 0) return; //NO STOPS
+ if(stops==null || stops.isEmpty()) return; //NO STOPS
final Stop stop = stops.get(position);
final Context context = holder.itemView.getContext();
if(stop!=null){
- if(stop.getDistanceFromLocation(userPosition)!=Double.POSITIVE_INFINITY){
+ if(userPosition!=null && stop.getDistanceFromLocation(userPosition)!=Double.POSITIVE_INFINITY){
Double distance = stop.getDistanceFromLocation(userPosition);
holder.distancetextView.setText(distance.intValue()+" m");
+ holder.distancetextView.setVisibility(View.VISIBLE);
} else {
holder.distancetextView.setVisibility(View.GONE);
}
@@ -80,10 +87,19 @@
if(whatStopsHere == null) {
holder.routesView.setVisibility(View.GONE);
} else {
- holder.routesView.setText(context.getString(R.string.lines_fill, whatStopsHere));
+ holder.routesView.setText(whatStopsHere);
+ //context.getString(R.string.lines_fill, whatStopsHere));
holder.routesView.setVisibility(View.VISIBLE); // might be GONE due to View Holder Pattern
}
holder.stopID =stop.ID;
+ if (showLocation && !(
+ stop.location==null || stop.location.isEmpty() || stop.location.contains("null"))
+ ){
+ holder.locationTextView.setText(stop.location);
+ holder.locationTextView.setVisibility(View.VISIBLE);
+ } else {
+ holder.locationTextView.setVisibility(View.GONE);
+ }
} else {
Log.w("SquareStopAdapter","!! The selected stop is null !!");
}
@@ -97,6 +113,7 @@
class SquareViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView stopIDView;
TextView stopNameView;
+ TextView locationTextView;
TextView routesView;
TextView distancetextView;
String stopID;
@@ -107,6 +124,7 @@
stopIDView = (TextView) holdView.findViewById(R.id.stop_numberText);
stopNameView = (TextView) holdView.findViewById(R.id.stop_nameText);
routesView = (TextView) holdView.findViewById(R.id.stop_linesText);
+ locationTextView = holdView.findViewById(R.id.stop_locationTextView);
distancetextView = (TextView) holdView.findViewById(R.id.stop_distanceTextView);
}
diff --git a/app/src/main/java/it/reyboz/bustorino/data/NextGenDB.java b/app/src/main/java/it/reyboz/bustorino/data/NextGenDB.java
--- a/app/src/main/java/it/reyboz/bustorino/data/NextGenDB.java
+++ b/app/src/main/java/it/reyboz/bustorino/data/NextGenDB.java
@@ -337,6 +337,28 @@
});
}
+ @NonNull
+ public synchronized List<Stop> searchStopsByCodeOrName(String query, boolean searchById){
+ String escaped = query.replace("\\", "\\\\")
+ .replace("%", "\\%")
+ .replace("_", "\\_");
+ String sql;
+ final String like = "%" + escaped + "%";
+ if (searchById){
+ sql = "SELECT * FROM "+StopsTable.TABLE_NAME+" WHERE "+StopsTable.COL_ID+" LIKE ? ESCAPE '\\'";
+ } else{
+ sql = "SELECT * FROM "+StopsTable.TABLE_NAME+" WHERE "+StopsTable.COL_NAME+" LIKE ? ESCAPE '\\'";
+ }
+ final List<Stop> out = new ArrayList<>();
+ SQLiteDatabase db = getReadableDatabase();
+ try (Cursor c= db.rawQuery(sql, new String[]{like}
+ ) ) {
+ out.addAll(getStopsFromCursorAllFields(c));
+ }
+
+ return out;
+ }
+
/**
* Get the list of stop in the query, with all the possible fields {NextGenDB.QUERY_COLUMN_stops_all}
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
@@ -22,18 +22,23 @@
import android.content.pm.PackageManager;
import android.os.Bundle;
+import android.text.InputType;
+import android.widget.TextView;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageButton;
+import androidx.appcompat.widget.SearchView;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.util.Log;
@@ -48,15 +53,18 @@
import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
-import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;
import it.reyboz.bustorino.BuildConfig;
import it.reyboz.bustorino.R;
+import it.reyboz.bustorino.adapters.SquareStopAdapter;
import it.reyboz.bustorino.backend.*;
import it.reyboz.bustorino.util.Permissions;
import it.reyboz.bustorino.viewmodels.IntroViewModel;
+import it.reyboz.bustorino.viewmodels.SearchStopsDBViewModel;
import org.jetbrains.annotations.NotNull;
import static it.reyboz.bustorino.util.Permissions.LOCATION_PERMISSIONS;
@@ -81,7 +89,7 @@
public final static String FRAGMENT_TAG = "MainScreenFragment";
private enum SearchMode {SEARCH_ID,SEARCH_NAME,INITIAL}
- public enum InternalScreen {
+ public enum InitialScreen {
HOME_BUTTONS(0),
NEARBY_STOPS(1),
ARRIVALS(2),
@@ -89,21 +97,21 @@
NEARBY_ARRIVALS(4);
public final int code;
- InternalScreen(int code) { this.code = code; }
+ InitialScreen(int code) { this.code = code; }
@Nullable
- public static InternalScreen fromCode(int code) {
- for (InternalScreen c : values()) if (c.code == code) return c;
+ public static InitialScreen fromCode(int code) {
+ for (InitialScreen c : values()) if (c.code == code) return c;
return null;
}
@NonNull
- public static InternalScreen fromFragmentKind(@NonNull FragmentKind kind){
+ public static InitialScreen fromFragmentKind(@NonNull FragmentKind kind){
switch (kind){
- case HOME_BUTTONS -> { return InternalScreen.HOME_BUTTONS; }
- case NEARBY_STOPS -> { return InternalScreen.NEARBY_STOPS; }
- case FragmentKind.ARRIVALS -> { return InternalScreen.ARRIVALS; }
- case FragmentKind.STOPS -> { return InternalScreen.STOP_SEARCH; }
- case FragmentKind.NEARBY_ARRIVALS -> { return InternalScreen.NEARBY_ARRIVALS; }
+ case HOME_BUTTONS -> { return InitialScreen.HOME_BUTTONS; }
+ case NEARBY_STOPS -> { return InitialScreen.NEARBY_STOPS; }
+ case FragmentKind.ARRIVALS -> { return InitialScreen.ARRIVALS; }
+ case FragmentKind.STOPS -> { return InitialScreen.STOP_SEARCH; }
+ case FragmentKind.NEARBY_ARRIVALS -> { return InitialScreen.NEARBY_ARRIVALS; }
default -> {
throw new IllegalArgumentException("Unknown fragment kind");
}
@@ -113,13 +121,14 @@
private FragmentHelper fragmentHelper;
private SwipeRefreshLayout swipeRefreshLayout;
- private EditText busStopSearchByIDEditText;
- private EditText busStopSearchByNameEditText;
+ //private EditText busStopSearchByIDEditText;
+ //private EditText busStopSearchByNameEditText;
+
+ private SearchView busStopSearchView;
private ProgressBar progressBar;
private FloatingActionButton floatingActionButton;
- /// VIEW MODELS in BaseFragment
-
+ private SearchStopsDBViewModel searchStopsViewModel;
private boolean setupOnStart = true;
private boolean suppressArrivalsReload = false;
@@ -138,9 +147,13 @@
private String pendingStopID = null;
private String pendingSearchQuery = null;
- private InternalScreen internalScreen = InternalScreen.HOME_BUTTONS;
+ private InitialScreen initialScreen = InitialScreen.HOME_BUTTONS;
private CoordinatorLayout coordLayout;
+ private RecyclerView suggestionsRecyclerView;
+ private SquareStopAdapter suggestionsAdapter = null;
+ private TextView stopSearchMessageTextView;
+
//this is really a hackish thing, but it works
private final LinkedBlockingQueue<Runnable> thingsToDoOnStart = new LinkedBlockingQueue<>();
@@ -203,14 +216,14 @@
}
- public static MainScreenFragment newInstance(@NonNull InternalScreen kind,
+ public static MainScreenFragment newInstance(@NonNull InitialScreen kind,
@Nullable String stopId,
@Nullable String query) {
MainScreenFragment f = new MainScreenFragment();
f.setArguments(makeArgs(kind, stopId, query));
return f;
}
- public static MainScreenFragment newInstance(@NonNull InternalScreen kind, @Nullable Bundle args){
+ public static MainScreenFragment newInstance(@NonNull InitialScreen kind, @Nullable Bundle args){
MainScreenFragment f = new MainScreenFragment();
if (args != null) {
f.setArguments(args);
@@ -225,7 +238,7 @@
* @param query
* @return
*/
- public static Bundle makeArgs(@NonNull InternalScreen kind, @Nullable String stopId, @Nullable String query) {
+ public static Bundle makeArgs(@NonNull InitialScreen kind, @Nullable String stopId, @Nullable String query) {
Bundle b = new Bundle();
b.putInt(ARG_INITIAL_CONTENT, kind.code);
if (stopId != null) b.putString(ARG_STOP_ID, stopId);
@@ -233,16 +246,16 @@
return b;
}
public static Bundle makeArgsArrivals(@NonNull String stopID){
- return makeArgs(InternalScreen.ARRIVALS, stopID, null);
+ return makeArgs(InitialScreen.ARRIVALS, stopID, null);
}
public static Bundle makeArgsStops(@NonNull String query){
- return makeArgs(InternalScreen.STOP_SEARCH, query, null);
+ return makeArgs(InitialScreen.STOP_SEARCH, query, null);
}
public static Bundle makeArgsNearby(){
- return makeArgs(InternalScreen.NEARBY_STOPS, null, null);
+ return makeArgs(InitialScreen.NEARBY_STOPS, null, null);
}
public static Bundle makeArgsButtonsScreen(){
- return makeArgs(InternalScreen.HOME_BUTTONS, null, null);
+ return makeArgs(InitialScreen.HOME_BUTTONS, null, null);
}
@@ -254,9 +267,9 @@
Log.d(DEBUG_TAG, "ARGS ARE NOT NULL: "+ args);
if (args.containsKey(ARG_INITIAL_CONTENT)) {
- int code = args.getInt(ARG_INITIAL_CONTENT, InternalScreen.HOME_BUTTONS.code);
- InternalScreen parsed = InternalScreen.fromCode(code);
- internalScreen = (parsed != null) ? parsed : InternalScreen.HOME_BUTTONS;
+ int code = args.getInt(ARG_INITIAL_CONTENT, InitialScreen.HOME_BUTTONS.code);
+ InitialScreen parsed = InitialScreen.fromCode(code);
+ initialScreen = (parsed != null) ? parsed : InitialScreen.HOME_BUTTONS;
}
String stopId = args.getString(ARG_STOP_ID);
if (stopId != null)
@@ -266,7 +279,6 @@
}
fragmentHelper = new FragmentHelper(this, getChildFragmentManager(), getContext(), R.id.resultFrame);
-
}
@Override
@@ -285,14 +297,31 @@
// Inflate the layout for this fragment
View root = inflater.inflate(R.layout.fragment_main_screen, container, false);
/// UI ELEMENTS //
- busStopSearchByIDEditText = root.findViewById(R.id.busStopSearchByIDEditText);
- busStopSearchByNameEditText = root.findViewById(R.id.busStopSearchByNameEditText);
+ //busStopSearchByIDEditText = root.findViewById(R.id.busStopSearchByIDEditText);
+ //busStopSearchByNameEditText = root.findViewById(R.id.busStopSearchByNameEditText);
+ busStopSearchView = root.findViewById(R.id.busStopSearchView);
progressBar = root.findViewById(R.id.progressBar);
swipeRefreshLayout = root.findViewById(R.id.listRefreshLayout);
floatingActionButton = root.findViewById(R.id.floatingActionButton);
- busStopSearchByIDEditText.setSelectAllOnFocus(true);
- busStopSearchByIDEditText
+ stopSearchMessageTextView = root.findViewById(R.id.stopSearchMessageTextView);
+ suggestionsRecyclerView = root.findViewById(R.id.suggestionsRecyclerView);
+ suggestionsRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(),LinearLayoutManager.VERTICAL, false));
+ EditText searchEditText = busStopSearchView.findViewById(androidx.appcompat.R.id.search_src_text);
+ searchEditText.setSelectAllOnFocus(true);
+ searchEditText.setOnFocusChangeListener( (view,hasFocus) ->{
+ if(hasFocus){
+ showFloatingActionButton(true);
+ }
+ });
+
+ busStopSearchView.setOnFocusChangeListener( (view, hasFocus) ->{
+ if(hasFocus){
+ showFloatingActionButton(true);
+ }
+ });
+ //busStopSearchView.setSelectAllOnFocus(true);
+ /*busStopSearchByIDEditText
.setOnEditorActionListener((v, actionId, event) -> {
// IME_ACTION_SEARCH alphabetical option
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
@@ -301,7 +330,9 @@
}
return false;
});
- busStopSearchByNameEditText
+
+ */
+ searchEditText
.setOnEditorActionListener((v, actionId, event) -> {
// IME_ACTION_SEARCH alphabetical option
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
@@ -311,6 +342,19 @@
return false;
});
+ busStopSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String q) {
+ return false;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String q) {
+ searchStopsViewModel.searchStops(q, searchMode != SearchMode.SEARCH_NAME);
+ return true;
+ }
+ });
+
swipeRefreshLayout
.setOnRefreshListener(this::refreshStop);
swipeRefreshLayout.setColorSchemeResources(R.color.blue_500, R.color.orange_500);
@@ -319,7 +363,7 @@
floatingActionButton.setImageResource(R.drawable.magnifying_glass_larger);
floatingActionButton.setOnClickListener((this::onToggleKeyboardLayout));
- busStopSearchByIDEditText.setOnFocusChangeListener((v, hasFocus) -> {
+ /*busStopSearchByIDEditText.setOnFocusChangeListener((v, hasFocus) -> {
//Log.d(DEBUG_TAG, "stop search by ID has focus: " + hasFocus);
if(hasFocus)
setSearchModeBusStopID();
@@ -331,6 +375,8 @@
setSearchModeBusStopName();
});
+ */
+
AppCompatImageButton qrButton = root.findViewById(R.id.QRButton);
qrButton.setOnClickListener(this::onQRButtonClick);
@@ -381,16 +427,19 @@
super.onViewCreated(view, savedInstanceState);
Log.d(DEBUG_TAG, "onViewCreated, SwipeRefreshLayout visible: "+(swipeRefreshLayout.getVisibility()==View.VISIBLE));
Log.d(DEBUG_TAG, "Saved instance state is: "+savedInstanceState);
- //Restore instance state
- /*if (savedInstanceState!=null){
- Fragment fragment = getChildFragmentManager().getFragment(savedInstanceState, SAVED_FRAGMENT);
- if (fragment!=null){
- getChildFragmentManager().beginTransaction().add(R.id.resultFrame, fragment).commit();
- setupOnStart = false;
+ searchStopsViewModel = new ViewModelProvider(requireActivity()).get(SearchStopsDBViewModel.class);
+
+ searchStopsViewModel.getFilteredStopsSearch().observe(getViewLifecycleOwner(),stops -> {setSuggestionsStopRecyclerView(stops, true);});
+
+ /*if(res){
+ if(!searchStopsResultsFragmentShown())
+ showSearchStopsResultsFragment();
+ } else if (searchStopsResultsFragmentShown()) {
+ childFragMan.popBackStack(); //remove the fragment
}
- }
- */
+ */
+
if (getChildFragmentManager().findFragmentById(R.id.resultFrame)!= null){
swipeRefreshLayout.setVisibility(View.VISIBLE);
// The child FragmentManager has restored its content — don't dispatch again
@@ -399,13 +448,13 @@
if (savedInstanceState != null) return;
- showDifferentSubFragments(internalScreen);
+ showDifferentSubFragments(initialScreen);
}
/**
* Installs the initial child fragment based on the arguments supplied as arguments
*/
- private void showDifferentSubFragments(@NonNull InternalScreen screen) {
+ private void showDifferentSubFragments(@NonNull InitialScreen screen) {
boolean firstTime = !initialScreenShown;
switch (screen) {
case NEARBY_STOPS:
@@ -451,6 +500,34 @@
}
+ public void setSuggestionsStopRecyclerView(List<Stop> stops, boolean showMessage){
+
+ var res = !stops.isEmpty();
+ var query = searchStopsViewModel.getQueryStops();
+ Log.d(DEBUG_TAG, "received stops suggestions, are "+stops.size());
+ if(res){
+ if(suggestionsAdapter!=null){
+ suggestionsAdapter.setStops(stops);
+ } else{
+ suggestionsAdapter = new SquareStopAdapter(new ArrayList<>(stops), this, null, true);
+ suggestionsRecyclerView.setAdapter(suggestionsAdapter);
+ }
+ suggestionsRecyclerView.setVisibility(View.VISIBLE);
+
+ } else{
+ if(suggestionsAdapter !=null) suggestionsAdapter = null;
+ suggestionsRecyclerView.setVisibility(View.GONE);
+ if(showMessage && query!=null && !query.trim().isEmpty()){
+ stopSearchMessageTextView.setText( searchMode == SearchMode.SEARCH_NAME ?
+ R.string.no_stop_found_search_name : R.string.no_stop_found_search_number);
+ stopSearchMessageTextView.setVisibility(View.VISIBLE);
+ } else{
+ stopSearchMessageTextView.setVisibility(View.GONE);
+ }
+
+ }
+ }
+
public void setSuppressArrivalsReload(boolean value){
suppressArrivalsReload = value;
// we have to suppress the reloading of the (possible) ArrivalsFragment
@@ -644,7 +721,8 @@
@Override
public void onQrScanSuccess(@NotNull String busIDToSearch) {
- busStopSearchByIDEditText.setText(busIDToSearch);
+ EditText searchEditText = busStopSearchView.findViewById(androidx.appcompat.R.id.search_src_text);
+ searchEditText.setText(busIDToSearch);
requestArrivalsForStopID(busIDToSearch);
}
@@ -664,13 +742,13 @@
*/
public void onSearchClick(View v) {
//final StopsFinderByName[] stopsFinderByNames = new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()};
- if (searchMode == SearchMode.SEARCH_ID) {
- String busStopID = busStopSearchByIDEditText.getText().toString();
+ if (searchMode == SearchMode.SEARCH_ID || searchMode == SearchMode.INITIAL) {
+ String busStopID = busStopSearchView.getQuery().toString();
fragmentHelper.stopLastRequestIfNeeded();
requestArrivalsForStopID(busStopID);
} else if (searchMode == SearchMode.SEARCH_NAME) {
// searchMode == SEARCH_BY_NAME
- String query = busStopSearchByNameEditText.getText().toString();
+ String query = busStopSearchView.getQuery().toString();
query = query.trim();
if(getContext()!=null) {
if (query.length() < 1) {
@@ -688,17 +766,17 @@
public void onToggleKeyboardLayout(View v) {
switch (searchMode){
case SEARCH_ID:
- setSearchModeBusStopName();
- if (busStopSearchByNameEditText.requestFocus()) {
+ setSearchMode(SearchMode.SEARCH_NAME);
+ if (busStopSearchView.requestFocus())
showKeyboard();
- }
+ //}
break;
case SEARCH_NAME:
case INITIAL:
- setSearchModeBusStopID();
- if (busStopSearchByIDEditText.requestFocus()) {
- showKeyboard();
- }
+ setSearchMode(SearchMode.SEARCH_ID);
+ if (busStopSearchView.requestFocus())
+ showKeyboard();
+ //}
}
}
@@ -709,52 +787,52 @@
}
////////////////////////////////////// GUI HELPERS /////////////////////////////////////////////
+
+ private EditText getSearchEditText() {
+ return busStopSearchView.findViewById(androidx.appcompat.R.id.search_src_text);
+ }
public void showKeyboard() {
if(getActivity() == null) return;
- InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
- View view;
- if(searchMode == SearchMode.SEARCH_ID)
- view= busStopSearchByIDEditText;
- else if(searchMode == SearchMode.SEARCH_NAME)
- view = busStopSearchByNameEditText;
- else{
- Log.e(DEBUG_TAG, "Asking to show keyboard but SearchMode is "+searchMode+", ignoring");
- return;
- }
-
- imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
+ final EditText et = getSearchEditText();
+ et.requestFocus();
+ et.post(() -> {
+ InputMethodManager imm = (InputMethodManager)
+ requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm == null) return;
+ imm.restartInput(et); // applica il nuovo inputType
+ imm.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT);
+ });
}
- private void setSearchModeBusStopID() {
- searchMode = SearchMode.SEARCH_ID;
- busStopSearchByNameEditText.setVisibility(View.GONE);
- busStopSearchByNameEditText.setText("");
- busStopSearchByIDEditText.setVisibility(View.VISIBLE);
- floatingActionButton.setImageResource(R.drawable.alphabetical);
- }
- private void setSearchModeBusStopName() {
- searchMode = SearchMode.SEARCH_NAME;
- busStopSearchByIDEditText.setVisibility(View.GONE);
- busStopSearchByIDEditText.setText("");
- busStopSearchByNameEditText.setVisibility(View.VISIBLE);
- floatingActionButton.setImageResource(R.drawable.numeric);
- }
protected boolean isNearbyFragmentShown(){
Fragment fragment = getChildFragmentManager().findFragmentByTag(NearbyStopsFragment.FRAGMENT_TAG);
return (fragment!= null && fragment.isResumed());
}
- /**
+ private void setSearchMode(SearchMode mode) {
+ searchMode = mode;
+ busStopSearchView.setQuery("", false);
+ boolean byId = mode != SearchMode.SEARCH_NAME;
+ busStopSearchView.setInputType(byId ? InputType.TYPE_CLASS_NUMBER : InputType.TYPE_CLASS_TEXT);
+ floatingActionButton.setImageResource(byId ? R.drawable.numeric : R.drawable.alphabetical);
+ busStopSearchView.setQueryHint(getString(byId ? R.string.insert_bus_stop_number : R.string.insert_bus_stop_name));
+ }
+
+ /*
* Having that cursor at the left of the edit text makes me cancer.
*
* @param busStopID bus stop ID
*/
+ //
+ /*
private void setBusStopSearchByIDEditText(String busStopID) {
busStopSearchByIDEditText.setText(busStopID);
busStopSearchByIDEditText.setSelection(busStopID.length());
}
+ */
+
@Nullable
@Override
public View getBaseViewForSnackBar() {
@@ -777,12 +855,15 @@
private void prepareGUIForArrivals() {
swipeRefreshLayout.setEnabled(true);
swipeRefreshLayout.setVisibility(View.VISIBLE);
+ setSuggestionsStopRecyclerView(List.of(), false);
//actionHelpMenuItem.setVisible(true);
}
private void prepareGUIForBusStops() {
swipeRefreshLayout.setEnabled(false);
swipeRefreshLayout.setVisibility(View.VISIBLE);
+ setSuggestionsStopRecyclerView(List.of(), false);
+
//actionHelpMenuItem.setVisible(false);
}
@@ -832,6 +913,37 @@
}
+ /*
+ // KEEPING THIS METHODS AS EXAMPLES FOR SHOW
+ boolean searchStopsResultsFragmentShown(){
+ Fragment frag = childFragMan.findFragmentById(R.id.resultFrame);
+ return frag instanceof StopSearchResultFragment;
+ }
+ void showSearchStopsResultsFragment(){
+ final String TAG = "stopSearchResult";
+ Fragment frag = childFragMan.findFragmentById(R.id.resultFrame);
+ if (frag instanceof StopSearchResultFragment){
+ return; //nothing to do
+ }
+ boolean exists = frag != null;
+ var trans = childFragMan.beginTransaction();
+
+ frag = childFragMan.findFragmentByTag(TAG);
+ if (!(frag instanceof StopSearchResultFragment)) {
+ frag = StopSearchResultFragment.newInstance();
+ }
+ if(exists){
+ //show the fragment
+ trans.replace(R.id.resultFrame,frag, TAG);
+ } else{
+ //create new fragment
+ trans.add(R.id.resultFrame,frag, TAG);
+ }
+ trans.addToBackStack(null);
+ trans.commit();
+ }
+ */
+
@Override
public void openLineFromStop(String routeGtfsId, @Nullable String stopIDFrom) {
//pass to activity
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
@@ -732,7 +732,7 @@
Collections.sort(stops, StopSorterByDistance(location))
if (dataAdapter == null) {
- dataAdapter = SquareStopAdapter(stops, mListener, lastPosition)
+ dataAdapter = SquareStopAdapter(ArrayList(stops), mListener, lastPosition, false)
firstLocForStops = false
} else {
dataAdapter!!.setUserPosition(lastPosition)
diff --git a/app/src/main/java/it/reyboz/bustorino/util/StopSorterSearch.kt b/app/src/main/java/it/reyboz/bustorino/util/StopSorterSearch.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/util/StopSorterSearch.kt
@@ -0,0 +1,31 @@
+package it.reyboz.bustorino.util
+
+import it.reyboz.bustorino.backend.Stop
+
+class StopSorterSearch(val searchById: Boolean): Comparator<Stop> {
+ override fun compare(s0: Stop?, s1: Stop?): Int {
+ if (s0 ==null) {
+ if (s1 != null) return 1
+ else return 0
+ }
+ else if(s1 == null){
+ //s0 is not null
+ return -1
+ }
+ if(s0.location==null){
+ if(s1.location != null) return 1
+ } else if(s1.location==null) return -1
+
+ if(searchById){
+ val lenDiff = s0.ID.length - s1.ID.length
+ if(lenDiff!=0) return lenDiff
+ //second criterion
+ val diff = s0.ID.toInt() - s1.ID.toInt()
+ //if(diff!=0) return diff
+ return diff
+ } else{
+ return -1*(s0.numRoutesStopping - s1.numRoutesStopping)
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/SearchStopsDBViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/SearchStopsDBViewModel.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/SearchStopsDBViewModel.kt
@@ -0,0 +1,85 @@
+package it.reyboz.bustorino.viewmodels
+
+import android.app.Application
+import android.util.Log
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.MediatorLiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.distinctUntilChanged
+import androidx.lifecycle.liveData
+import androidx.lifecycle.map
+import androidx.lifecycle.switchMap
+import androidx.lifecycle.viewModelScope
+import it.reyboz.bustorino.backend.Stop
+import it.reyboz.bustorino.data.NextGenDB
+import it.reyboz.bustorino.util.StopSorterSearch
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.delay
+import kotlin.math.min
+import kotlin.time.Duration.Companion.milliseconds
+
+class SearchStopsDBViewModel(application: Application): AndroidViewModel(application) {
+
+ private data class Request(val q: String, val byId: Boolean)
+
+ private val nextGenDB = NextGenDB.getInstance(application)
+
+
+ private val queryLiveData = MutableLiveData(Request("", true))
+ private val numberLimitStop = MutableLiveData(20)
+ val queryResultsLiveData = queryLiveData.distinctUntilChanged().switchMap { r->
+ liveData(viewModelScope.coroutineContext + Dispatchers.IO, timeoutInMs = 0) {
+ if (r.q.isEmpty()) {
+ //showQueryResult.postValue(false)
+ emit(emptyList<Stop>())
+ }
+ else {
+ delay(250.milliseconds)
+ //showQueryResult.postValue(true)
+ val list = nextGenDB.searchStopsByCodeOrName(r.q, r.byId)
+ /*if (r.byId)
+ emit(list.sortedBy { it.ID })
+ else
+ emit(list.sortedBy { it.numRoutesStopping }.reversed())
+
+ */
+ emit(list.sortedWith(StopSorterSearch(r.byId)))
+ }
+ }
+ }
+
+ val showQueryResult = queryResultsLiveData.map { it.isNotEmpty() }
+
+ fun searchStops(query: String, byId: Boolean){
+ Log.d(TAG, "setting query $query with id $byId")
+ this.queryLiveData.value = Request(query, byId)
+ }
+ fun getQueryStops(): String?{
+ return queryLiveData.value?.q
+ }
+ fun setLimitSearchStops(num: Int){
+ numberLimitStop.value = num
+ }
+
+
+ val filteredStopsSearch = MediatorLiveData<List<Stop>>()
+ private fun setFilteredStops(stops:List<Stop>, num: Int){
+ filteredStopsSearch.postValue(stops.subList(0, min(num, stops.size)))
+ }
+
+ init {
+ filteredStopsSearch.addSource(queryResultsLiveData) {
+ setFilteredStops(it, numberLimitStop.value!!)
+ }
+ filteredStopsSearch.addSource(numberLimitStop) {
+ queryResultsLiveData.value?.let{ stops ->
+ setFilteredStops(stops, it)
+ }
+ }
+ }
+
+ companion object{
+ private const val TAG = "BusTO-SearchStopsVM"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_main_screen.xml b/app/src/main/res/layout/fragment_main_screen.xml
--- a/app/src/main/res/layout/fragment_main_screen.xml
+++ b/app/src/main/res/layout/fragment_main_screen.xml
@@ -6,115 +6,156 @@
tools:context=".fragments.MainScreenFragment"
android:paddingTop="10dip"
>
- <ImageButton
- android:id="@+id/QRButton"
- style="?android:attr/borderlessButtonStyle"
- android:layout_width="40dip"
- android:layout_height="40dip"
- android:layout_marginStart="16dp"
- android:background="@drawable/qrcode_button_custom"
- android:contentDescription="@string/scan_qr_code_stop"
- android:scaleType="fitCenter"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- />
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/leftGuide"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- app:layout_constraintStart_toEndOf="@id/QRButton"
- />
- <EditText
- android:id="@+id/busStopSearchByIDEditText"
+ <com.google.android.material.card.MaterialCardView
+ android:id="@+id/searchCardView"
android:layout_width="0dp"
android:layout_height="wrap_content"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/progressBar"
+ app:cardCornerRadius="24dp"
+ app:cardElevation="2dp"
+ app:cardBackgroundColor="?attr/colorSurface"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
- android:ems="10"
- android:hint="@string/insert_bus_stop_number"
- android:imeOptions="actionSearch"
+ android:layout_marginBottom="5dp"
+ android:paddingBottom="4dp"
+ android:animateLayoutChanges="true"
+ >
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <androidx.appcompat.widget.SearchView
+ android:id="@+id/busStopSearchView"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"
+ android:layout_marginEnd="10dp"
+ android:imeOptions="actionSearch"
+ android:inputType="number"
+ app:iconifiedByDefault="false"
+ app:queryHint="@string/insert_bus_stop_number"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/barrierSearch"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/searchButton"
+ app:queryBackground="@null"
+ app:submitBackground="@null"
- android:inputType="number"
- android:selectAllOnFocus="true"
- android:singleLine="true"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="@id/leftGuide"
- app:layout_constraintEnd_toStartOf="@id/searchButton"
- >
- </EditText>
+ />
+ <ImageButton
+ android:id="@+id/searchButton"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="43dp"
+ android:layout_height="43dip"
+ android:layout_alignTop="@+id/busStopSearchView"
+ android:layout_marginEnd="5dp"
- <!--android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"-->
- <EditText
- android:id="@+id/busStopSearchByNameEditText"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginEnd="10dp"
- android:layout_marginStart="10dp"
- android:inputType="text"
- android:ems="10"
- android:hint="@string/insert_bus_stop_name"
- android:imeOptions="actionSearch"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="@id/leftGuide"
- app:layout_constraintEnd_toStartOf="@id/searchButton"
- android:singleLine="true"
- android:visibility="gone">
- </EditText>
+ android:background="@drawable/search_button_custom"
+ android:contentDescription="@string/search"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/barrierSearch"
+ app:layout_constraintStart_toEndOf="@id/busStopSearchView"
+ app:layout_constraintEnd_toStartOf="@id/QRButton"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/QRButton"
+ style="?android:attr/borderlessButtonStyle"
+ android:layout_width="40dip"
+ android:layout_height="40dip"
+ android:layout_marginStart="6dp"
+ android:layout_marginEnd="12dp"
+ android:background="@drawable/qrcode_button_custom"
+ android:contentDescription="@string/scan_qr_code_stop"
+ android:scaleType="fitCenter"
- <ImageButton
- android:id="@+id/searchButton"
- style="?android:attr/borderlessButtonStyle"
- android:layout_width="40dip"
- android:layout_height="40dip"
- android:layout_alignTop="@+id/busStopSearchByIDEditText"
- android:layout_marginEnd="16dp"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- android:background="@drawable/search_button_custom"
- android:contentDescription="@string/search"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/barrierSearch"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toEndOf="@id/searchButton"
/>
+ <androidx.constraintlayout.widget.Barrier
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/barrierSearch"
+ app:barrierDirection="bottom"
+ app:constraint_referenced_ids="searchButton,busStopSearchView,QRButton"
+ />
+ <androidx.recyclerview.widget.RecyclerView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:id="@+id/suggestionsRecyclerView"
+ android:layout_marginTop="5dp"
+ android:layout_marginStart="10dp"
+ android:layout_marginEnd="10dp"
+ android:layout_marginBottom="10dp"
+ app:layout_constraintTop_toBottomOf="@id/barrierSearch"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/stopSearchMessageTextView"
+ app:layout_constraintHeight_default="wrap"
+ android:visibility="visible"
+ />
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/stopSearchMessageTextView"
+ app:layout_constraintTop_toBottomOf="@id/suggestionsRecyclerView"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:text="@string/no_stop_found_search_number"
+ android:fontFamily="@font/lato_regular"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="5dp"
+ android:visibility="visible"
+ />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+ </com.google.android.material.card.MaterialCardView>
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="8dp"
- android:layout_below="@+id/QRButton"
- android:layout_marginTop="5dp"
+ android:layout_marginTop="3dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:indeterminateOnly="true"
android:minWidth="10dp"
android:visibility="gone"
- app:layout_constraintTop_toBottomOf="@id/searchButton"
+ app:layout_constraintTop_toBottomOf="@id/searchCardView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
- <androidx.constraintlayout.widget.Barrier
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/barrierSearch"
- app:barrierDirection="bottom"
- app:constraint_referenced_ids="searchButton,QRButton,busStopSearchByIDEditText,busStopSearchByNameEditText"
- />
+
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:id="@+id/coord_layout"
android:layout_gravity="bottom|end"
android:layout_marginTop="4dp"
- app:layout_constraintTop_toBottomOf="@id/barrierSearch"
+ app:layout_constraintTop_toBottomOf="@id/searchCardView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:flow_verticalBias="0.0"
app:layout_constraintVertical_bias="0.0"
+ android:animateLayoutChanges="true"
>
- <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ >
+
+ <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/listRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -126,10 +167,12 @@
<FrameLayout
android:layout_width="match_parent"
android:id="@+id/resultFrame"
- android:layout_height="fill_parent"
+ android:layout_height="match_parent"
android:layout_marginTop="5dp"
android:layout_alignParentStart="true"/>
- </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+ </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+ </LinearLayout>
+
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/floatingActionButton"
diff --git a/app/src/main/res/layout/item_stop_nearby_card.xml b/app/src/main/res/layout/item_stop_nearby_card.xml
--- a/app/src/main/res/layout/item_stop_nearby_card.xml
+++ b/app/src/main/res/layout/item_stop_nearby_card.xml
@@ -28,7 +28,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="7261"
- android:textSize="19sp"
+ android:textSize="20sp"
android:textIsSelectable="true"
android:fontFamily="@font/lato_bold"
android:textColor="@color/stop_number_color"
@@ -56,6 +56,23 @@
app:layout_constraintStart_toEndOf="@id/stop_numberText"
app:layout_constraintEnd_toStartOf="@id/stop_distanceTextView"
/>
+
+ <TextView
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:text="STOP"
+ android:id="@+id/stop_locationTextView"
+ android:gravity="center_vertical|start"
+ android:textSize="15sp"
+ android:fontFamily="@font/lato_regular"
+ android:layout_marginBottom="6dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginStart="30dp"
+ android:layout_marginEnd="20dp"
+ app:layout_constraintTop_toBottomOf="@id/stop_nameText"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/stop_distanceTextView"
+ />
<TextView
android:text="200m"
android:layout_width="wrap_content"
@@ -86,6 +103,19 @@
android:layout_marginTop="8dp"
android:layout_marginStart="12dp"
/>-->
+ <ImageView
+ android:id="@+id/cardBusIcon"
+ android:layout_width="26dp"
+ android:layout_height="26dp"
+ android:layout_marginStart="13sp"
+ android:layout_marginTop="5sp"
+
+ android:src="@drawable/ic_bus"
+ android:scaleType="fitCenter"
+ app:tint="@color/black_icon_text"
+ app:layout_constraintTop_toBottomOf="@id/stop_locationTextView"
+ app:layout_constraintStart_toStartOf="parent"
+ />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
@@ -98,13 +128,13 @@
android:layout_marginTop="8dp"
android:layout_marginBottom="10dp"
android:layout_marginEnd="15dp"
+ android:layout_marginStart="6dp"
- app:layout_constraintTop_toBottomOf="@id/stop_nameText"
- app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@id/stop_locationTextView"
+ app:layout_constraintStart_toEndOf="@id/cardBusIcon"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/stop_distanceTextView"
- android:layout_marginStart="50dp"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
\ No newline at end of file
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -267,4 +267,6 @@
<string name="no_trip_info_warning">Nessuna informazione trasmessa sulla direzione o sul viaggio del veicolo.</string>
<string name="downloading_trip_info">Download in corso delle informazioni sul viaggio</string>
+ <string name="no_stop_found_search_name">Nessuna fermata trovata con questo nome</string>
+ <string name="no_stop_found_search_number">Nessuna fermata trovata con questo numero</string>
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -164,6 +164,8 @@
<string name="position_searching_message">Finding location</string>
<string name="no_stops_nearby">No stops nearby</string>
+ <string name="no_stop_found_search_name">No stop found matching this name</string>
+ <string name="no_stop_found_search_number">No stop found matching this number</string>
<string name="searching_arrivals_indefinite">Loading arrival times</string>
<string name="no_stops_nearby_arrivals">No stops nearby to search arrival times for</string>
<string name="pref_num_elements">Minimum number of stops</string>

File Metadata

Mime Type
text/plain
Expires
Fri, Oct 2, 03:21 (19 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2204418
Default Alt Text
D259.1790904070.diff (49 KB)

Event Timeline