From 2622a759068d28381024ecf803c161cd4858f323 Mon Sep 17 00:00:00 2001 From: tom79 Date: Sun, 31 Mar 2019 12:40:51 +0200 Subject: [PATCH] Change the way to retrieve results for searches --- .../activities/SearchResultTabActivity.java | 123 +----------------- .../asynctasks/RetrieveSearchAsyncTask.java | 73 ++++++----- .../fr/gouv/etalab/mastodon/client/API.java | 66 +++++++++- .../etalab/mastodon/client/APIResponse.java | 10 ++ .../gouv/etalab/mastodon/client/GNUAPI.java | 6 +- .../fragments/DisplaySearchTagsFragment.java | 36 +++-- .../interfaces/OnRetrieveSearchInterface.java | 5 +- 7 files changed, 140 insertions(+), 179 deletions(-) diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/activities/SearchResultTabActivity.java b/app/src/main/java/fr/gouv/etalab/mastodon/activities/SearchResultTabActivity.java index bb79ca017..bbb2b6492 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/activities/SearchResultTabActivity.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/activities/SearchResultTabActivity.java @@ -17,13 +17,11 @@ package fr.gouv.etalab.mastodon.activities; import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; -import android.os.AsyncTask; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; @@ -35,30 +33,13 @@ import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; -import android.widget.Toast; - -import java.util.ArrayList; -import java.util.List; - -import es.dmoral.toasty.Toasty; import fr.gouv.etalab.mastodon.R; import fr.gouv.etalab.mastodon.asynctasks.RetrieveAccountsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; -import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAsyncTask; -import fr.gouv.etalab.mastodon.client.APIResponse; -import fr.gouv.etalab.mastodon.client.Entities.Account; -import fr.gouv.etalab.mastodon.client.Entities.Error; -import fr.gouv.etalab.mastodon.client.Entities.Results; -import fr.gouv.etalab.mastodon.client.Entities.Status; -import fr.gouv.etalab.mastodon.drawers.SearchListAdapter; -import fr.gouv.etalab.mastodon.drawers.SearchTagsAdapter; import fr.gouv.etalab.mastodon.fragments.DisplayAccountsFragment; import fr.gouv.etalab.mastodon.fragments.DisplaySearchTagsFragment; import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment; -import fr.gouv.etalab.mastodon.fragments.TabLayoutTootsFragment; import fr.gouv.etalab.mastodon.helper.Helper; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface; -import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchStatusInterface; import static fr.gouv.etalab.mastodon.helper.Helper.THEME_LIGHT; @@ -68,7 +49,7 @@ import static fr.gouv.etalab.mastodon.helper.Helper.THEME_LIGHT; * Show search results within tabs */ -public class SearchResultTabActivity extends BaseActivity implements OnRetrieveSearchInterface, OnRetrieveSearchStatusInterface { +public class SearchResultTabActivity extends BaseActivity { private String search; @@ -105,16 +86,7 @@ public class SearchResultTabActivity extends BaseActivity implements OnRetrieveS tabLayout = findViewById(R.id.search_tabLayout); search_viewpager = findViewById(R.id.search_viewpager); - Bundle b = getIntent().getExtras(); - if(b != null){ - search = b.getString("search"); - if( search != null) - new RetrieveSearchAsyncTask(getApplicationContext(), search.trim(), SearchResultTabActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - else - Toasty.error(this,getString(R.string.toast_error_search),Toast.LENGTH_LONG).show(); - }else{ - Toasty.error(this,getString(R.string.toast_error_search),Toast.LENGTH_LONG).show(); - } + if( getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true); ActionBar actionBar = getSupportActionBar(); @@ -157,80 +129,6 @@ public class SearchResultTabActivity extends BaseActivity implements OnRetrieveS } - @Override - public void onRetrieveSearch(Results results, Error error) { - loader.setVisibility(View.GONE); - - if( error != null){ - Toasty.error(getApplicationContext(), error.getError(),Toast.LENGTH_LONG).show(); - return; - } - if( results == null || (results.getAccounts().size() == 0 && results.getStatuses().size() == 0 && results.getHashtags().size() == 0)){ - RelativeLayout no_result = findViewById(R.id.no_result); - no_result.setVisibility(View.VISIBLE); - return; - } - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.tags))); - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.accounts))); - tabLayout.addTab(tabLayout.newTab().setText(getString(R.string.toots))); - - PagerAdapter mPagerAdapter = new SearchResultTabActivity.ScreenSlidePagerAdapter(getSupportFragmentManager()); - - search_viewpager.setAdapter(mPagerAdapter); - - search_viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - - } - - @Override - public void onPageSelected(int position) { - TabLayout.Tab tab = tabLayout.getTabAt(position); - if( tab != null) - tab.select(); - } - - @Override - public void onPageScrollStateChanged(int state) { - - } - }); - - tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { - @Override - public void onTabSelected(TabLayout.Tab tab) { - search_viewpager.setCurrentItem(tab.getPosition()); - } - - @Override - public void onTabUnselected(TabLayout.Tab tab) { - - } - - @Override - public void onTabReselected(TabLayout.Tab tab) { - Fragment fragment = null; - if( search_viewpager.getAdapter() != null) - fragment = (Fragment) search_viewpager.getAdapter().instantiateItem(search_viewpager, tab.getPosition()); - if( fragment != null) { - if( fragment instanceof DisplayAccountsFragment) { - DisplayAccountsFragment displayAccountsFragment = ((DisplayAccountsFragment) fragment); - displayAccountsFragment.scrollToTop(); - }else if (fragment instanceof DisplayStatusFragment){ - DisplayStatusFragment displayStatusFragment = ((DisplayStatusFragment) fragment); - displayStatusFragment.scrollToTop(); - }else if (fragment instanceof DisplaySearchTagsFragment){ - DisplaySearchTagsFragment displaySearchTagsFragment = ((DisplaySearchTagsFragment) fragment); - displaySearchTagsFragment.scrollToTop(); - } - } - } - }); - - } - - /** * Pager adapter for the 4 fragments */ @@ -272,21 +170,4 @@ public class SearchResultTabActivity extends BaseActivity implements OnRetrieveS return 3; } } - - @Override - public void onRetrieveSearchStatus(APIResponse apiResponse, Error error) { - loader.setVisibility(View.GONE); - if( apiResponse.getError() != null){ - Toasty.error(getApplicationContext(), error.getError(),Toast.LENGTH_LONG).show(); - return; - } - lv_search.setVisibility(View.VISIBLE); - List tags = new ArrayList<>(); - List accounts = new ArrayList<>(); - List statuses = apiResponse.getStatuses(); - - SearchListAdapter searchListAdapter = new SearchListAdapter(SearchResultTabActivity.this, statuses, accounts, tags); - lv_search.setAdapter(searchListAdapter); - searchListAdapter.notifyDataSetChanged(); - } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveSearchAsyncTask.java b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveSearchAsyncTask.java index e5b8a69f4..18fc85b56 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveSearchAsyncTask.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/asynctasks/RetrieveSearchAsyncTask.java @@ -23,7 +23,7 @@ import java.util.List; import fr.gouv.etalab.mastodon.activities.MainActivity; import fr.gouv.etalab.mastodon.client.API; -import fr.gouv.etalab.mastodon.client.Entities.Error; +import fr.gouv.etalab.mastodon.client.APIResponse; import fr.gouv.etalab.mastodon.client.Entities.Results; import fr.gouv.etalab.mastodon.client.GNUAPI; import fr.gouv.etalab.mastodon.helper.Helper; @@ -40,11 +40,12 @@ import fr.gouv.etalab.mastodon.sqlite.TagsCacheDAO; public class RetrieveSearchAsyncTask extends AsyncTask { private String query; - private Results results; + private APIResponse apiResponse; private OnRetrieveSearchInterface listener; - private Error error; private WeakReference contextReference; private boolean tagsOnly = false; + private API.searchType type; + private String max_id; public RetrieveSearchAsyncTask(Context context, String query, OnRetrieveSearchInterface onRetrieveSearchInterface){ this.contextReference = new WeakReference<>(context); @@ -59,40 +60,52 @@ public class RetrieveSearchAsyncTask extends AsyncTask { this.tagsOnly = tagsOnly; } + public RetrieveSearchAsyncTask(Context context, String query, API.searchType searchType, String max_id, OnRetrieveSearchInterface onRetrieveSearchInterface){ + this.contextReference = new WeakReference<>(context); + this.query = query; + this.listener = onRetrieveSearchInterface; + this.type = searchType; + this.max_id = max_id; + } + @Override protected Void doInBackground(Void... params) { - if(MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { - API api = new API(this.contextReference.get()); - if (!tagsOnly) - results = api.search(query); - else { - //search tags only - results = api.search(query); - SQLiteDatabase db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); - List cachedTags = new TagsCacheDAO(contextReference.get(), db).getBy(query); - if (results != null && results.getHashtags() != null) { - //If cache contains matching tags - if (cachedTags != null) { - for (String apiTag : results.getHashtags()) { - //Cache doesn't contain the tags coming from the api (case insensitive) - if (!Helper.containsCaseInsensitive(apiTag, cachedTags)) { - cachedTags.add(apiTag); //It's added + if (this.type == null) { + if (MainActivity.social != UpdateAccountInfoAsyncTask.SOCIAL.FRIENDICA) { + API api = new API(this.contextReference.get()); + if (!tagsOnly) + apiResponse = api.search(query); + else { + //search tags only + apiResponse = api.search(query); + SQLiteDatabase db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); + List cachedTags = new TagsCacheDAO(contextReference.get(), db).getBy(query); + if (apiResponse != null && apiResponse.getResults() != null && apiResponse.getResults().getHashtags() != null) { + //If cache contains matching tags + if (cachedTags != null) { + for (String apiTag : apiResponse.getResults().getHashtags()) { + //Cache doesn't contain the tags coming from the api (case insensitive) + if (!Helper.containsCaseInsensitive(apiTag, cachedTags)) { + cachedTags.add(apiTag); //It's added + } } + apiResponse.getResults().setHashtags(cachedTags); + } + } else if (cachedTags != null) { + if (apiResponse != null && apiResponse.getResults() == null) { + apiResponse.setResults(new Results()); + apiResponse.getResults().setHashtags(cachedTags); } - results.setHashtags(cachedTags); } - } else if (cachedTags != null) { - if (results == null) - results = new Results(); - results.setHashtags(cachedTags); } + } else { + GNUAPI gnuapi = new GNUAPI(this.contextReference.get()); + apiResponse = gnuapi.search(query); } - error = api.getError(); - }else { - GNUAPI gnuapi = new GNUAPI(this.contextReference.get()); - results = gnuapi.search(query); - error = gnuapi.getError(); + }else{ + API api = new API(this.contextReference.get()); + apiResponse = api.search2(query, type, max_id); } return null; @@ -100,7 +113,7 @@ public class RetrieveSearchAsyncTask extends AsyncTask { @Override protected void onPostExecute(Void result) { - listener.onRetrieveSearch(results, error); + listener.onRetrieveSearch(apiResponse); } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java index 8e6970977..9e482c835 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/API.java @@ -106,6 +106,12 @@ public class API { private Error APIError; private List domains; + public enum searchType{ + TAGS, + STATUSES, + ACCOUNTS + } + public enum StatusAction{ FAVOURITE, UNFAVOURITE, @@ -2510,9 +2516,10 @@ public class API { * @param query String search * @return Results */ - public Results search(String query) { + public APIResponse search(String query) { HashMap params = new HashMap<>(); + apiResponse = new APIResponse(); if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) params.put("q", query); else @@ -2525,6 +2532,7 @@ public class API { HttpsConnection httpsConnection = new HttpsConnection(context); String response = httpsConnection.get(getAbsoluteUrl("/search"), 60, params, prefKeyOauthTokenT); results = parseResultsResponse(new JSONObject(response)); + apiResponse.setResults(results); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); @@ -2537,7 +2545,61 @@ public class API { } catch (JSONException e) { e.printStackTrace(); } - return results; + return apiResponse; + } + + + /** + * Retrieves Accounts and feeds when searching *synchronously* + * + * @param query String search + * @return Results + */ + public APIResponse search2(String query, searchType type, String max_id) { + apiResponse = new APIResponse(); + HashMap params = new HashMap<>(); + if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) + params.put("q", query); + else + try { + params.put("q", URLEncoder.encode(query, "UTF-8")); + } catch (UnsupportedEncodingException e) { + params.put("q", query); + } + if( max_id != null) + params.put("max_id", max_id); + switch (type){ + case TAGS: + params.put("type", "hashtags"); + break; + case ACCOUNTS: + params.put("type", "accounts"); + break; + case STATUSES: + params.put("type", "statuses"); + break; + } + params.put("limite", "40"); + try { + HttpsConnection httpsConnection = new HttpsConnection(context); + String response = httpsConnection.get(getAbsoluteUr2l("/search"), 60, params, prefKeyOauthTokenT); + results = parseResultsResponse(new JSONObject(response)); + apiResponse.setSince_id(httpsConnection.getSince_id()); + apiResponse.setMax_id(httpsConnection.getMax_id()); + apiResponse.setResults(results); + } catch (HttpsConnection.HttpsConnectionException e) { + setError(e.getStatusCode(), e); + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (JSONException e) { + e.printStackTrace(); + } + return apiResponse; } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java index d2bdae81a..ec220735f 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/APIResponse.java @@ -29,6 +29,7 @@ import fr.gouv.etalab.mastodon.client.Entities.Notification; import fr.gouv.etalab.mastodon.client.Entities.Peertube; import fr.gouv.etalab.mastodon.client.Entities.PeertubeNotification; import fr.gouv.etalab.mastodon.client.Entities.Relationship; +import fr.gouv.etalab.mastodon.client.Entities.Results; import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.client.Entities.StoredStatus; @@ -45,6 +46,7 @@ public class APIResponse { private List conversations = null; private List notifications = null; private List relationships = null; + private Results results = null; private List howToVideos = null; private List peertubes = null; private List peertubeNotifications = null; @@ -199,4 +201,12 @@ public class APIResponse { public void setPeertubeNotifications(List peertubeNotifications) { this.peertubeNotifications = peertubeNotifications; } + + public Results getResults() { + return results; + } + + public void setResults(Results results) { + this.results = results; + } } diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/client/GNUAPI.java b/app/src/main/java/fr/gouv/etalab/mastodon/client/GNUAPI.java index 9fab9d736..3ea5041cc 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/client/GNUAPI.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/client/GNUAPI.java @@ -1646,9 +1646,10 @@ public class GNUAPI { * @param query String search * @return Results */ - public Results search(String query) { + public APIResponse search(String query) { Results results = new Results(); HashMap params = new HashMap<>(); + apiResponse = new APIResponse(); if( MainActivity.social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) params.put("q", query); else @@ -1662,6 +1663,7 @@ public class GNUAPI { String response = httpsConnection.get(getAbsoluteUrl("/users/search.json"), 60, params, prefKeyOauthTokenT); List accounts = parseAccountResponse(new JSONArray(response)); results.setAccounts(accounts); + apiResponse.setResults(results); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); @@ -1674,7 +1676,7 @@ public class GNUAPI { } catch (JSONException e) { e.printStackTrace(); } - return results; + return apiResponse; } /** diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplaySearchTagsFragment.java b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplaySearchTagsFragment.java index 9117bfe02..d3e6796cf 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplaySearchTagsFragment.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/fragments/DisplaySearchTagsFragment.java @@ -24,25 +24,15 @@ import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.Toast; - import java.util.ArrayList; -import java.util.Date; import java.util.List; - import es.dmoral.toasty.Toasty; import fr.gouv.etalab.mastodon.R; -import fr.gouv.etalab.mastodon.activities.BaseMainActivity; -import fr.gouv.etalab.mastodon.activities.SearchResultActivity; -import fr.gouv.etalab.mastodon.asynctasks.RetrieveFeedsAsyncTask; import fr.gouv.etalab.mastodon.asynctasks.RetrieveSearchAsyncTask; -import fr.gouv.etalab.mastodon.client.Entities.Account; -import fr.gouv.etalab.mastodon.client.Entities.Error; -import fr.gouv.etalab.mastodon.client.Entities.Results; -import fr.gouv.etalab.mastodon.client.Entities.Status; -import fr.gouv.etalab.mastodon.drawers.SearchListAdapter; +import fr.gouv.etalab.mastodon.client.API; +import fr.gouv.etalab.mastodon.client.APIResponse; import fr.gouv.etalab.mastodon.drawers.SearchTagsAdapter; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveSearchInterface; @@ -65,7 +55,7 @@ public class DisplaySearchTagsFragment extends Fragment implements OnRetrieveSea private RelativeLayout loading_next_tags; private LinearLayoutManager mLayoutManager; private boolean flag_loading; - + private String max_id; @Override public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) { @@ -80,7 +70,7 @@ public class DisplaySearchTagsFragment extends Fragment implements OnRetrieveSea flag_loading = true; if (tags == null) tags = new ArrayList<>(); - + max_id = null; Bundle bundle = this.getArguments(); if (bundle != null) { search = bundle.getString("search"); @@ -105,7 +95,7 @@ public class DisplaySearchTagsFragment extends Fragment implements OnRetrieveSea if(firstVisibleItem + visibleItemCount == totalItemCount && context != null) { if(!flag_loading ) { flag_loading = true; - + new RetrieveSearchAsyncTask(context, search, API.searchType.TAGS, max_id, DisplaySearchTagsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); loading_next_tags.setVisibility(View.VISIBLE); } } else { @@ -114,7 +104,7 @@ public class DisplaySearchTagsFragment extends Fragment implements OnRetrieveSea } } }); - + new RetrieveSearchAsyncTask(context, search, API.searchType.TAGS, null,DisplaySearchTagsFragment.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); return rootView; } @@ -137,18 +127,22 @@ public class DisplaySearchTagsFragment extends Fragment implements OnRetrieveSea this.context = context; } + @Override - public void onRetrieveSearch(Results results, Error error) { + public void onRetrieveSearch(APIResponse apiResponse) { searchTagsAdapter = new SearchTagsAdapter(context, tags); - + this.max_id = apiResponse.getMax_id(); loader.setVisibility(View.GONE); - if (error!= null) { - Toasty.error(context, error.getError(), Toast.LENGTH_LONG).show(); + if (apiResponse.getError() != null) { + if( apiResponse.getError().getError() != null) + Toasty.error(context, apiResponse.getError().getError(), Toast.LENGTH_LONG).show(); + else + Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show(); return; } lv_search_tags.setVisibility(View.VISIBLE); - List newTags = results.getHashtags(); + List newTags = apiResponse.getResults().getHashtags(); tags.addAll(newTags); SearchTagsAdapter searchTagsAdapter = new SearchTagsAdapter(context, tags); lv_search_tags.setAdapter(searchTagsAdapter); diff --git a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchInterface.java b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchInterface.java index 372df0f75..1e31c7559 100644 --- a/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchInterface.java +++ b/app/src/main/java/fr/gouv/etalab/mastodon/interfaces/OnRetrieveSearchInterface.java @@ -14,13 +14,12 @@ * see . */ package fr.gouv.etalab.mastodon.interfaces; -import fr.gouv.etalab.mastodon.client.Entities.Error; -import fr.gouv.etalab.mastodon.client.Entities.Results; +import fr.gouv.etalab.mastodon.client.APIResponse; /** * Created by Thomas on 05/05/2017. * Interface for search */ public interface OnRetrieveSearchInterface { - void onRetrieveSearch(Results results, Error error); + void onRetrieveSearch(APIResponse apiResponse); }