mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-02-23 22:40:06 +00:00
-Added bulk playlist creation and append.
-Added UI to create playlist from service player activity. -Added state saving to playlist dialogs. -Removed access to history activity on service player activity. -Made StreamEntity serializable.
This commit is contained in:
parent
168ac91ab8
commit
776dbc34f7
@ -19,7 +19,7 @@ public final class NewPipeDatabase {
|
||||
|
||||
public static void init(Context context) {
|
||||
databaseInstance = Room
|
||||
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
||||
.databaseBuilder(context, AppDatabase.class, DATABASE_NAME)
|
||||
.addMigrations(MIGRATION_11_12)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build();
|
||||
|
@ -15,7 +15,7 @@ public class Migrations {
|
||||
/*
|
||||
* Unfortunately these queries must be hardcoded due to the possibility of
|
||||
* schema and names changing at a later date, thus invalidating the older migration
|
||||
* scripts if names are not hardcoded.
|
||||
* scripts if they are not hardcoded.
|
||||
* */
|
||||
|
||||
// Not much we can do about this, since room doesn't create tables before migration.
|
||||
|
@ -9,15 +9,18 @@ import android.arch.persistence.room.PrimaryKey;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.util.Constants;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_SERVICE_ID;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL;
|
||||
|
||||
@Entity(tableName = STREAM_TABLE,
|
||||
indices = {@Index(value = {STREAM_SERVICE_ID, STREAM_URL}, unique = true)})
|
||||
public class StreamEntity {
|
||||
public class StreamEntity implements Serializable {
|
||||
|
||||
final public static String STREAM_TABLE = "streams";
|
||||
final public static String STREAM_ID = "uid";
|
||||
@ -78,6 +81,12 @@ public class StreamEntity {
|
||||
info.uploader_name, info.duration);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public StreamEntity(final PlayQueueItem item) {
|
||||
this(item.getServiceId(), item.getTitle(), item.getUrl(), item.getStreamType(),
|
||||
item.getThumbnailUrl(), item.getUploader(), item.getDuration());
|
||||
}
|
||||
|
||||
@Ignore
|
||||
public StreamInfoItem toStreamInfoItem() throws IllegalArgumentException {
|
||||
StreamInfoItem item = new StreamInfoItem(
|
||||
|
@ -331,7 +331,8 @@ public class VideoDetailFragment extends BaseStateFragment<StreamInfo> implement
|
||||
break;
|
||||
case R.id.detail_controls_playlist_append:
|
||||
if (getFragmentManager() != null && currentInfo != null) {
|
||||
PlaylistAppendDialog.newInstance(currentInfo).show(getFragmentManager(), TAG);
|
||||
PlaylistAppendDialog.fromStreamInfo(currentInfo)
|
||||
.show(getFragmentManager(), TAG);
|
||||
}
|
||||
break;
|
||||
case R.id.detail_uploader_root_layout:
|
||||
|
@ -33,34 +33,38 @@ public class LocalPlaylistManager {
|
||||
}
|
||||
|
||||
public Maybe<List<Long>> createPlaylist(final String name, final List<StreamEntity> streams) {
|
||||
// Disallow creation of empty playlists until user is able to select thumbnail
|
||||
// Disallow creation of empty playlists
|
||||
if (streams.isEmpty()) return Maybe.empty();
|
||||
final StreamEntity defaultStream = streams.get(0);
|
||||
final PlaylistEntity newPlaylist = new PlaylistEntity(name, defaultStream.getThumbnailUrl());
|
||||
final PlaylistEntity newPlaylist =
|
||||
new PlaylistEntity(name, defaultStream.getThumbnailUrl());
|
||||
|
||||
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
||||
final long playlistId = playlistTable.insert(newPlaylist);
|
||||
return Maybe.fromCallable(() -> database.runInTransaction(() ->
|
||||
upsertStreams(playlistTable.insert(newPlaylist), streams, 0))
|
||||
).subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public Maybe<List<Long>> appendToPlaylist(final long playlistId,
|
||||
final List<StreamEntity> streams) {
|
||||
return playlistStreamTable.getMaximumIndexOf(playlistId)
|
||||
.firstElement()
|
||||
.map(maxJoinIndex -> database.runInTransaction(() ->
|
||||
upsertStreams(playlistId, streams, maxJoinIndex + 1))
|
||||
).subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
private List<Long> upsertStreams(final long playlistId,
|
||||
final List<StreamEntity> streams,
|
||||
final int indexOffset) {
|
||||
|
||||
List<PlaylistStreamEntity> joinEntities = new ArrayList<>(streams.size());
|
||||
for (int index = 0; index < streams.size(); index++) {
|
||||
// Upsert streams and get their ids
|
||||
final long streamId = streamTable.upsert(streams.get(index));
|
||||
joinEntities.add(new PlaylistStreamEntity(playlistId, streamId, index));
|
||||
joinEntities.add(new PlaylistStreamEntity(playlistId, streamId,
|
||||
index + indexOffset));
|
||||
}
|
||||
|
||||
return playlistStreamTable.insertAll(joinEntities);
|
||||
})).subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public Maybe<Long> appendToPlaylist(final long playlistId, final StreamEntity stream) {
|
||||
final Maybe<Long> streamIdFuture = Maybe.fromCallable(() -> streamTable.upsert(stream));
|
||||
final Maybe<Integer> joinIndexFuture =
|
||||
playlistStreamTable.getMaximumIndexOf(playlistId).firstElement();
|
||||
|
||||
return Maybe.zip(streamIdFuture, joinIndexFuture, (streamId, currentMaxJoinIndex) ->
|
||||
playlistStreamTable.insert(new PlaylistStreamEntity(playlistId,
|
||||
streamId, currentMaxJoinIndex + 1))
|
||||
).subscribeOn(Schedulers.io());
|
||||
}
|
||||
|
||||
public Completable updateJoin(final long playlistId, final List<Long> streamIds) {
|
||||
|
@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
@ -19,34 +18,48 @@ import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||
import org.schabi.newpipe.info_list.stored.LocalPlaylistInfoItem;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public class PlaylistAppendDialog extends DialogFragment {
|
||||
public final class PlaylistAppendDialog extends PlaylistDialog {
|
||||
private static final String TAG = PlaylistAppendDialog.class.getCanonicalName();
|
||||
private static final String INFO_KEY = "info_key";
|
||||
|
||||
private StreamInfo streamInfo;
|
||||
|
||||
private View newPlaylistButton;
|
||||
private RecyclerView playlistRecyclerView;
|
||||
private InfoListAdapter playlistAdapter;
|
||||
|
||||
public static PlaylistAppendDialog newInstance(final StreamInfo info) {
|
||||
public static PlaylistAppendDialog fromStreamInfo(final StreamInfo info) {
|
||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||
dialog.setInfo(info);
|
||||
dialog.setInfo(Collections.singletonList(new StreamEntity(info)));
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private void setInfo(StreamInfo info) {
|
||||
this.streamInfo = info;
|
||||
public static PlaylistAppendDialog fromStreamInfoItems(final List<StreamInfoItem> items) {
|
||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||
List<StreamEntity> entities = new ArrayList<>(items.size());
|
||||
for (final StreamInfoItem item : items) {
|
||||
entities.add(new StreamEntity(item));
|
||||
}
|
||||
dialog.setInfo(entities);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static PlaylistAppendDialog fromPlayQueueItems(final List<PlayQueueItem> items) {
|
||||
PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||
List<StreamEntity> entities = new ArrayList<>(items.size());
|
||||
for (final PlayQueueItem item : items) {
|
||||
entities.add(new StreamEntity(item));
|
||||
}
|
||||
dialog.setInfo(entities);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
@ -60,14 +73,9 @@ public class PlaylistAppendDialog extends DialogFragment {
|
||||
playlistAdapter.useMiniItemVariants(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
Serializable serial = savedInstanceState.getSerializable(INFO_KEY);
|
||||
if (serial instanceof StreamInfo) streamInfo = (StreamInfo) serial;
|
||||
}
|
||||
}
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
@ -79,7 +87,7 @@ public class PlaylistAppendDialog extends DialogFragment {
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
newPlaylistButton = view.findViewById(R.id.newPlaylist);
|
||||
final View newPlaylistButton = view.findViewById(R.id.newPlaylist);
|
||||
playlistRecyclerView = view.findViewById(R.id.playlist_list);
|
||||
playlistRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
playlistRecyclerView.setAdapter(playlistAdapter);
|
||||
@ -92,12 +100,14 @@ public class PlaylistAppendDialog extends DialogFragment {
|
||||
playlistAdapter.setOnPlaylistSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener<PlaylistInfoItem>() {
|
||||
@Override
|
||||
public void selected(PlaylistInfoItem selectedItem) {
|
||||
if (!(selectedItem instanceof LocalPlaylistInfoItem)) return;
|
||||
if (!(selectedItem instanceof LocalPlaylistInfoItem) || getStreams() == null)
|
||||
return;
|
||||
|
||||
final long playlistId = ((LocalPlaylistInfoItem) selectedItem).getPlaylistId();
|
||||
final Toast successToast =
|
||||
Toast.makeText(getContext(), "Added", Toast.LENGTH_SHORT);
|
||||
|
||||
playlistManager.appendToPlaylist(playlistId, new StreamEntity(streamInfo))
|
||||
playlistManager.appendToPlaylist(playlistId, getStreams())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignored -> successToast.show());
|
||||
|
||||
@ -127,20 +137,14 @@ public class PlaylistAppendDialog extends DialogFragment {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putSerializable(INFO_KEY, streamInfo);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Helper
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void openCreatePlaylistDialog() {
|
||||
if (streamInfo == null || getFragmentManager() == null) return;
|
||||
if (getStreams() == null || getFragmentManager() == null) return;
|
||||
|
||||
PlaylistCreationDialog.newInstance(streamInfo).show(getFragmentManager(), TAG);
|
||||
PlaylistCreationDialog.newInstance(getStreams()).show(getFragmentManager(), TAG);
|
||||
getDialog().dismiss();
|
||||
}
|
||||
}
|
||||
|
@ -5,63 +5,35 @@ import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.NewPipeDatabase;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
|
||||
public class PlaylistCreationDialog extends DialogFragment {
|
||||
public final class PlaylistCreationDialog extends PlaylistDialog {
|
||||
private static final String TAG = PlaylistCreationDialog.class.getCanonicalName();
|
||||
private static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
||||
private static final String INFO_KEY = "info_key";
|
||||
|
||||
private StreamInfo streamInfo;
|
||||
|
||||
public static PlaylistCreationDialog newInstance(final StreamInfo info) {
|
||||
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streams) {
|
||||
PlaylistCreationDialog dialog = new PlaylistCreationDialog();
|
||||
dialog.setInfo(info);
|
||||
dialog.setInfo(streams);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
private void setInfo(final StreamInfo info) {
|
||||
this.streamInfo = info;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// LifeCycle
|
||||
// Dialog
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (streamInfo != null) {
|
||||
outState.putSerializable(INFO_KEY, streamInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null && streamInfo == null) {
|
||||
final Object infoCandidate = savedInstanceState.getSerializable(INFO_KEY);
|
||||
if (infoCandidate != null && infoCandidate instanceof StreamInfo) {
|
||||
streamInfo = (StreamInfo) infoCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
if (streamInfo == null) return super.onCreateDialog(savedInstanceState);
|
||||
if (getStreams() == null) return super.onCreateDialog(savedInstanceState);
|
||||
|
||||
View dialogView = View.inflate(getContext(),
|
||||
R.layout.dialog_create_playlist, null);
|
||||
@ -76,13 +48,11 @@ public class PlaylistCreationDialog extends DialogFragment {
|
||||
final String name = nameInput.getText().toString();
|
||||
final LocalPlaylistManager playlistManager =
|
||||
new LocalPlaylistManager(NewPipeDatabase.getInstance(getContext()));
|
||||
final List<StreamEntity> streams =
|
||||
Collections.singletonList(new StreamEntity(streamInfo));
|
||||
final Toast successToast = Toast.makeText(getActivity(),
|
||||
"Playlist " + name + " successfully created",
|
||||
"Playlist successfully created",
|
||||
Toast.LENGTH_SHORT);
|
||||
|
||||
playlistManager.createPlaylist(name, streams)
|
||||
playlistManager.createPlaylist(name, getStreams())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(longs -> successToast.show());
|
||||
});
|
||||
|
@ -0,0 +1,73 @@
|
||||
package org.schabi.newpipe.fragments.local;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.util.StateSaver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
public abstract class PlaylistDialog extends DialogFragment implements StateSaver.WriteRead {
|
||||
|
||||
private List<StreamEntity> streamEntities;
|
||||
|
||||
private StateSaver.SavedState savedState;
|
||||
|
||||
protected void setInfo(final List<StreamEntity> entities) {
|
||||
this.streamEntities = entities;
|
||||
}
|
||||
|
||||
protected List<StreamEntity> getStreams() {
|
||||
return streamEntities;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// LifeCycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
savedState = StateSaver.tryToRestore(savedInstanceState, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
StateSaver.onDestroy(savedState);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// State Saving
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public String generateSuffix() {
|
||||
final int size = streamEntities == null ? 0 : streamEntities.size();
|
||||
return "." + size + ".list";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(Queue<Object> objectsToSave) {
|
||||
objectsToSave.add(streamEntities);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void readFrom(@NonNull Queue<Object> savedObjects) throws Exception {
|
||||
streamEntities = (List<StreamEntity>) savedObjects.poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (getActivity() != null) {
|
||||
savedState = StateSaver.tryToSave(getActivity().isChangingConfigurations(),
|
||||
savedState, outState, this);
|
||||
}
|
||||
}
|
||||
}
|
@ -675,6 +675,7 @@ public abstract class BasePlayer implements Player.EventListener, PlaybackListen
|
||||
simpleExoPlayer.seekTo(currentSourceIndex, startPos);
|
||||
}
|
||||
|
||||
// TODO: update exoplayer to 2.6.x in order to register view count on repeated streams
|
||||
databaseUpdateReactor.add(recordManager.onViewed(currentInfo).subscribe());
|
||||
initThumbnail(info == null ? item.getThumbnailUrl() : info.thumbnail_url);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.google.android.exoplayer2.Player;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||
import org.schabi.newpipe.fragments.local.PlaylistAppendDialog;
|
||||
import org.schabi.newpipe.player.event.PlayerEventListener;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItemBuilder;
|
||||
@ -149,8 +150,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
case R.id.action_history:
|
||||
NavigationHelper.openHistory(this);
|
||||
case R.id.action_append_playlist:
|
||||
appendToPlaylist();
|
||||
return true;
|
||||
case R.id.action_settings:
|
||||
NavigationHelper.openSettings(this);
|
||||
@ -185,6 +186,14 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
null
|
||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
}
|
||||
|
||||
private void appendToPlaylist() {
|
||||
if (this.player != null && this.player.getPlayQueue() != null) {
|
||||
PlaylistAppendDialog.fromPlayQueueItems(this.player.getPlayQueue().getStreams())
|
||||
.show(getSupportFragmentManager(), getTag());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Service Connection
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5,6 +5,7 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -23,6 +24,7 @@ public class PlayQueueItem implements Serializable {
|
||||
final private long duration;
|
||||
final private String thumbnailUrl;
|
||||
final private String uploader;
|
||||
final private StreamType streamType;
|
||||
|
||||
private long recoveryPosition;
|
||||
private Throwable error;
|
||||
@ -30,22 +32,26 @@ public class PlayQueueItem implements Serializable {
|
||||
private transient Single<StreamInfo> stream;
|
||||
|
||||
PlayQueueItem(@NonNull final StreamInfo info) {
|
||||
this(info.getName(), info.getUrl(), info.getServiceId(), info.duration, info.thumbnail_url, info.uploader_name);
|
||||
this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(),
|
||||
info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType());
|
||||
this.stream = Single.just(info);
|
||||
}
|
||||
|
||||
PlayQueueItem(@NonNull final StreamInfoItem item) {
|
||||
this(item.getName(), item.getUrl(), item.getServiceId(), item.duration, item.thumbnail_url, item.uploader_name);
|
||||
this(item.getName(), item.getUrl(), item.getServiceId(), item.getDuration(),
|
||||
item.getThumbnailUrl(), item.getUploaderName(), item.getStreamType());
|
||||
}
|
||||
|
||||
private PlayQueueItem(final String name, final String url, final int serviceId,
|
||||
final long duration, final String thumbnailUrl, final String uploader) {
|
||||
final long duration, final String thumbnailUrl, final String uploader,
|
||||
final StreamType streamType) {
|
||||
this.title = name;
|
||||
this.url = url;
|
||||
this.serviceId = serviceId;
|
||||
this.duration = duration;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.uploader = uploader;
|
||||
this.streamType = streamType;
|
||||
|
||||
this.recoveryPosition = RECOVERY_UNSET;
|
||||
}
|
||||
@ -78,6 +84,10 @@ public class PlayQueueItem implements Serializable {
|
||||
return uploader;
|
||||
}
|
||||
|
||||
public StreamType getStreamType() {
|
||||
return streamType;
|
||||
}
|
||||
|
||||
public long getRecoveryPosition() {
|
||||
return recoveryPosition;
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.schabi.newpipe.history.HistoryActivity">
|
||||
tools:context=".player.BackgroundPlayerActivity">
|
||||
|
||||
<item android:id="@+id/action_history"
|
||||
<item android:id="@+id/action_append_playlist"
|
||||
android:orderInCategory="981"
|
||||
android:title="@string/action_history"
|
||||
android:title="@string/append_playlist"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
<item android:id="@+id/action_settings"
|
||||
|
Loading…
x
Reference in New Issue
Block a user