Add search and watch history (#626)

Add search and watch history

* Make MainActicity a single task
* Remove some casting
* SearchFragment: start searching when created with query
* Handle settings change in onResume
* History: Log pop up and background playback
* History: Add swipe to remove functionallity
* Enable history by default
* Use stream item
* Store more information about the stream
* Integrate history database into AppDatabase
* Remove redundant casts
* Re-enable date converters
* History: Use Rx Java and run DB in background
 * Also make HistoryDAO extend BasicDAO
* History: RX-ify swipe to remove
* Sort history entries by creation date
* History: Set toolbar title
* Don't repeat history entries
  * Introduced setters so we can update entries in the database
  * If the latest entry has the same (main) values, just update it
This commit is contained in:
Cyril Müller 2017-08-12 06:50:25 +02:00 committed by Mauricio Colli
parent 09159ec245
commit c0515de6b7
37 changed files with 1470 additions and 33 deletions

View file

@ -188,7 +188,7 @@ private final String TAG = "ChannelFragment@" + Integer.toHexString(hashCode());
outState.putString(Constants.KEY_TITLE, channelName);
outState.putInt(Constants.KEY_SERVICE_ID, serviceId);
outState.putSerializable(INFO_LIST_KEY, ((ArrayList<InfoItem>) infoListAdapter.getItemsList()));
outState.putSerializable(INFO_LIST_KEY, infoListAdapter.getItemsList());
outState.putSerializable(CHANNEL_INFO_KEY, currentChannelInfo);
outState.putInt(PAGE_NUMBER_KEY, pageNumber);
}

View file

@ -156,6 +156,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
private LinearLayout relatedStreamRootLayout;
private LinearLayout relatedStreamsView;
private ImageButton relatedStreamExpandButton;
private OnVideoPlayListener onVideoPlayedListener;
/*////////////////////////////////////////////////////////////////////////*/
@ -230,6 +231,18 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
else prepareAndLoad(currentStreamInfo, false);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
onVideoPlayedListener = (OnVideoPlayListener) context;
}
@Override
public void onDetach() {
super.onDetach();
onVideoPlayedListener = null;
}
@Override
public void onResume() {
super.onResume();
@ -414,6 +427,8 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
Intent intent;
AudioStream audioStream = currentStreamInfo.audio_streams.get(Utils.getPreferredAudioFormat(activity, currentStreamInfo.audio_streams));
onVideoPlayedListener.onBackgroundPlayed(currentStreamInfo, audioStream);
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
activity.startService(NavigationHelper.getOpenBackgroundPlayerIntent(activity, currentStreamInfo, audioStream));
Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
@ -464,6 +479,7 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
return;
}
onVideoPlayedListener.onVideoPlayed(getSelectedVideoStream(), currentStreamInfo);
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
Intent mIntent = NavigationHelper.getOpenVideoPlayerIntent(activity, PopupVideoPlayer.class, currentStreamInfo, actionBarHandler.getSelectedVideoStream());
activity.startService(mIntent);
@ -968,9 +984,21 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
}
}
/**
* Get the currently selected video stream
* @return the selected video stream
*/
private VideoStream getSelectedVideoStream() {
return sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream());
}
public void playVideo(StreamInfo info) {
// ----------- THE MAGIC MOMENT ---------------
VideoStream selectedVideoStream = sortedStreamVideosList.get(actionBarHandler.getSelectedVideoStream());
VideoStream selectedVideoStream = getSelectedVideoStream();
if(onVideoPlayedListener != null) {
onVideoPlayedListener.onVideoPlayed(selectedVideoStream, info);
}
if (PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
@ -1242,4 +1270,20 @@ public class VideoDetailFragment extends BaseFragment implements StreamExtractor
return false;
}
}
public interface OnVideoPlayListener {
/**
* Called when a video is played
* @param videoStream the video stream that is played
* @param streamInfo the stream info
*/
void onVideoPlayed(VideoStream videoStream, StreamInfo streamInfo);
/**
* Called when the audio is played in the background
* @param streamInfo the stream info
* @param audioStream the audio stream that is played
*/
void onBackgroundPlayed(StreamInfo streamInfo, AudioStream audioStream);
}
}

View file

@ -3,6 +3,7 @@ package org.schabi.newpipe.fragments.search;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
@ -85,12 +86,16 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
private View searchClear;
private RecyclerView resultRecyclerView;
private OnSearchListener onSearchListener;
/*////////////////////////////////////////////////////////////////////////*/
public static SearchFragment getInstance(int serviceId, String query) {
SearchFragment searchFragment = new SearchFragment();
searchFragment.setQuery(serviceId, query);
if(!TextUtils.isEmpty(query)) {
searchFragment.wasLoading.set(true);
}
return searchFragment;
}
@ -120,13 +125,26 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
@Override
public void onViewCreated(View rootView, @Nullable Bundle savedInstanceState) {
final boolean wasLoadingPreserved = wasLoading.get();
super.onViewCreated(rootView, savedInstanceState);
wasLoading.set(wasLoadingPreserved);
if (DEBUG) Log.d(TAG, "onViewCreated() called with: rootView = [" + rootView + "], savedInstanceState = [" + savedInstanceState + "]");
if (savedInstanceState != null && savedInstanceState.getBoolean(ERROR_KEY, false)) {
search(searchQuery, 0, true);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
onSearchListener = (OnSearchListener) context;
}
@Override
public void onDetach() {
super.onDetach();
onSearchListener = null;
}
@Override
@ -179,10 +197,12 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
outState.putString(QUERY_KEY, query);
outState.putInt(Constants.KEY_SERVICE_ID, serviceId);
outState.putInt(PAGE_NUMBER_KEY, pageNumber);
outState.putSerializable(INFO_LIST_KEY, ((ArrayList<InfoItem>) infoListAdapter.getItemsList()));
outState.putSerializable(INFO_LIST_KEY, infoListAdapter.getItemsList());
outState.putBoolean(WAS_LOADING_KEY, curSearchWorker != null && curSearchWorker.isRunning());
if (errorPanel != null && errorPanel.getVisibility() == View.VISIBLE) outState.putBoolean(ERROR_KEY, true);
if (errorPanel != null && errorPanel.getVisibility() == View.VISIBLE) {
outState.putBoolean(ERROR_KEY, true);
}
if (filterItemCheckedId != -1) outState.putInt(FILTER_CHECKED_ID_KEY, filterItemCheckedId);
}
@ -537,7 +557,11 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "], pageNumber = [" + pageNumber + "], clearList = [" + clearList + "]");
isLoading.set(true);
hideSoftKeyboard(searchEditText);
if(pageNumber == 0) {
if(onSearchListener != null) {
onSearchListener.onSearch(serviceId, query);
}
}
searchQuery = query;
this.pageNumber = pageNumber;
@ -612,4 +636,7 @@ public class SearchFragment extends BaseFragment implements SuggestionWorker.OnS
startActivityForResult(new Intent(getActivity(), ReCaptchaActivity.class), ReCaptchaActivity.RECAPTCHA_REQUEST);
}
public interface OnSearchListener {
void onSearch(int serviceId, String query);
}
}