2018-04-12 23:46:03 +02:00
|
|
|
package org.schabi.newpipe.local.playlist;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
import android.app.Activity;
|
|
|
|
import android.content.Context;
|
2020-02-08 06:57:36 +01:00
|
|
|
import android.os.AsyncTask;
|
2018-01-17 06:12:03 +01:00
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Parcelable;
|
|
|
|
import android.text.TextUtils;
|
2018-01-31 01:01:11 +01:00
|
|
|
import android.util.Log;
|
2018-01-17 06:12:03 +01:00
|
|
|
import android.view.LayoutInflater;
|
2020-03-05 14:49:04 +01:00
|
|
|
import android.view.Menu;
|
|
|
|
import android.view.MenuInflater;
|
|
|
|
import android.view.MenuItem;
|
2018-01-17 06:12:03 +01:00
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
2018-01-28 07:14:38 +01:00
|
|
|
import android.widget.EditText;
|
2018-01-17 06:12:03 +01:00
|
|
|
import android.widget.TextView;
|
2018-01-28 07:14:38 +01:00
|
|
|
import android.widget.Toast;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
2020-01-07 22:48:35 +01:00
|
|
|
import androidx.annotation.NonNull;
|
|
|
|
import androidx.annotation.Nullable;
|
|
|
|
import androidx.appcompat.app.AlertDialog;
|
|
|
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
import org.reactivestreams.Subscriber;
|
|
|
|
import org.reactivestreams.Subscription;
|
|
|
|
import org.schabi.newpipe.NewPipeDatabase;
|
|
|
|
import org.schabi.newpipe.R;
|
2018-01-28 07:14:38 +01:00
|
|
|
import org.schabi.newpipe.database.LocalItem;
|
2020-02-08 06:57:36 +01:00
|
|
|
import org.schabi.newpipe.database.history.model.StreamHistoryEntry;
|
2018-01-28 07:14:38 +01:00
|
|
|
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
2018-01-17 06:12:03 +01:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
2019-07-22 11:58:01 +02:00
|
|
|
import org.schabi.newpipe.extractor.stream.StreamType;
|
2018-01-17 06:12:03 +01:00
|
|
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
2019-07-25 11:47:38 +02:00
|
|
|
import org.schabi.newpipe.local.BaseLocalListFragment;
|
2020-02-08 06:57:36 +01:00
|
|
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
2018-04-21 23:10:01 +02:00
|
|
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
|
|
|
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
2018-01-17 06:12:03 +01:00
|
|
|
import org.schabi.newpipe.report.UserAction;
|
2018-01-28 07:14:38 +01:00
|
|
|
import org.schabi.newpipe.util.Localization;
|
2018-01-17 06:12:03 +01:00
|
|
|
import org.schabi.newpipe.util.NavigationHelper;
|
2018-01-31 01:21:50 +01:00
|
|
|
import org.schabi.newpipe.util.OnClickGesture;
|
2019-07-25 00:44:12 +02:00
|
|
|
import org.schabi.newpipe.util.StreamDialogEntry;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
2018-02-03 18:36:40 +01:00
|
|
|
import java.util.Collections;
|
2020-02-08 06:57:36 +01:00
|
|
|
import java.util.Iterator;
|
2018-01-17 06:12:03 +01:00
|
|
|
import java.util.List;
|
2018-01-29 08:01:06 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2018-01-31 20:51:47 +01:00
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
import icepick.State;
|
2020-02-08 06:57:36 +01:00
|
|
|
import io.reactivex.Flowable;
|
2018-01-17 06:12:03 +01:00
|
|
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
2018-02-11 02:20:56 +01:00
|
|
|
import io.reactivex.disposables.CompositeDisposable;
|
2018-01-29 08:01:06 +01:00
|
|
|
import io.reactivex.disposables.Disposable;
|
2018-02-11 02:20:56 +01:00
|
|
|
import io.reactivex.disposables.Disposables;
|
2018-01-29 08:01:06 +01:00
|
|
|
import io.reactivex.subjects.PublishSubject;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistStreamEntry>, Void> {
|
2018-01-31 04:39:41 +01:00
|
|
|
// Save the list 10 seconds after the last change occurred
|
|
|
|
private static final long SAVE_DEBOUNCE_MILLIS = 10000;
|
2018-01-31 20:51:47 +01:00
|
|
|
private static final int MINIMUM_INITIAL_DRAG_VELOCITY = 12;
|
2020-04-02 13:51:10 +02:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
@State
|
|
|
|
protected Long playlistId;
|
|
|
|
@State
|
|
|
|
protected String name;
|
|
|
|
@State
|
2020-04-02 13:51:10 +02:00
|
|
|
Parcelable itemsListState;
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
private View headerRootLayout;
|
|
|
|
private TextView headerTitleView;
|
|
|
|
private TextView headerStreamCount;
|
2018-01-31 01:01:11 +01:00
|
|
|
private View playlistControl;
|
2018-01-17 06:12:03 +01:00
|
|
|
private View headerPlayAllButton;
|
|
|
|
private View headerPopupButton;
|
|
|
|
private View headerBackgroundButton;
|
2020-02-08 06:57:36 +01:00
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
private ItemTouchHelper itemTouchHelper;
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
private LocalPlaylistManager playlistManager;
|
2018-01-31 01:01:11 +01:00
|
|
|
private Subscription databaseSubscription;
|
2018-01-17 06:12:03 +01:00
|
|
|
|
2018-01-29 08:01:06 +01:00
|
|
|
private PublishSubject<Long> debouncedSaveSignal;
|
2018-02-11 02:20:56 +01:00
|
|
|
private CompositeDisposable disposables;
|
2018-01-29 08:01:06 +01:00
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
/* Has the playlist been fully loaded from db */
|
|
|
|
private AtomicBoolean isLoadingComplete;
|
|
|
|
/* Has the playlist been modified (e.g. items reordered or deleted) */
|
|
|
|
private AtomicBoolean isModified;
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
public static LocalPlaylistFragment getInstance(final long playlistId, final String name) {
|
2018-01-17 06:12:03 +01:00
|
|
|
LocalPlaylistFragment instance = new LocalPlaylistFragment();
|
|
|
|
instance.setInitialData(playlistId, name);
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2018-01-31 01:01:11 +01:00
|
|
|
// Fragment LifeCycle - Creation
|
2018-01-17 06:12:03 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onCreate(final Bundle savedInstanceState) {
|
2018-01-31 01:01:11 +01:00
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
playlistManager = new LocalPlaylistManager(NewPipeDatabase.getInstance(getContext()));
|
|
|
|
debouncedSaveSignal = PublishSubject.create();
|
2018-01-31 20:51:47 +01:00
|
|
|
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables = new CompositeDisposable();
|
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
isLoadingComplete = new AtomicBoolean();
|
|
|
|
isModified = new AtomicBoolean();
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public View onCreateView(@NonNull final LayoutInflater inflater,
|
|
|
|
@Nullable final ViewGroup container,
|
|
|
|
@Nullable final Bundle savedInstanceState) {
|
2018-01-17 06:12:03 +01:00
|
|
|
return inflater.inflate(R.layout.fragment_playlist, container, false);
|
|
|
|
}
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Fragment Lifecycle - Views
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
@Override
|
2018-01-31 01:01:11 +01:00
|
|
|
public void setTitle(final String title) {
|
|
|
|
super.setTitle(title);
|
2018-01-17 06:12:03 +01:00
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
if (headerTitleView != null) {
|
|
|
|
headerTitleView.setText(title);
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
2018-01-17 06:12:03 +01:00
|
|
|
super.initViews(rootView, savedInstanceState);
|
2018-01-31 01:01:11 +01:00
|
|
|
setTitle(name);
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected View getListHeader() {
|
2020-03-31 19:20:15 +02:00
|
|
|
headerRootLayout = activity.getLayoutInflater()
|
|
|
|
.inflate(R.layout.local_playlist_header, itemsList, false);
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
|
|
|
|
headerTitleView.setSelected(true);
|
|
|
|
|
|
|
|
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2020-02-08 06:57:36 +01:00
|
|
|
playlistControl = headerRootLayout.findViewById(R.id.local_playlist_control);
|
2018-01-17 06:12:03 +01:00
|
|
|
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
|
|
|
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
|
|
|
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
|
|
|
|
|
|
|
return headerRootLayout;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void initListeners() {
|
|
|
|
super.initListeners();
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
headerTitleView.setOnClickListener(view -> createRenameDialog());
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
|
|
|
itemTouchHelper.attachToRecyclerView(itemsList);
|
|
|
|
|
2018-01-31 01:21:50 +01:00
|
|
|
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
|
2018-01-17 06:12:03 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void selected(final LocalItem selectedItem) {
|
2018-01-28 07:14:38 +01:00
|
|
|
if (selectedItem instanceof PlaylistStreamEntry) {
|
|
|
|
final PlaylistStreamEntry item = (PlaylistStreamEntry) selectedItem;
|
|
|
|
NavigationHelper.openVideoDetailFragment(getFragmentManager(),
|
2020-03-31 19:20:15 +02:00
|
|
|
item.getStreamEntity().getServiceId(), item.getStreamEntity().getUrl(),
|
|
|
|
item.getStreamEntity().getTitle());
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void held(final LocalItem selectedItem) {
|
2018-01-28 07:14:38 +01:00
|
|
|
if (selectedItem instanceof PlaylistStreamEntry) {
|
2018-04-12 23:46:03 +02:00
|
|
|
showStreamItemDialog((PlaylistStreamEntry) selectedItem);
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void drag(final LocalItem selectedItem,
|
|
|
|
final RecyclerView.ViewHolder viewHolder) {
|
|
|
|
if (itemTouchHelper != null) {
|
|
|
|
itemTouchHelper.startDrag(viewHolder);
|
|
|
|
}
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
|
|
|
});
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2018-01-31 01:01:11 +01:00
|
|
|
// Fragment Lifecycle - Loading
|
2018-01-17 06:12:03 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void showLoading() {
|
|
|
|
super.showLoading();
|
2020-03-31 19:20:15 +02:00
|
|
|
if (headerRootLayout != null) {
|
|
|
|
animateView(headerRootLayout, false, 200);
|
|
|
|
}
|
|
|
|
if (playlistControl != null) {
|
|
|
|
animateView(playlistControl, false, 200);
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void hideLoading() {
|
|
|
|
super.hideLoading();
|
2020-03-31 19:20:15 +02:00
|
|
|
if (headerRootLayout != null) {
|
|
|
|
animateView(headerRootLayout, true, 200);
|
|
|
|
}
|
|
|
|
if (playlistControl != null) {
|
|
|
|
animateView(playlistControl, true, 200);
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void startLoading(final boolean forceLoad) {
|
2018-01-17 06:12:03 +01:00
|
|
|
super.startLoading(forceLoad);
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (disposables != null) {
|
|
|
|
disposables.clear();
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables.add(getDebouncedSaver());
|
2018-01-17 06:12:03 +01:00
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
isLoadingComplete.set(false);
|
|
|
|
isModified.set(false);
|
|
|
|
|
2018-01-26 07:24:59 +01:00
|
|
|
playlistManager.getPlaylistStreams(playlistId)
|
2018-01-31 20:51:47 +01:00
|
|
|
.onBackpressureLatest()
|
2018-01-17 06:12:03 +01:00
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
|
|
|
.subscribe(getPlaylistObserver());
|
|
|
|
}
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Fragment Lifecycle - Destruction
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPause() {
|
|
|
|
super.onPause();
|
|
|
|
itemsListState = itemsList.getLayoutManager().onSaveInstanceState();
|
2018-01-31 20:51:47 +01:00
|
|
|
|
|
|
|
// Save on exit
|
|
|
|
saveImmediate();
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
2020-03-05 14:49:04 +01:00
|
|
|
@Override
|
|
|
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
|
|
if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu +
|
|
|
|
"], inflater = [" + inflater + "]");
|
|
|
|
super.onCreateOptionsMenu(menu, inflater);
|
|
|
|
inflater.inflate(R.menu.menu_local_playlist, menu);
|
|
|
|
}
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
@Override
|
|
|
|
public void onDestroyView() {
|
|
|
|
super.onDestroyView();
|
2018-01-31 20:51:47 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (itemListAdapter != null) {
|
|
|
|
itemListAdapter.unsetSelectedListener();
|
|
|
|
}
|
|
|
|
if (headerBackgroundButton != null) {
|
|
|
|
headerBackgroundButton.setOnClickListener(null);
|
|
|
|
}
|
|
|
|
if (headerPlayAllButton != null) {
|
|
|
|
headerPlayAllButton.setOnClickListener(null);
|
|
|
|
}
|
|
|
|
if (headerPopupButton != null) {
|
|
|
|
headerPopupButton.setOnClickListener(null);
|
|
|
|
}
|
2018-02-07 23:20:16 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (databaseSubscription != null) {
|
|
|
|
databaseSubscription.cancel();
|
|
|
|
}
|
|
|
|
if (disposables != null) {
|
|
|
|
disposables.clear();
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
|
|
|
databaseSubscription = null;
|
|
|
|
itemTouchHelper = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
super.onDestroy();
|
2020-03-31 19:20:15 +02:00
|
|
|
if (debouncedSaveSignal != null) {
|
|
|
|
debouncedSaveSignal.onComplete();
|
|
|
|
}
|
|
|
|
if (disposables != null) {
|
|
|
|
disposables.dispose();
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
|
|
|
debouncedSaveSignal = null;
|
|
|
|
playlistManager = null;
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables = null;
|
2018-01-31 20:51:47 +01:00
|
|
|
|
|
|
|
isLoadingComplete = null;
|
|
|
|
isModified = null;
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Playlist Stream Loader
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
private Subscriber<List<PlaylistStreamEntry>> getPlaylistObserver() {
|
|
|
|
return new Subscriber<List<PlaylistStreamEntry>>() {
|
2018-01-17 06:12:03 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onSubscribe(final Subscription s) {
|
2018-01-17 06:12:03 +01:00
|
|
|
showLoading();
|
2018-01-31 20:51:47 +01:00
|
|
|
isLoadingComplete.set(false);
|
2018-01-17 06:12:03 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (databaseSubscription != null) {
|
|
|
|
databaseSubscription.cancel();
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
databaseSubscription = s;
|
|
|
|
databaseSubscription.request(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onNext(final List<PlaylistStreamEntry> streams) {
|
2018-01-31 20:51:47 +01:00
|
|
|
// Skip handling the result after it has been modified
|
|
|
|
if (isModified == null || !isModified.get()) {
|
|
|
|
handleResult(streams);
|
|
|
|
isLoadingComplete.set(true);
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
if (databaseSubscription != null) {
|
|
|
|
databaseSubscription.request(1);
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onError(final Throwable exception) {
|
2018-01-17 06:12:03 +01:00
|
|
|
LocalPlaylistFragment.this.onError(exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onComplete() { }
|
2018-01-17 06:12:03 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-03-05 14:49:04 +01:00
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.menu_item_removeWatched:
|
|
|
|
//Solution, Scorched Earth, Copy non duplicates, clear playlist, then copy back over
|
|
|
|
//Other options didn't work as intended, or crashed. Like deleteItem(playlist_item) crashes when called in this function.
|
|
|
|
new RemoveWatchedStreams().execute();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void handleResult(@NonNull final List<PlaylistStreamEntry> result) {
|
2018-01-17 06:12:03 +01:00
|
|
|
super.handleResult(result);
|
2020-03-31 19:20:15 +02:00
|
|
|
if (itemListAdapter == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-03 18:36:40 +01:00
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
itemListAdapter.clearStreamItemList();
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
if (result.isEmpty()) {
|
|
|
|
showEmptyState();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-30 03:06:48 +01:00
|
|
|
itemListAdapter.addItems(result);
|
2018-01-17 06:12:03 +01:00
|
|
|
if (itemsListState != null) {
|
|
|
|
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
|
|
|
|
itemsListState = null;
|
|
|
|
}
|
2018-01-28 07:14:38 +01:00
|
|
|
setVideoCount(itemListAdapter.getItemsList().size());
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
headerPlayAllButton.setOnClickListener(view ->
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
2018-01-17 06:12:03 +01:00
|
|
|
headerPopupButton.setOnClickListener(view ->
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
2018-01-17 06:12:03 +01:00
|
|
|
headerBackgroundButton.setOnClickListener(view ->
|
2019-04-13 09:31:32 +02:00
|
|
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2019-09-16 20:22:55 +02:00
|
|
|
headerPopupButton.setOnLongClickListener(view -> {
|
|
|
|
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
headerBackgroundButton.setOnLongClickListener(view -> {
|
|
|
|
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
hideLoading();
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Fragment Error Handling
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
@Override
|
|
|
|
protected void resetFragment() {
|
|
|
|
super.resetFragment();
|
2020-03-31 19:20:15 +02:00
|
|
|
if (databaseSubscription != null) {
|
|
|
|
databaseSubscription.cancel();
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
2018-01-17 06:12:03 +01:00
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
protected boolean onError(final Throwable exception) {
|
|
|
|
if (super.onError(exception)) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
|
|
|
|
onUnrecoverableError(exception, UserAction.SOMETHING_ELSE,
|
2018-01-26 07:24:59 +01:00
|
|
|
"none", "Local Playlist", R.string.general_error);
|
2018-01-17 06:12:03 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
2018-01-31 01:01:11 +01:00
|
|
|
// Playlist Metadata/Streams Manipulation
|
2018-01-17 06:12:03 +01:00
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
private void createRenameDialog() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (playlistId == null || name == null || getContext() == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-28 07:14:38 +01:00
|
|
|
|
|
|
|
final View dialogView = View.inflate(getContext(), R.layout.dialog_playlist_name, null);
|
|
|
|
EditText nameEdit = dialogView.findViewById(R.id.playlist_name);
|
|
|
|
nameEdit.setText(name);
|
|
|
|
nameEdit.setSelection(nameEdit.getText().length());
|
|
|
|
|
|
|
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext())
|
|
|
|
.setTitle(R.string.rename_playlist)
|
|
|
|
.setView(dialogView)
|
|
|
|
.setCancelable(true)
|
|
|
|
.setNegativeButton(R.string.cancel, null)
|
2018-02-11 02:20:56 +01:00
|
|
|
.setPositiveButton(R.string.rename, (dialogInterface, i) -> {
|
|
|
|
changePlaylistName(nameEdit.getText().toString());
|
|
|
|
});
|
2018-01-31 01:01:11 +01:00
|
|
|
|
|
|
|
dialogBuilder.show();
|
|
|
|
}
|
2018-01-28 07:14:38 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
private void changePlaylistName(final String title) {
|
|
|
|
if (playlistManager == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
this.name = title;
|
|
|
|
setTitle(title);
|
2018-01-28 07:14:38 +01:00
|
|
|
|
2020-02-01 16:36:45 +01:00
|
|
|
if (DEBUG) {
|
2020-03-31 19:20:15 +02:00
|
|
|
Log.d(TAG, "Updating playlist id=[" + playlistId + "] "
|
|
|
|
+ "with new title=[" + title + "] items");
|
2020-02-01 16:36:45 +01:00
|
|
|
}
|
2018-01-28 07:14:38 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
final Disposable disposable = playlistManager.renamePlaylist(playlistId, title)
|
2018-01-31 01:01:11 +01:00
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2020-03-31 19:20:15 +02:00
|
|
|
.subscribe(longs -> { /*Do nothing on success*/ }, this::onError);
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables.add(disposable);
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void changeThumbnailUrl(final String thumbnailUrl) {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (playlistManager == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
final Toast successToast = Toast.makeText(getActivity(),
|
2018-01-29 08:01:06 +01:00
|
|
|
R.string.playlist_thumbnail_change_success,
|
2018-01-28 07:14:38 +01:00
|
|
|
Toast.LENGTH_SHORT);
|
|
|
|
|
2020-02-01 16:36:45 +01:00
|
|
|
if (DEBUG) {
|
2020-03-31 19:20:15 +02:00
|
|
|
Log.d(TAG, "Updating playlist id=[" + playlistId + "] "
|
|
|
|
+ "with new thumbnail url=[" + thumbnailUrl + "]");
|
2020-02-01 16:36:45 +01:00
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2018-02-11 02:20:56 +01:00
|
|
|
final Disposable disposable = playlistManager
|
|
|
|
.changePlaylistThumbnail(playlistId, thumbnailUrl)
|
2018-01-28 07:14:38 +01:00
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2018-01-31 01:01:11 +01:00
|
|
|
.subscribe(ignore -> successToast.show(), this::onError);
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables.add(disposable);
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
2019-12-02 22:20:43 +01:00
|
|
|
private void updateThumbnailUrl() {
|
|
|
|
String newThumbnailUrl;
|
|
|
|
|
2020-01-07 22:48:35 +01:00
|
|
|
if (!itemListAdapter.getItemsList().isEmpty()) {
|
2020-03-31 19:20:15 +02:00
|
|
|
newThumbnailUrl = ((PlaylistStreamEntry) itemListAdapter.getItemsList().get(0))
|
|
|
|
.getStreamEntity().getThumbnailUrl();
|
2020-01-07 22:48:35 +01:00
|
|
|
} else {
|
|
|
|
newThumbnailUrl = "drawable://" + R.drawable.dummy_thumbnail_playlist;
|
2019-12-02 22:20:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
changeThumbnailUrl(newThumbnailUrl);
|
|
|
|
}
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
private void deleteItem(final PlaylistStreamEntry item) {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (itemListAdapter == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-03 18:36:40 +01:00
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
itemListAdapter.removeItem(item);
|
2020-03-31 19:20:15 +02:00
|
|
|
if (playlistManager.getPlaylistThumbnail(playlistId)
|
|
|
|
.equals(item.getStreamEntity().getThumbnailUrl())) {
|
2019-12-02 22:20:43 +01:00
|
|
|
updateThumbnailUrl();
|
2020-03-31 19:20:15 +02:00
|
|
|
}
|
2019-12-02 22:20:43 +01:00
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
setVideoCount(itemListAdapter.getItemsList().size());
|
2018-01-31 20:51:47 +01:00
|
|
|
saveChanges();
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
private void saveChanges() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (isModified == null || debouncedSaveSignal == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
isModified.set(true);
|
2018-01-29 08:01:06 +01:00
|
|
|
debouncedSaveSignal.onNext(System.currentTimeMillis());
|
|
|
|
}
|
|
|
|
|
|
|
|
private Disposable getDebouncedSaver() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (debouncedSaveSignal == null) {
|
|
|
|
return Disposables.empty();
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
|
2018-01-29 08:01:06 +01:00
|
|
|
return debouncedSaveSignal
|
|
|
|
.debounce(SAVE_DEBOUNCE_MILLIS, TimeUnit.MILLISECONDS)
|
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2018-01-31 20:51:47 +01:00
|
|
|
.subscribe(ignored -> saveImmediate(), this::onError);
|
2018-01-29 08:01:06 +01:00
|
|
|
}
|
|
|
|
|
2018-01-31 04:39:41 +01:00
|
|
|
private void saveImmediate() {
|
2020-03-31 19:20:15 +02:00
|
|
|
if (playlistManager == null || itemListAdapter == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-02-11 02:20:56 +01:00
|
|
|
|
2018-01-31 20:51:47 +01:00
|
|
|
// List must be loaded and modified in order to save
|
2020-03-31 19:20:15 +02:00
|
|
|
if (isLoadingComplete == null || isModified == null
|
|
|
|
|| !isLoadingComplete.get() || !isModified.get()) {
|
|
|
|
Log.w(TAG, "Attempting to save playlist when local playlist "
|
|
|
|
+ "is not loaded or not modified: playlist id=[" + playlistId + "]");
|
2018-01-31 20:51:47 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-28 07:14:38 +01:00
|
|
|
final List<LocalItem> items = itemListAdapter.getItemsList();
|
|
|
|
List<Long> streamIds = new ArrayList<>(items.size());
|
|
|
|
for (final LocalItem item : items) {
|
|
|
|
if (item instanceof PlaylistStreamEntry) {
|
2019-04-28 22:43:52 +02:00
|
|
|
streamIds.add(((PlaylistStreamEntry) item).getStreamId());
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-01 16:36:45 +01:00
|
|
|
if (DEBUG) {
|
2020-03-31 19:20:15 +02:00
|
|
|
Log.d(TAG, "Updating playlist id=[" + playlistId + "] "
|
|
|
|
+ "with [" + streamIds.size() + "] items");
|
2020-02-01 16:36:45 +01:00
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2018-02-11 02:20:56 +01:00
|
|
|
final Disposable disposable = playlistManager.updateJoin(playlistId, streamIds)
|
2018-01-28 07:14:38 +01:00
|
|
|
.observeOn(AndroidSchedulers.mainThread())
|
2018-01-31 20:51:47 +01:00
|
|
|
.subscribe(
|
2020-03-31 19:20:15 +02:00
|
|
|
() -> {
|
|
|
|
if (isModified != null) {
|
|
|
|
isModified.set(false);
|
|
|
|
}
|
|
|
|
},
|
2018-01-31 20:51:47 +01:00
|
|
|
this::onError
|
|
|
|
);
|
2018-02-11 02:20:56 +01:00
|
|
|
disposables.add(disposable);
|
2018-01-31 20:51:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
2018-08-31 15:34:35 +02:00
|
|
|
int directions = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
|
|
|
if (isGridLayout()) {
|
|
|
|
directions |= ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
|
|
|
}
|
|
|
|
return new ItemTouchHelper.SimpleCallback(directions,
|
2018-01-31 20:51:47 +01:00
|
|
|
ItemTouchHelper.ACTION_STATE_IDLE) {
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public int interpolateOutOfBoundsScroll(final RecyclerView recyclerView,
|
|
|
|
final int viewSize,
|
|
|
|
final int viewSizeOutOfBounds,
|
|
|
|
final int totalSize,
|
|
|
|
final long msSinceStartScroll) {
|
|
|
|
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView,
|
|
|
|
viewSize, viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
2018-01-31 20:51:47 +01:00
|
|
|
final int minimumAbsVelocity = Math.max(MINIMUM_INITIAL_DRAG_VELOCITY,
|
|
|
|
Math.abs(standardSpeed));
|
|
|
|
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public boolean onMove(final RecyclerView recyclerView,
|
|
|
|
final RecyclerView.ViewHolder source,
|
|
|
|
final RecyclerView.ViewHolder target) {
|
|
|
|
if (source.getItemViewType() != target.getItemViewType()
|
|
|
|
|| itemListAdapter == null) {
|
2018-01-31 20:51:47 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
final int sourceIndex = source.getAdapterPosition();
|
|
|
|
final int targetIndex = target.getAdapterPosition();
|
|
|
|
final boolean isSwapped = itemListAdapter.swapItems(sourceIndex, targetIndex);
|
2020-03-31 19:20:15 +02:00
|
|
|
if (isSwapped) {
|
|
|
|
saveChanges();
|
|
|
|
}
|
2018-01-31 20:51:47 +01:00
|
|
|
return isSwapped;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isLongPressDragEnabled() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isItemViewSwipeEnabled() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2020-03-31 19:20:15 +02:00
|
|
|
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) { }
|
2018-01-31 20:51:47 +01:00
|
|
|
};
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Utils
|
|
|
|
//////////////////////////////////////////////////////////////////////////*/
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
private PlayQueue getPlayQueueStartingAt(final PlaylistStreamEntry infoItem) {
|
2019-08-14 14:17:05 +02:00
|
|
|
return getPlayQueue(Math.max(itemListAdapter.getItemsList().indexOf(infoItem), 0));
|
|
|
|
}
|
|
|
|
|
2018-04-12 23:46:03 +02:00
|
|
|
protected void showStreamItemDialog(final PlaylistStreamEntry item) {
|
2018-01-31 01:01:11 +01:00
|
|
|
final Context context = getContext();
|
|
|
|
final Activity activity = getActivity();
|
2020-03-31 19:20:15 +02:00
|
|
|
if (context == null || context.getResources() == null || activity == null) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
final StreamInfoItem infoItem = item.toStreamInfoItem();
|
2019-07-25 00:44:12 +02:00
|
|
|
|
|
|
|
if (infoItem.getStreamType() == StreamType.AUDIO_STREAM) {
|
|
|
|
StreamDialogEntry.setEnabledEntries(
|
|
|
|
StreamDialogEntry.enqueue_on_background,
|
|
|
|
StreamDialogEntry.start_here_on_background,
|
|
|
|
StreamDialogEntry.set_as_playlist_thumbnail,
|
|
|
|
StreamDialogEntry.delete,
|
|
|
|
StreamDialogEntry.append_playlist,
|
|
|
|
StreamDialogEntry.share);
|
2019-07-22 11:58:01 +02:00
|
|
|
} else {
|
2019-07-25 00:44:12 +02:00
|
|
|
StreamDialogEntry.setEnabledEntries(
|
|
|
|
StreamDialogEntry.enqueue_on_background,
|
|
|
|
StreamDialogEntry.enqueue_on_popup,
|
|
|
|
StreamDialogEntry.start_here_on_background,
|
|
|
|
StreamDialogEntry.start_here_on_popup,
|
|
|
|
StreamDialogEntry.set_as_playlist_thumbnail,
|
|
|
|
StreamDialogEntry.delete,
|
|
|
|
StreamDialogEntry.append_playlist,
|
|
|
|
StreamDialogEntry.share);
|
2019-08-14 14:17:05 +02:00
|
|
|
|
|
|
|
StreamDialogEntry.start_here_on_popup.setCustomAction(
|
2020-03-31 19:20:15 +02:00
|
|
|
(fragment, infoItemDuplicate) -> NavigationHelper.
|
|
|
|
playOnPopupPlayer(context, getPlayQueueStartingAt(item), true));
|
2019-07-22 11:58:01 +02:00
|
|
|
}
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
StreamDialogEntry.start_here_on_background.setCustomAction((fragment, infoItemDuplicate) ->
|
|
|
|
NavigationHelper.playOnBackgroundPlayer(context,
|
|
|
|
getPlayQueueStartingAt(item), true));
|
2019-07-25 00:53:13 +02:00
|
|
|
StreamDialogEntry.set_as_playlist_thumbnail.setCustomAction(
|
2020-03-31 19:20:15 +02:00
|
|
|
(fragment, infoItemDuplicate) ->
|
|
|
|
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl()));
|
|
|
|
StreamDialogEntry.delete.setCustomAction((fragment, infoItemDuplicate) ->
|
|
|
|
deleteItem(item));
|
2018-01-31 01:01:11 +01:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
new InfoItemDialog(activity, infoItem, StreamDialogEntry.getCommands(context),
|
|
|
|
(dialog, which) -> StreamDialogEntry.clickOn(which, this, infoItem)).show();
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
private void setInitialData(final long pid, final String title) {
|
|
|
|
this.playlistId = pid;
|
|
|
|
this.name = !TextUtils.isEmpty(title) ? title : "";
|
2018-01-31 01:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void setVideoCount(final long count) {
|
|
|
|
if (activity != null && headerStreamCount != null) {
|
|
|
|
headerStreamCount.setText(Localization.localizeStreamCount(activity, count));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private PlayQueue getPlayQueue() {
|
|
|
|
return getPlayQueue(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private PlayQueue getPlayQueue(final int index) {
|
2018-02-03 18:36:40 +01:00
|
|
|
if (itemListAdapter == null) {
|
|
|
|
return new SinglePlayQueue(Collections.emptyList(), 0);
|
|
|
|
}
|
|
|
|
|
2018-01-31 01:01:11 +01:00
|
|
|
final List<LocalItem> infoItems = itemListAdapter.getItemsList();
|
|
|
|
List<StreamInfoItem> streamInfoItems = new ArrayList<>(infoItems.size());
|
|
|
|
for (final LocalItem item : infoItems) {
|
|
|
|
if (item instanceof PlaylistStreamEntry) {
|
|
|
|
streamInfoItems.add(((PlaylistStreamEntry) item).toStreamInfoItem());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new SinglePlayQueue(streamInfoItems, index);
|
2018-01-28 07:14:38 +01:00
|
|
|
}
|
2020-02-08 06:57:36 +01:00
|
|
|
|
|
|
|
private class RemoveWatchedStreams extends AsyncTask<String, Long, Long> {
|
|
|
|
List<PlaylistStreamEntry> localItems = new ArrayList<>();
|
|
|
|
Long RemovedItemCount = 0l;
|
2020-03-05 14:49:04 +01:00
|
|
|
boolean thumbnailVideoRemoved = false;
|
2020-02-08 06:57:36 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPreExecute() {
|
|
|
|
super.onPreExecute();
|
|
|
|
showLoading();
|
|
|
|
localItems.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected Long doInBackground(String... urls) {
|
|
|
|
|
|
|
|
HistoryRecordManager recordManager = new HistoryRecordManager(getContext());
|
|
|
|
Iterator<StreamHistoryEntry> it_history;
|
|
|
|
StreamHistoryEntry history_item;
|
|
|
|
|
|
|
|
Flowable<List<PlaylistStreamEntry>> playlist = playlistManager.getPlaylistStreams(playlistId);
|
|
|
|
Iterator<PlaylistStreamEntry> it_playlist = playlist.blockingFirst().iterator();
|
|
|
|
PlaylistStreamEntry playlist_item = null;
|
|
|
|
|
|
|
|
boolean isNonDuplicate;
|
|
|
|
|
|
|
|
while (it_playlist.hasNext()) {
|
|
|
|
playlist_item = it_playlist.next();
|
|
|
|
|
|
|
|
it_history = recordManager.getStreamHistory().blockingFirst().iterator();
|
|
|
|
|
|
|
|
isNonDuplicate = true;
|
|
|
|
while (it_history.hasNext()) {
|
|
|
|
history_item = it_history.next();
|
|
|
|
if (history_item.streamId == playlist_item.streamId) {
|
|
|
|
isNonDuplicate = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isNonDuplicate) {
|
|
|
|
localItems.add(playlist_item);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RemovedItemCount++;
|
|
|
|
if(playlistManager.getPlaylistThumbnail(playlistId).equals(playlist_item.thumbnailUrl))
|
|
|
|
{
|
2020-03-05 14:49:04 +01:00
|
|
|
thumbnailVideoRemoved = true;
|
2020-02-08 06:57:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this.RemovedItemCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onPostExecute(Long result) {
|
|
|
|
itemListAdapter.clearStreamItemList();
|
|
|
|
itemListAdapter.addItems(localItems);
|
|
|
|
localItems.clear();
|
|
|
|
|
2020-03-05 14:49:04 +01:00
|
|
|
if (thumbnailVideoRemoved)
|
2020-02-08 06:57:36 +01:00
|
|
|
updateThumbnailUrl();
|
|
|
|
|
2020-03-05 14:49:04 +01:00
|
|
|
int amountOfVideos = itemListAdapter.getItemsList().size();
|
|
|
|
setVideoCount(amountOfVideos);
|
2020-02-08 06:57:36 +01:00
|
|
|
|
|
|
|
saveChanges();
|
|
|
|
hideLoading();
|
2020-03-05 14:49:04 +01:00
|
|
|
|
|
|
|
if(amountOfVideos == 0)
|
|
|
|
showEmptyState();
|
2020-02-08 06:57:36 +01:00
|
|
|
}
|
|
|
|
}
|
2018-01-17 06:12:03 +01:00
|
|
|
}
|
|
|
|
|