diff --git a/Listify/app/src/main/java/com/example/listify/MainActivity.java b/Listify/app/src/main/java/com/example/listify/MainActivity.java index c0adf36..404ca8b 100644 --- a/Listify/app/src/main/java/com/example/listify/MainActivity.java +++ b/Listify/app/src/main/java/com/example/listify/MainActivity.java @@ -36,6 +36,7 @@ import org.json.JSONException; import java.io.*; import java.text.SimpleDateFormat; import java.time.Instant; +import java.util.ArrayList; import java.util.Date; import java.util.Properties; @@ -44,6 +45,7 @@ import static com.example.listify.SplashActivity.showSplash; public class MainActivity extends AppCompatActivity implements CreateListDialogFragment.OnNewListListener { private AppBarConfiguration mAppBarConfiguration; public static AuthManager am = new AuthManager(); + public static ArrayList searchHistory; private File newImageFileLocation = null; private final int CAMERA_CAPTURE = 1; private final int IMAGE_SELECT = 2; diff --git a/Listify/app/src/main/java/com/example/listify/SearchResults.java b/Listify/app/src/main/java/com/example/listify/SearchResults.java index 379ac8d..b3c1d80 100644 --- a/Listify/app/src/main/java/com/example/listify/SearchResults.java +++ b/Listify/app/src/main/java/com/example/listify/SearchResults.java @@ -1,4 +1,5 @@ package com.example.listify; +import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; @@ -7,12 +8,14 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.SearchView; +//import android.widget.SearchView; +import androidx.appcompat.widget.SearchView; import android.widget.TextView; import com.example.listify.adapter.SearchResultsListAdapter; @@ -28,12 +31,16 @@ import java.util.List; import java.util.Properties; 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 { private ListView resultsListView; private MenuItem filterItem; private ProgressBar loadingSearch; private TextView tvNoResults; + private SearchView.SearchAutoComplete searchAutoComplete; + private ArrayList orderedHistory = new ArrayList<>(); + private ArrayAdapter searchHistoryAdapter; private SearchResultsListAdapter searchResultsListAdapter; private List resultsProductList = new ArrayList<>(); private List 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 // doing it - int searchCloseButtonId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null); - ImageView closeButton = (ImageView) searchView.findViewById(searchCloseButtonId); - closeButton.setOnClickListener(new View.OnClickListener() { - // Override default close behavior to only clear the search text and the query - @Override - public void onClick(View v) { - // 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); - EditText searchText = (EditText) searchView.findViewById(searchTextId); - searchText.setText(""); - searchView.setQuery("", false); - } - }); +// int searchCloseButtonId = searchView.getContext().getResources().getIdentifier("android:id/search_close_btn", null, null); +// ImageView closeButton = (ImageView) searchView.findViewById(searchCloseButtonId); +// closeButton.setOnClickListener(new View.OnClickListener() { +// // Override default close behavior to only clear the search text and the query +// @Override +// public void onClick(View v) { +// // 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); +// EditText searchText = (EditText) searchView.findViewById(searchTextId); +// searchText.setText(""); +// searchView.setQuery("", false); +// } +// }); resultsListView = (ListView) findViewById(R.id.search_results_list); 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() { @Override public boolean onQueryTextSubmit(String query) { @@ -135,6 +142,49 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag 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(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 @@ -188,7 +238,6 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag if (resultsProductList.isEmpty()) { filterItem.setEnabled(false); } - return true; } @@ -200,6 +249,25 @@ public class SearchResults extends AppCompatActivity implements FilterDialogFrag } private void doSearch(String query) { + // Add this search to the history + searchHistory.add(query); + orderedHistory.clear(); + orderedHistory.addAll(searchHistory); + ArrayList 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(getApplicationContext(), R.layout.search_suggestion, t); + searchAutoComplete.setAdapter(searchHistoryAdapter); + + Properties configs = new Properties(); try { configs = AuthManager.loadProperties(this, "android.resource://" + getPackageName() + "/raw/auths.json"); diff --git a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java index eb65496..b481677 100644 --- a/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java +++ b/Listify/app/src/main/java/com/example/listify/ui/home/HomeFragment.java @@ -14,6 +14,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.example.listify.*; import com.example.listify.adapter.ShoppingListsSwipeableAdapter; 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 org.json.JSONException; @@ -23,6 +25,7 @@ import java.util.ArrayList; import java.util.Properties; import static com.example.listify.MainActivity.am; +import static com.example.listify.MainActivity.searchHistory; public class HomeFragment extends Fragment implements CreateListDialogFragment.OnNewListListener, Requestor.Receiver { ArrayList shoppingLists = new ArrayList<>(); @@ -147,6 +150,7 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O shoppingLists.clear(); Integer[] listIds = (Integer[]) delivered; + // Create threads and add them to a list if (listIds == null) { return; @@ -171,6 +175,30 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O t.start(); } + // Request search history + final SearchHistory[] history = new SearchHistory[1]; // Needs to be an array because of anonymous class weirdness + SynchronousReceiver 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 for (int i = 0; i < threads.length; i++) { try { @@ -181,6 +209,15 @@ public class HomeFragment extends Fragment implements CreateListDialogFragment.O 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 shoppingListsSwipeableAdapter = new ShoppingListsSwipeableAdapter(getActivity(), shoppingLists); diff --git a/Listify/app/src/main/res/layout/activity_search_results.xml b/Listify/app/src/main/res/layout/activity_search_results.xml index 3850f4d..e0c94a2 100644 --- a/Listify/app/src/main/res/layout/activity_search_results.xml +++ b/Listify/app/src/main/res/layout/activity_search_results.xml @@ -30,13 +30,13 @@ android:contentDescription="@string/backButton" android:foreground="?android:attr/selectableItemBackgroundBorderless"/> - - + diff --git a/Listify/app/src/main/res/layout/search_suggestion.xml b/Listify/app/src/main/res/layout/search_suggestion.xml new file mode 100644 index 0000000..9d1935f --- /dev/null +++ b/Listify/app/src/main/res/layout/search_suggestion.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/Listify/app/src/main/res/menu/search.xml b/Listify/app/src/main/res/menu/search.xml index 85af65c..8aa3ab5 100644 --- a/Listify/app/src/main/res/menu/search.xml +++ b/Listify/app/src/main/res/menu/search.xml @@ -1,6 +1,12 @@ + + + + + +