From 2f2334eac4ce2f17346143836f8242ed9175bbde Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Tue, 2 Aug 2016 18:38:05 +0200 Subject: [PATCH] make search fagment handle video items --- .../schabi/newpipe/extractor/ServiceList.java | 2 +- .../SearchInfoItemFragment.java | 60 ++++-- .../newpipe/search_fragment/SearchWorker.java | 175 ++++++++++++++++++ .../StreamInfoListAdapter.java | 17 +- 4 files changed, 236 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/search_fragment/SearchWorker.java rename app/src/main/java/org/schabi/newpipe/{ => search_fragment}/StreamInfoListAdapter.java (91%) diff --git a/app/src/main/java/org/schabi/newpipe/extractor/ServiceList.java b/app/src/main/java/org/schabi/newpipe/extractor/ServiceList.java index 63ccc5cb2..9571819a9 100644 --- a/app/src/main/java/org/schabi/newpipe/extractor/ServiceList.java +++ b/app/src/main/java/org/schabi/newpipe/extractor/ServiceList.java @@ -40,7 +40,7 @@ public class ServiceList { public static StreamingService[] getServices() { return services; } - public static StreamingService getService(int serviceId) throws ExtractionException { + public static StreamingService getService(int serviceId)throws ExtractionException { for(StreamingService s : services) { if(s.getServiceId() == serviceId) { return s; diff --git a/app/src/main/java/org/schabi/newpipe/search_fragment/SearchInfoItemFragment.java b/app/src/main/java/org/schabi/newpipe/search_fragment/SearchInfoItemFragment.java index 582a295e7..aae87e1a4 100644 --- a/app/src/main/java/org/schabi/newpipe/search_fragment/SearchInfoItemFragment.java +++ b/app/src/main/java/org/schabi/newpipe/search_fragment/SearchInfoItemFragment.java @@ -2,14 +2,9 @@ package org.schabi.newpipe.search_fragment; import android.app.Activity; import android.content.Context; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.MatrixCursor; import android.os.Bundle; import android.os.Handler; -import android.preference.PreferenceManager; import android.support.v4.app.Fragment; -import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -21,19 +16,13 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; -import android.widget.TextView; import android.widget.Toast; -import org.schabi.newpipe.Downloader; import org.schabi.newpipe.ErrorActivity; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.ExtractionException; -import org.schabi.newpipe.extractor.SearchEngine; +import org.schabi.newpipe.extractor.SearchResult; import org.schabi.newpipe.extractor.ServiceList; -import java.io.IOException; -import java.util.List; - /** * Created by Christian Schabesberger on 02.08.16. */ @@ -99,6 +88,7 @@ public class SearchInfoItemFragment extends Fragment { private SearchView searchView = null; private SuggestionListAdapter suggestionListAdapter = null; + private StreamInfoListAdapter streamInfoListAdapter = null; // savedInstanceBundle arguments private static final String QUERY = "query"; @@ -144,6 +134,28 @@ public class SearchInfoItemFragment extends Fragment { "", R.string.general_error)); } } + + SearchWorker sw = SearchWorker.getInstance(); + sw.setSearchWorkerResultListner(new SearchWorker.SearchWorkerResultListner() { + @Override + public void onResult(SearchResult result) { + streamInfoListAdapter.addVideoList(result.resultList); + } + + @Override + public void onNothingFound(int stringResource) { + //setListShown(true); + Toast.makeText(getActivity(), getString(stringResource), + Toast.LENGTH_SHORT).show(); + } + + @Override + public void onError(String message) { + //setListShown(true); + Toast.makeText(getActivity(), message, + Toast.LENGTH_LONG).show(); + } + }); } @Override @@ -160,8 +172,12 @@ public class SearchInfoItemFragment extends Fragment { } else { recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); } - recyclerView.setAdapter(null); + + streamInfoListAdapter = new StreamInfoListAdapter(getActivity(), + getActivity().findViewById(android.R.id.content)); + recyclerView.setAdapter(streamInfoListAdapter); } + return view; } @@ -202,7 +218,13 @@ public class SearchInfoItemFragment extends Fragment { } private void search(String query) { + streamInfoListAdapter.clearVideoList(); + search(query, 0); + } + private void search(String query, int page) { + SearchWorker sw = SearchWorker.getInstance(); + sw.search(streamingServiceId, query, page, getActivity()); } private void searchSuggestions(String query) { @@ -216,8 +238,16 @@ public class SearchInfoItemFragment extends Fragment { h.post(new Runnable() { @Override public void run() { - Toast.makeText(getActivity(), getString(stringResource), - Toast.LENGTH_SHORT).show(); + + } + }); + } + + private void postNewNothingFoundToast(Handler h, final int stringResource) { + h.post(new Runnable() { + @Override + public void run() { + } }); } diff --git a/app/src/main/java/org/schabi/newpipe/search_fragment/SearchWorker.java b/app/src/main/java/org/schabi/newpipe/search_fragment/SearchWorker.java new file mode 100644 index 000000000..3e7464333 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/search_fragment/SearchWorker.java @@ -0,0 +1,175 @@ +package org.schabi.newpipe.search_fragment; + +import android.app.Activity; +import android.content.SharedPreferences; +import android.os.Handler; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.widget.Toast; + +import org.schabi.newpipe.Downloader; +import org.schabi.newpipe.ErrorActivity; +import org.schabi.newpipe.R; +import org.schabi.newpipe.extractor.ExtractionException; +import org.schabi.newpipe.extractor.SearchEngine; +import org.schabi.newpipe.extractor.SearchResult; +import org.schabi.newpipe.extractor.ServiceList; + +import java.io.IOException; + +/** + * Created by the-scrabi on 02.08.16. + */ + + +public class SearchWorker { + private static final String TAG = SearchWorker.class.toString(); + + public interface SearchWorkerResultListner { + void onResult(SearchResult result); + void onNothingFound(final int stringResource); + void onError(String message); + } + + private class ResultRunnable implements Runnable { + private final SearchResult result; + private int requestId = 0; + public ResultRunnable(SearchResult result, int requestId) { + this.result = result; + this.requestId = requestId; + } + @Override + public void run() { + if(this.requestId == SearchWorker.this.requestId) { + searchWorkerResultListner.onResult(result); + } + } + } + + private class SearchRunnable implements Runnable { + public static final String YOUTUBE = "Youtube"; + private final String query; + private final int page; + final Handler h = new Handler(); + private volatile boolean runs = true; + private Activity a = null; + private int serviceId = -1; + public SearchRunnable(int serviceId, String query, int page, Activity activity, int requestId) { + this.serviceId = serviceId; + this.query = query; + this.page = page; + this.a = activity; + } + void terminate() { + runs = false; + } + @Override + public void run() { + SearchResult result = null; + SearchEngine engine = null; + + try { + engine = ServiceList.getService(serviceId) + .getSearchEngineInstance(new Downloader()); + } catch(ExtractionException e) { + ErrorActivity.reportError(h, a, e, null, null, + ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, + Integer.toString(serviceId), query, R.string.general_error)); + return; + } + + try { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(a); + String searchLanguageKey = a.getString(R.string.search_language_key); + String searchLanguage = sp.getString(searchLanguageKey, + a.getString(R.string.default_language_value)); + result = SearchResult + .getSearchResult(engine, query, page, searchLanguage, new Downloader()); + + if(runs) { + h.post(new ResultRunnable(result, requestId)); + } + + // look for errors during extraction + // soft errors: + if(result != null && + !result.errors.isEmpty()) { + Log.e(TAG, "OCCURRED ERRORS DURING SEARCH EXTRACTION:"); + for(Throwable e : result.errors) { + e.printStackTrace(); + Log.e(TAG, "------"); + } + + View rootView = a.findViewById(R.id.videoitem_list); + ErrorActivity.reportError(h, a, result.errors, null, rootView, + ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, + /* todo: this shoudl not be assigned static */ YOUTUBE, query, R.string.light_parsing_error)); + + } + // hard errors: + } catch(IOException e) { + h.post(new Runnable() { + @Override + public void run() { + searchWorkerResultListner.onNothingFound(R.string.network_error); + } + }); + e.printStackTrace(); + } catch(final SearchEngine.NothingFoundException e) { + h.post(new Runnable() { + @Override + public void run() { + searchWorkerResultListner.onError(e.getMessage()); + } + }); + } catch(ExtractionException e) { + ErrorActivity.reportError(h, a, e, null, null, + ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, + /* todo: this shoudl not be assigned static */ + YOUTUBE, query, R.string.parsing_error)); + //postNewErrorToast(h, R.string.parsing_error); + e.printStackTrace(); + + } catch(Exception e) { + ErrorActivity.reportError(h, a, e, null, null, + ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, + /* todo: this shoudl not be assigned static */ YOUTUBE, query, R.string.general_error)); + + e.printStackTrace(); + } + } + } + + private static SearchWorker searchWorker = null; + private SearchWorkerResultListner searchWorkerResultListner = null; + private SearchRunnable runnable = null; + private int requestId = 0; //prevents running requests that have already ben expired + + public static SearchWorker getInstance() { + return searchWorker == null ? (searchWorker = new SearchWorker()) : searchWorker; + } + + public void setSearchWorkerResultListner(SearchWorkerResultListner listener) { + searchWorkerResultListner = listener; + } + + private SearchWorker() { + + } + + public void search(int serviceId, String query, int page, Activity a) { + if(runnable != null) { + terminate(); + } else { + runnable = new SearchRunnable(serviceId, query, page, a, requestId); + } + Thread thread = new Thread(runnable); + thread.start(); + } + + public void terminate() { + requestId++; + runnable.terminate(); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/StreamInfoListAdapter.java b/app/src/main/java/org/schabi/newpipe/search_fragment/StreamInfoListAdapter.java similarity index 91% rename from app/src/main/java/org/schabi/newpipe/StreamInfoListAdapter.java rename to app/src/main/java/org/schabi/newpipe/search_fragment/StreamInfoListAdapter.java index a7a466636..112e706d1 100644 --- a/app/src/main/java/org/schabi/newpipe/StreamInfoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/search_fragment/StreamInfoListAdapter.java @@ -1,4 +1,4 @@ -package org.schabi.newpipe; +package org.schabi.newpipe.search_fragment; import android.app.Activity; import android.content.Context; @@ -10,6 +10,10 @@ import android.view.ViewGroup; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; +import org.schabi.newpipe.ImageErrorLoadingListener; +import org.schabi.newpipe.R; +import org.schabi.newpipe.StreamInfoItemHolder; +import org.schabi.newpipe.StreamInfoItemViewCreator; import org.schabi.newpipe.extractor.AbstractVideoInfo; import org.schabi.newpipe.extractor.StreamPreviewInfo; @@ -28,12 +32,21 @@ public class StreamInfoListAdapter extends RecyclerView.Adapter videos) { + streamList.addAll(videos); + notifyDataSetChanged(); + } + + public void clearVideoList() { + streamList = new Vector<>(); + notifyDataSetChanged(); + } + @Override public int getItemCount() { return streamList.size();