package what.whatandroid.search; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.*; import api.search.torrents.TorrentSearch; import api.soup.MySoup; import what.whatandroid.R; import what.whatandroid.callbacks.OnLoggedInCallback; import what.whatandroid.callbacks.SetTitleCallback; /** * Fragment for searching for torrents */ public class TorrentSearchFragment extends Fragment implements View.OnClickListener, TextView.OnEditorActionListener, OnLoggedInCallback, LoaderManager.LoaderCallbacks<TorrentSearch>, AbsListView.OnScrollListener { /** * So we can set the action bar title */ private SetTitleCallback setTitle; /** * Search terms and tags sent to use by the intent */ private String searchTerms, searchTags; /** * The torrent search we're viewing */ private TorrentSearch torrentSearch; /** * The search input boxes */ private EditText editTerms, editTags; /** * The list of search results and the search result adapter */ private TorrentSearchAdapter resultsAdapter; /** * The loading status footer */ private View footer; private TextView noResults; /** * Create a torrent search fragment and have it start loading the search desired when the view * is created. If the terms are empty then no search will be launched * * @param terms terms to search for * @param tags tags to search for * @return a torrent search fragment that will load the desired search */ public static TorrentSearchFragment newInstance(String terms, String tags){ TorrentSearchFragment f = new TorrentSearchFragment(); Bundle args = new Bundle(); args.putString(SearchActivity.TERMS, terms); args.putString(SearchActivity.TAGS, tags); f.setArguments(args); return f; } public TorrentSearchFragment(){ //required empty ctor } @Override public void onAttach(Activity activity){ super.onAttach(activity); try { setTitle = (SetTitleCallback)activity; } catch (ClassCastException e){ throw new ClassCastException(activity.toString() + " must implement SetTitleCallback"); } } @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); if (savedInstanceState == null){ searchTerms = getArguments().getString(SearchActivity.TERMS, ""); searchTags = getArguments().getString(SearchActivity.TAGS, ""); } else { searchTerms = savedInstanceState.getString(SearchActivity.TERMS, ""); searchTags = savedInstanceState.getString(SearchActivity.TAGS, ""); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){ setTitle.setTitle("Torrent Search"); View view = inflater.inflate(R.layout.fragment_list_view, container, false); ListView resultsList = (ListView)view.findViewById(R.id.list); noResults = (TextView)view.findViewById(R.id.no_content_notice); noResults.setText("No Results"); View header = inflater.inflate(R.layout.header_search, null); editTerms = (EditText)header.findViewById(R.id.search_terms); editTags = (EditText)header.findViewById(R.id.search_tags); editTags.setOnEditorActionListener(this); Button search = (Button)header.findViewById(R.id.search_button); search.setOnClickListener(this); footer = inflater.inflate(R.layout.footer_loading_indicator, null); resultsList.addHeaderView(header); resultsList.addFooterView(footer); resultsList.setFooterDividersEnabled(false); footer.setVisibility(View.GONE); resultsAdapter = new TorrentSearchAdapter(getActivity()); resultsList.setAdapter(resultsAdapter); resultsList.setOnItemClickListener(resultsAdapter); resultsList.setOnScrollListener(this); if (searchTerms.isEmpty() && searchTags.isEmpty()){ editTerms.requestFocus(); } else { editTerms.setText(searchTerms); editTags.setText(searchTags); if (MySoup.isLoggedIn()){ footer.setVisibility(View.VISIBLE); startSearch(searchTerms, searchTags, 1); } } return view; } @Override public void onSaveInstanceState(Bundle outState){ super.onSaveInstanceState(outState); outState.putString(SearchActivity.TERMS, editTerms.getText().toString()); outState.putString(SearchActivity.TAGS, editTags.getText().toString()); } @Override public void onLoggedIn(){ //If we were sent a search intent and are added then start loading it if (!searchTerms.isEmpty() || !searchTags.isEmpty()){ footer.setVisibility(View.VISIBLE); startSearch(searchTerms, searchTags, 1); } } @Override public void onClick(View v){ searchTerms = editTerms.getText().toString(); searchTags = editTags.getText().toString(); if (!searchTerms.isEmpty() || !searchTags.isEmpty()){ InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editTerms.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY); resultsAdapter.clear(); resultsAdapter.notifyDataSetChanged(); footer.setVisibility(View.VISIBLE); startSearch(searchTerms, searchTags, 1); } else { Toast.makeText(getActivity(), "Enter search terms or tags", Toast.LENGTH_SHORT).show(); editTerms.requestFocus(); } } @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event){ if (event == null || event.getAction() == KeyEvent.ACTION_DOWN){ searchTerms = editTerms.getText().toString(); searchTags = editTags.getText().toString(); if (!searchTerms.isEmpty() || !searchTags.isEmpty()){ InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(editTerms.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY); resultsAdapter.clear(); resultsAdapter.notifyDataSetChanged(); footer.setVisibility(View.VISIBLE); startSearch(searchTerms, searchTags, 1); } else { Toast.makeText(getActivity(), "Enter search terms or tags", Toast.LENGTH_SHORT).show(); editTerms.requestFocus(); } } return true; } @Override public void onScrollStateChanged(AbsListView view, int scrollState){ } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount){ //Load more if we're within 10 items of the end and there's a next page to load if (torrentSearch != null && torrentSearch.hasNextPage() && firstVisibleItem + visibleItemCount + 10 >= totalItemCount){ startSearch(searchTerms, searchTags, torrentSearch.getPage() + 1); } } private void startSearch(String terms, String tags, int page){ noResults.setVisibility(View.GONE); Bundle args = new Bundle(); args.putString(SearchActivity.TERMS, terms); args.putString(SearchActivity.TAGS, tags); args.putInt(SearchActivity.PAGE, page); LoaderManager lm = getLoaderManager(); Loader l = lm.getLoader(page); if (l == null){ lm.initLoader(page, args, this); } //Check if the terms and tags are different from what the loader has and restart if they're different else { TorrentSearchAsyncLoader s = (TorrentSearchAsyncLoader)l; if (!s.getTerms().equalsIgnoreCase(searchTerms) || !s.getTags().equalsIgnoreCase(tags)){ lm.restartLoader(page, args, this); } else { lm.initLoader(page, args, this); } } } @Override public Loader<TorrentSearch> onCreateLoader(int id, Bundle args){ return new TorrentSearchAsyncLoader(getActivity(), args); } @Override public void onLoadFinished(Loader<TorrentSearch> loader, TorrentSearch data){ torrentSearch = data; //Update the views like in post execute if (torrentSearch != null){ if (isAdded()){ if (torrentSearch.getResponse().getResults().isEmpty()){ noResults.setVisibility(View.VISIBLE); } //If it's the first page then clear any previous search if (torrentSearch.getPage() == 1){ resultsAdapter.clear(); } resultsAdapter.addAll(torrentSearch.getResponse().getResults()); resultsAdapter.notifyDataSetChanged(); if (!torrentSearch.hasNextPage()){ footer.setVisibility(View.GONE); } } } else if (isAdded()){ Toast.makeText(getActivity(), "Could not load search results", Toast.LENGTH_LONG).show(); footer.setVisibility(View.GONE); } } @Override public void onLoaderReset(Loader<TorrentSearch> loader){ } }