mirror of
https://github.com/ClaytonWWilson/Listify.git
synced 2025-12-15 10:28:46 +00:00
Merge pull request #160 from ClaytonWWilson/search-suggestions
Search history and recent searches displayed under search bar
This commit is contained in:
commit
3a6ebce1c5
@ -36,6 +36,7 @@ import org.json.JSONException;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ import static com.example.listify.SplashActivity.showSplash;
|
|||||||
public class MainActivity extends AppCompatActivity implements CreateListDialogFragment.OnNewListListener {
|
public class MainActivity extends AppCompatActivity implements CreateListDialogFragment.OnNewListListener {
|
||||||
private AppBarConfiguration mAppBarConfiguration;
|
private AppBarConfiguration mAppBarConfiguration;
|
||||||
public static AuthManager am = new AuthManager();
|
public static AuthManager am = new AuthManager();
|
||||||
|
public static ArrayList<String> searchHistory;
|
||||||
private File newImageFileLocation = null;
|
private File newImageFileLocation = null;
|
||||||
private final int CAMERA_CAPTURE = 1;
|
private final int CAMERA_CAPTURE = 1;
|
||||||
private final int IMAGE_SELECT = 2;
|
private final int IMAGE_SELECT = 2;
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
package com.example.listify;
|
package com.example.listify;
|
||||||
|
import android.app.SearchManager;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
@ -7,12 +8,14 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.SearchView;
|
//import android.widget.SearchView;
|
||||||
|
import androidx.appcompat.widget.SearchView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.example.listify.adapter.SearchResultsListAdapter;
|
import com.example.listify.adapter.SearchResultsListAdapter;
|
||||||
@ -28,12 +31,16 @@ import java.util.List;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import static com.example.listify.MainActivity.am;
|
import static com.example.listify.MainActivity.am;
|
||||||
|
import static com.example.listify.MainActivity.searchHistory;
|
||||||
|
|
||||||
public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener, Requestor.Receiver {
|
public class SearchResults extends AppCompatActivity implements FilterDialogFragment.OnFilterListener, SortDialogFragment.OnSortListener, Requestor.Receiver {
|
||||||
private ListView resultsListView;
|
private ListView resultsListView;
|
||||||
private MenuItem filterItem;
|
private MenuItem filterItem;
|
||||||
private ProgressBar loadingSearch;
|
private ProgressBar loadingSearch;
|
||||||
private TextView tvNoResults;
|
private TextView tvNoResults;
|
||||||
|
private SearchView.SearchAutoComplete searchAutoComplete;
|
||||||
|
private ArrayList<String> orderedHistory = new ArrayList<>();
|
||||||
|
private ArrayAdapter<String> searchHistoryAdapter;
|
||||||
private SearchResultsListAdapter searchResultsListAdapter;
|
private SearchResultsListAdapter searchResultsListAdapter;
|
||||||
private List<Product> resultsProductList = new ArrayList<>();
|
private List<Product> resultsProductList = new ArrayList<>();
|
||||||
private List<Product> resultsProductListSorted = new ArrayList<>();
|
private List<Product> resultsProductListSorted = new ArrayList<>();
|
||||||
@ -85,19 +92,19 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag
|
|||||||
|
|
||||||
// There's no easy way to find the close button on the search bar, so this is the way I'm
|
// There's no easy way to find the close button on the search bar, so this is the way I'm
|
||||||
// doing it
|
// doing it
|
||||||
int searchCloseButtonId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null);
|
// int searchCloseButtonId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null);
|
||||||
ImageView closeButton = (ImageView) searchView.findViewById(searchCloseButtonId);
|
// ImageView closeButton = (ImageView) searchView.findViewById(searchCloseButtonId);
|
||||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
// closeButton.setOnClickListener(new View.OnClickListener() {
|
||||||
// Override default close behavior to only clear the search text and the query
|
// // Override default close behavior to only clear the search text and the query
|
||||||
@Override
|
// @Override
|
||||||
public void onClick(View v) {
|
// public void onClick(View v) {
|
||||||
// Finding the edit text of the search bar. Same as the method above
|
// // Finding the edit text of the search bar. Same as the method above
|
||||||
int searchTextId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
|
// int searchTextId = searchView.getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
|
||||||
EditText searchText = (EditText) searchView.findViewById(searchTextId);
|
// EditText searchText = (EditText) searchView.findViewById(searchTextId);
|
||||||
searchText.setText("");
|
// searchText.setText("");
|
||||||
searchView.setQuery("", false);
|
// searchView.setQuery("", false);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
resultsListView = (ListView) findViewById(R.id.search_results_list);
|
resultsListView = (ListView) findViewById(R.id.search_results_list);
|
||||||
searchResultsListAdapter = new SearchResultsListAdapter(this, resultsProductListSorted);
|
searchResultsListAdapter = new SearchResultsListAdapter(this, resultsProductListSorted);
|
||||||
@ -113,7 +120,7 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle searches
|
// Handle searches
|
||||||
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextSubmit(String query) {
|
public boolean onQueryTextSubmit(String query) {
|
||||||
@ -135,6 +142,49 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
searchAutoComplete = (SearchView.SearchAutoComplete) searchView.findViewById(androidx.appcompat.R.id.search_src_text);
|
||||||
|
|
||||||
|
SearchManager searchManager = (SearchManager) getSystemService(this.SEARCH_SERVICE);
|
||||||
|
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||||
|
|
||||||
|
orderedHistory.clear();
|
||||||
|
orderedHistory.addAll(searchHistory);
|
||||||
|
|
||||||
|
// Reverse the history so it's displayed in the correct ordered
|
||||||
|
for (int i = 0; i < orderedHistory.size() / 2; i++) {
|
||||||
|
String temp = orderedHistory.get(i);
|
||||||
|
orderedHistory.set(i, orderedHistory.get(orderedHistory.size() - i - 1));
|
||||||
|
orderedHistory.set(orderedHistory.size() - i - 1, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchHistoryAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.search_suggestion, orderedHistory);
|
||||||
|
System.out.println(orderedHistory);
|
||||||
|
|
||||||
|
searchAutoComplete.setAdapter(searchHistoryAdapter);
|
||||||
|
searchAutoComplete.setThreshold(0);
|
||||||
|
|
||||||
|
searchAutoComplete.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
String query = ((TextView) view).getText().toString();
|
||||||
|
searchView.setQuery(query, false);
|
||||||
|
|
||||||
|
// Show progress bar
|
||||||
|
loadingSearch.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// Clear the old search results
|
||||||
|
resultsProductList.clear();
|
||||||
|
|
||||||
|
// Clear old search results from the view
|
||||||
|
resultsProductListSorted.clear();
|
||||||
|
searchResultsListAdapter.notifyDataSetChanged();
|
||||||
|
|
||||||
|
doSearch(query);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -188,7 +238,6 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag
|
|||||||
if (resultsProductList.isEmpty()) {
|
if (resultsProductList.isEmpty()) {
|
||||||
filterItem.setEnabled(false);
|
filterItem.setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,6 +249,25 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void doSearch(String query) {
|
private void doSearch(String query) {
|
||||||
|
// Add this search to the history
|
||||||
|
searchHistory.add(query);
|
||||||
|
orderedHistory.clear();
|
||||||
|
orderedHistory.addAll(searchHistory);
|
||||||
|
ArrayList<String> t = new ArrayList<>();
|
||||||
|
t.addAll(searchHistory);
|
||||||
|
|
||||||
|
// Reverse the history so it's displayed in the correct ordered
|
||||||
|
for (int i = 0; i < t.size() / 2; i++) {
|
||||||
|
String temp = t.get(i);
|
||||||
|
t.set(i, t.get(t.size() - i - 1));
|
||||||
|
t.set(t.size() - i - 1, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Have to make a new adapter here because calling notifyDatasetChanged() would not update the search suggestions for some reason
|
||||||
|
searchHistoryAdapter = new ArrayAdapter<String>(getApplicationContext(), R.layout.search_suggestion, t);
|
||||||
|
searchAutoComplete.setAdapter(searchHistoryAdapter);
|
||||||
|
|
||||||
|
|
||||||
Properties configs = new Properties();
|
Properties configs = new Properties();
|
||||||
try {
|
try {
|
||||||
configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json");
|
configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json");
|
||||||
|
|||||||
@ -14,6 +14,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|||||||
import com.example.listify.*;
|
import com.example.listify.*;
|
||||||
import com.example.listify.adapter.ShoppingListsSwipeableAdapter;
|
import com.example.listify.adapter.ShoppingListsSwipeableAdapter;
|
||||||
import com.example.listify.data.List;
|
import com.example.listify.data.List;
|
||||||
|
import com.example.listify.data.SearchHistory;
|
||||||
|
import com.example.listify.model.Product;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
@ -23,6 +25,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import static com.example.listify.MainActivity.am;
|
import static com.example.listify.MainActivity.am;
|
||||||
|
import static com.example.listify.MainActivity.searchHistory;
|
||||||
|
|
||||||
public class HomeFragment extends Fragment implements CreateListDialogFragment.OnNewListListener, Requestor.Receiver {
|
public class HomeFragment extends Fragment implements CreateListDialogFragment.OnNewListListener, Requestor.Receiver {
|
||||||
ArrayList<List> shoppingLists = new ArrayList<>();
|
ArrayList<List> shoppingLists = new ArrayList<>();
|
||||||
@ -147,6 +150,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O
|
|||||||
shoppingLists.clear();
|
shoppingLists.clear();
|
||||||
|
|
||||||
Integer[] listIds = (Integer[]) delivered;
|
Integer[] listIds = (Integer[]) delivered;
|
||||||
|
|
||||||
// Create threads and add them to a list
|
// Create threads and add them to a list
|
||||||
if (listIds == null) {
|
if (listIds == null) {
|
||||||
return;
|
return;
|
||||||
@ -171,6 +175,30 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O
|
|||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request search history
|
||||||
|
final SearchHistory[] history = new SearchHistory[1]; // Needs to be an array because of anonymous class weirdness
|
||||||
|
SynchronousReceiver<SearchHistory> historyReceiver = new SynchronousReceiver<>();
|
||||||
|
Properties configs = new Properties();
|
||||||
|
try {
|
||||||
|
configs = AuthManager.loadProperties(getContext(), "android.resource://" + getActivity().getPackageName() + "/raw/auths.json");
|
||||||
|
} catch (IOException | JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
Requestor historyRequestor = new Requestor(am, configs.getProperty("apiKey"));
|
||||||
|
historyRequestor.getObject("0", SearchHistory.class, historyReceiver);
|
||||||
|
Thread historyThread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
history[0] = historyReceiver.await();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
historyThread.start();
|
||||||
|
|
||||||
// Wait for each thread to finish and add results to shoppingLists
|
// Wait for each thread to finish and add results to shoppingLists
|
||||||
for (int i = 0; i < threads.length; i++) {
|
for (int i = 0; i < threads.length; i++) {
|
||||||
try {
|
try {
|
||||||
@ -181,6 +209,15 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O
|
|||||||
shoppingLists.add(results[i]);
|
shoppingLists.add(results[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for search History response
|
||||||
|
try {
|
||||||
|
historyThread.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
searchHistory = history[0].getSearches();
|
||||||
|
|
||||||
// Set adapter and display this users lists
|
// Set adapter and display this users lists
|
||||||
shoppingListsSwipeableAdapter = new ShoppingListsSwipeableAdapter(getActivity(), shoppingLists);
|
shoppingListsSwipeableAdapter = new ShoppingListsSwipeableAdapter(getActivity(), shoppingLists);
|
||||||
|
|
||||||
|
|||||||
@ -30,13 +30,13 @@
|
|||||||
android:contentDescription="@string/backButton"
|
android:contentDescription="@string/backButton"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"/>
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
<SearchView
|
<androidx.appcompat.widget.SearchView
|
||||||
android:id="@+id/searchBar"
|
android:id="@+id/searchBar"
|
||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="50dp"
|
android:layout_height="50dp"
|
||||||
android:queryHint="Search Here"
|
android:queryHint="Search Here"
|
||||||
>
|
>
|
||||||
</SearchView>
|
</androidx.appcompat.widget.SearchView>
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
|||||||
8
Listify/app/src/main/res/layout/search_suggestion.xml
Normal file
8
Listify/app/src/main/res/layout/search_suggestion.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@android:id/text1"
|
||||||
|
style="?android:attr/dropDownItemStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||||
|
android:background="@color/colorAccent"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLargePopupMenu"/>
|
||||||
@ -1,6 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<!-- <item-->
|
||||||
|
<!-- android:id="@+id/action_search"-->
|
||||||
|
<!-- android:icon="@drawable/ic_baseline_search_28"-->
|
||||||
|
<!-- android:title="seeerch"-->
|
||||||
|
<!-- app:actionViewClass="androidx.appcompat.widget.SearchView"-->
|
||||||
|
<!-- app:showAsAction="always|collapseActionView"/>-->
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_more"
|
android:id="@+id/action_more"
|
||||||
android:icon="@drawable/ic_baseline_more_vert_24"
|
android:icon="@drawable/ic_baseline_more_vert_24"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user