Implement playback state management
This commit is contained in:
parent
416e0fb609
commit
4e1423d224
33 changed files with 978 additions and 582 deletions
|
@ -574,7 +574,7 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
playQueue = new SinglePlayQueue((StreamInfo) info);
|
playQueue = new SinglePlayQueue((StreamInfo) info);
|
||||||
|
|
||||||
if (playerChoice.equals(videoPlayerKey)) {
|
if (playerChoice.equals(videoPlayerKey)) {
|
||||||
NavigationHelper.playOnMainPlayer(this, playQueue);
|
NavigationHelper.playOnMainPlayer(this, playQueue, true);
|
||||||
} else if (playerChoice.equals(backgroundPlayerKey)) {
|
} else if (playerChoice.equals(backgroundPlayerKey)) {
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(this, playQueue, true);
|
NavigationHelper.enqueueOnBackgroundPlayer(this, playQueue, true);
|
||||||
} else if (playerChoice.equals(popupPlayerKey)) {
|
} else if (playerChoice.equals(popupPlayerKey)) {
|
||||||
|
@ -587,11 +587,11 @@ public class RouterActivity extends AppCompatActivity {
|
||||||
playQueue = info instanceof ChannelInfo ? new ChannelPlayQueue((ChannelInfo) info) : new PlaylistPlayQueue((PlaylistInfo) info);
|
playQueue = info instanceof ChannelInfo ? new ChannelPlayQueue((ChannelInfo) info) : new PlaylistPlayQueue((PlaylistInfo) info);
|
||||||
|
|
||||||
if (playerChoice.equals(videoPlayerKey)) {
|
if (playerChoice.equals(videoPlayerKey)) {
|
||||||
NavigationHelper.playOnMainPlayer(this, playQueue);
|
NavigationHelper.playOnMainPlayer(this, playQueue, true);
|
||||||
} else if (playerChoice.equals(backgroundPlayerKey)) {
|
} else if (playerChoice.equals(backgroundPlayerKey)) {
|
||||||
NavigationHelper.playOnBackgroundPlayer(this, playQueue);
|
NavigationHelper.playOnBackgroundPlayer(this, playQueue, true);
|
||||||
} else if (playerChoice.equals(popupPlayerKey)) {
|
} else if (playerChoice.equals(popupPlayerKey)) {
|
||||||
NavigationHelper.playOnPopupPlayer(this, playQueue);
|
NavigationHelper.playOnPopupPlayer(this, playQueue, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,6 +50,11 @@ public abstract class StreamHistoryDAO implements HistoryDAO<StreamHistoryEntity
|
||||||
" ORDER BY " + STREAM_ACCESS_DATE + " DESC")
|
" ORDER BY " + STREAM_ACCESS_DATE + " DESC")
|
||||||
public abstract Flowable<List<StreamHistoryEntry>> getHistory();
|
public abstract Flowable<List<StreamHistoryEntry>> getHistory();
|
||||||
|
|
||||||
|
@Query("SELECT * FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID +
|
||||||
|
" = :streamId ORDER BY " + STREAM_ACCESS_DATE + " DESC LIMIT 1")
|
||||||
|
@Nullable
|
||||||
|
public abstract StreamHistoryEntity getLatestEntry(final long streamId);
|
||||||
|
|
||||||
@Query("DELETE FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
|
@Query("DELETE FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
|
||||||
public abstract int deleteStreamHistory(final long streamId);
|
public abstract int deleteStreamHistory(final long streamId);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@ import android.arch.persistence.room.ColumnInfo;
|
||||||
import android.arch.persistence.room.Entity;
|
import android.arch.persistence.room.Entity;
|
||||||
import android.arch.persistence.room.ForeignKey;
|
import android.arch.persistence.room.ForeignKey;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static android.arch.persistence.room.ForeignKey.CASCADE;
|
import static android.arch.persistence.room.ForeignKey.CASCADE;
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
|
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
|
||||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
|
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
|
||||||
|
@ -22,6 +24,12 @@ public class StreamStateEntity {
|
||||||
final public static String JOIN_STREAM_ID = "stream_id";
|
final public static String JOIN_STREAM_ID = "stream_id";
|
||||||
final public static String STREAM_PROGRESS_TIME = "progress_time";
|
final public static String STREAM_PROGRESS_TIME = "progress_time";
|
||||||
|
|
||||||
|
|
||||||
|
/** Playback state will not be saved, if playback time less than this threshold */
|
||||||
|
private static final int PLAYBACK_SAVE_THRESHOLD_START_SECONDS = 5;
|
||||||
|
/** Playback state will not be saved, if time left less than this threshold */
|
||||||
|
private static final int PLAYBACK_SAVE_THRESHOLD_END_SECONDS = 10;
|
||||||
|
|
||||||
@ColumnInfo(name = JOIN_STREAM_ID)
|
@ColumnInfo(name = JOIN_STREAM_ID)
|
||||||
private long streamUid;
|
private long streamUid;
|
||||||
|
|
||||||
|
@ -48,4 +56,10 @@ public class StreamStateEntity {
|
||||||
public void setProgressTime(long progressTime) {
|
public void setProgressTime(long progressTime) {
|
||||||
this.progressTime = progressTime;
|
this.progressTime = progressTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isValid(int durationInSeconds) {
|
||||||
|
final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(progressTime);
|
||||||
|
return seconds > PLAYBACK_SAVE_THRESHOLD_START_SECONDS
|
||||||
|
&& seconds < durationInSeconds - PLAYBACK_SAVE_THRESHOLD_END_SECONDS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,12 +89,14 @@ import org.schabi.newpipe.util.PermissionHelper;
|
||||||
import org.schabi.newpipe.util.ShareUtils;
|
import org.schabi.newpipe.util.ShareUtils;
|
||||||
import org.schabi.newpipe.util.StreamItemAdapter;
|
import org.schabi.newpipe.util.StreamItemAdapter;
|
||||||
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
|
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
|
||||||
|
import org.schabi.newpipe.views.AnimatedProgressBar;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
@ -118,7 +120,7 @@ public class VideoDetailFragment
|
||||||
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
|
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
|
||||||
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
|
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
|
||||||
private static final int TOOLBAR_ITEMS_UPDATE_FLAG = 0x4;
|
private static final int TOOLBAR_ITEMS_UPDATE_FLAG = 0x4;
|
||||||
private static final int COMMENTS_UPDATE_FLAG = 0x4;
|
private static final int COMMENTS_UPDATE_FLAG = 0x8;
|
||||||
|
|
||||||
private boolean autoPlayEnabled;
|
private boolean autoPlayEnabled;
|
||||||
private boolean showRelatedStreams;
|
private boolean showRelatedStreams;
|
||||||
|
@ -136,6 +138,8 @@ public class VideoDetailFragment
|
||||||
private Disposable currentWorker;
|
private Disposable currentWorker;
|
||||||
@NonNull
|
@NonNull
|
||||||
private CompositeDisposable disposables = new CompositeDisposable();
|
private CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
@Nullable
|
||||||
|
private Disposable positionSubscriber = null;
|
||||||
|
|
||||||
private List<VideoStream> sortedVideoStreams;
|
private List<VideoStream> sortedVideoStreams;
|
||||||
private int selectedVideoStreamIndex = -1;
|
private int selectedVideoStreamIndex = -1;
|
||||||
|
@ -153,6 +157,7 @@ public class VideoDetailFragment
|
||||||
private View thumbnailBackgroundButton;
|
private View thumbnailBackgroundButton;
|
||||||
private ImageView thumbnailImageView;
|
private ImageView thumbnailImageView;
|
||||||
private ImageView thumbnailPlayButton;
|
private ImageView thumbnailPlayButton;
|
||||||
|
private AnimatedProgressBar positionView;
|
||||||
|
|
||||||
private View videoTitleRoot;
|
private View videoTitleRoot;
|
||||||
private TextView videoTitleTextView;
|
private TextView videoTitleTextView;
|
||||||
|
@ -165,6 +170,7 @@ public class VideoDetailFragment
|
||||||
private TextView detailControlsDownload;
|
private TextView detailControlsDownload;
|
||||||
private TextView appendControlsDetail;
|
private TextView appendControlsDetail;
|
||||||
private TextView detailDurationView;
|
private TextView detailDurationView;
|
||||||
|
private TextView detailPositionView;
|
||||||
|
|
||||||
private LinearLayout videoDescriptionRootLayout;
|
private LinearLayout videoDescriptionRootLayout;
|
||||||
private TextView videoUploadDateView;
|
private TextView videoUploadDateView;
|
||||||
|
@ -259,6 +265,8 @@ public class VideoDetailFragment
|
||||||
// Check if it was loading when the fragment was stopped/paused,
|
// Check if it was loading when the fragment was stopped/paused,
|
||||||
if (wasLoading.getAndSet(false)) {
|
if (wasLoading.getAndSet(false)) {
|
||||||
selectAndLoadVideo(serviceId, url, name);
|
selectAndLoadVideo(serviceId, url, name);
|
||||||
|
} else if (currentInfo != null) {
|
||||||
|
updateProgressInfo(currentInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,8 +276,10 @@ public class VideoDetailFragment
|
||||||
PreferenceManager.getDefaultSharedPreferences(activity)
|
PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
.unregisterOnSharedPreferenceChangeListener(this);
|
.unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
|
if (positionSubscriber != null) positionSubscriber.dispose();
|
||||||
if (currentWorker != null) currentWorker.dispose();
|
if (currentWorker != null) currentWorker.dispose();
|
||||||
if (disposables != null) disposables.clear();
|
if (disposables != null) disposables.clear();
|
||||||
|
positionSubscriber = null;
|
||||||
currentWorker = null;
|
currentWorker = null;
|
||||||
disposables = null;
|
disposables = null;
|
||||||
}
|
}
|
||||||
|
@ -462,6 +472,7 @@ public class VideoDetailFragment
|
||||||
videoTitleTextView = rootView.findViewById(R.id.detail_video_title_view);
|
videoTitleTextView = rootView.findViewById(R.id.detail_video_title_view);
|
||||||
videoTitleToggleArrow = rootView.findViewById(R.id.detail_toggle_description_view);
|
videoTitleToggleArrow = rootView.findViewById(R.id.detail_toggle_description_view);
|
||||||
videoCountView = rootView.findViewById(R.id.detail_view_count_view);
|
videoCountView = rootView.findViewById(R.id.detail_view_count_view);
|
||||||
|
positionView = rootView.findViewById(R.id.position_view);
|
||||||
|
|
||||||
detailControlsBackground = rootView.findViewById(R.id.detail_controls_background);
|
detailControlsBackground = rootView.findViewById(R.id.detail_controls_background);
|
||||||
detailControlsPopup = rootView.findViewById(R.id.detail_controls_popup);
|
detailControlsPopup = rootView.findViewById(R.id.detail_controls_popup);
|
||||||
|
@ -469,6 +480,7 @@ public class VideoDetailFragment
|
||||||
detailControlsDownload = rootView.findViewById(R.id.detail_controls_download);
|
detailControlsDownload = rootView.findViewById(R.id.detail_controls_download);
|
||||||
appendControlsDetail = rootView.findViewById(R.id.touch_append_detail);
|
appendControlsDetail = rootView.findViewById(R.id.touch_append_detail);
|
||||||
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
|
detailDurationView = rootView.findViewById(R.id.detail_duration_view);
|
||||||
|
detailPositionView = rootView.findViewById(R.id.detail_position_view);
|
||||||
|
|
||||||
videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
|
videoDescriptionRootLayout = rootView.findViewById(R.id.detail_description_root_layout);
|
||||||
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
|
videoUploadDateView = rootView.findViewById(R.id.detail_upload_date_view);
|
||||||
|
@ -536,10 +548,10 @@ public class VideoDetailFragment
|
||||||
final DialogInterface.OnClickListener actions = (DialogInterface dialogInterface, int i) -> {
|
final DialogInterface.OnClickListener actions = (DialogInterface dialogInterface, int i) -> {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item), true);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(getActivity(), new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnPopupPlayer(getActivity(), new SinglePlayQueue(item), true);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (getFragmentManager() != null) {
|
if (getFragmentManager() != null) {
|
||||||
|
@ -890,11 +902,11 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
||||||
if (append) {
|
if (append) {
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue);
|
NavigationHelper.enqueueOnPopupPlayer(activity, itemQueue, false);
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||||
final Intent intent = NavigationHelper.getPlayerIntent(
|
final Intent intent = NavigationHelper.getPlayerIntent(
|
||||||
activity, PopupVideoPlayer.class, itemQueue, getSelectedVideoStream().resolution
|
activity, PopupVideoPlayer.class, itemQueue, getSelectedVideoStream().resolution, true
|
||||||
);
|
);
|
||||||
activity.startService(intent);
|
activity.startService(intent);
|
||||||
}
|
}
|
||||||
|
@ -914,9 +926,9 @@ public class VideoDetailFragment
|
||||||
private void openNormalBackgroundPlayer(final boolean append) {
|
private void openNormalBackgroundPlayer(final boolean append) {
|
||||||
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
final PlayQueue itemQueue = new SinglePlayQueue(currentInfo);
|
||||||
if (append) {
|
if (append) {
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(activity, itemQueue);
|
NavigationHelper.enqueueOnBackgroundPlayer(activity, itemQueue, false);
|
||||||
} else {
|
} else {
|
||||||
NavigationHelper.playOnBackgroundPlayer(activity, itemQueue);
|
NavigationHelper.playOnBackgroundPlayer(activity, itemQueue, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -926,7 +938,7 @@ public class VideoDetailFragment
|
||||||
mIntent = NavigationHelper.getPlayerIntent(activity,
|
mIntent = NavigationHelper.getPlayerIntent(activity,
|
||||||
MainVideoPlayer.class,
|
MainVideoPlayer.class,
|
||||||
playQueue,
|
playQueue,
|
||||||
getSelectedVideoStream().getResolution());
|
getSelectedVideoStream().getResolution(), true);
|
||||||
startActivity(mIntent);
|
startActivity(mIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1032,6 +1044,8 @@ public class VideoDetailFragment
|
||||||
animateView(spinnerToolbar, false, 200);
|
animateView(spinnerToolbar, false, 200);
|
||||||
animateView(thumbnailPlayButton, false, 50);
|
animateView(thumbnailPlayButton, false, 50);
|
||||||
animateView(detailDurationView, false, 100);
|
animateView(detailDurationView, false, 100);
|
||||||
|
animateView(detailPositionView, false, 100);
|
||||||
|
animateView(positionView, false, 50);
|
||||||
|
|
||||||
videoTitleTextView.setText(name != null ? name : "");
|
videoTitleTextView.setText(name != null ? name : "");
|
||||||
videoTitleTextView.setMaxLines(1);
|
videoTitleTextView.setMaxLines(1);
|
||||||
|
@ -1146,6 +1160,7 @@ public class VideoDetailFragment
|
||||||
videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate()));
|
videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate()));
|
||||||
}
|
}
|
||||||
prepareDescription(info.getDescription());
|
prepareDescription(info.getDescription());
|
||||||
|
updateProgressInfo(info);
|
||||||
|
|
||||||
animateView(spinnerToolbar, true, 500);
|
animateView(spinnerToolbar, true, 500);
|
||||||
setupActionBar(info);
|
setupActionBar(info);
|
||||||
|
@ -1250,4 +1265,37 @@ public class VideoDetailFragment
|
||||||
|
|
||||||
showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema);
|
showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateProgressInfo(@NonNull final StreamInfo info) {
|
||||||
|
if (positionSubscriber != null) {
|
||||||
|
positionSubscriber.dispose();
|
||||||
|
}
|
||||||
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
|
final boolean playbackResumeEnabled =
|
||||||
|
prefs.getBoolean(activity.getString(R.string.enable_watch_history_key), true)
|
||||||
|
&& prefs.getBoolean(activity.getString(R.string.enable_playback_resume_key), true);
|
||||||
|
if (!playbackResumeEnabled || info.getDuration() <= 0) {
|
||||||
|
positionView.setVisibility(View.INVISIBLE);
|
||||||
|
detailPositionView.setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext());
|
||||||
|
positionSubscriber = recordManager.loadStreamState(info)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.onErrorComplete()
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(state -> {
|
||||||
|
final int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(state.getProgressTime());
|
||||||
|
positionView.setMax((int) info.getDuration());
|
||||||
|
positionView.setProgress(seconds);
|
||||||
|
detailPositionView.setText(Localization.getDurationString(seconds));
|
||||||
|
animateView(positionView, true, 500);
|
||||||
|
animateView(detailPositionView, true, 500);
|
||||||
|
}, e -> {
|
||||||
|
if (DEBUG) e.printStackTrace();
|
||||||
|
}, () -> {
|
||||||
|
animateView(positionView, false, 500);
|
||||||
|
animateView(detailPositionView, false, 500);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,13 +266,13 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
||||||
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
|
final DialogInterface.OnClickListener actions = (dialogInterface, i) -> {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.playOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
NavigationHelper.playOnBackgroundPlayer(context, new SinglePlayQueue(item), true);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item), true);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item), true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (getFragmentManager() != null) {
|
if (getFragmentManager() != null) {
|
||||||
|
|
|
@ -170,19 +170,19 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
final int index = Math.max(infoListAdapter.getItemsList().indexOf(item), 0);
|
final int index = Math.max(infoListAdapter.getItemsList().indexOf(item), 0);
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item), false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item), false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
if (getFragmentManager() != null) {
|
if (getFragmentManager() != null) {
|
||||||
|
@ -440,11 +440,11 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
|
||||||
monitorSubscription(result);
|
monitorSubscription(result);
|
||||||
|
|
||||||
headerPlayAllButton.setOnClickListener(
|
headerPlayAllButton.setOnClickListener(
|
||||||
view -> NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
view -> NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
||||||
headerPopupButton.setOnClickListener(
|
headerPopupButton.setOnClickListener(
|
||||||
view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()));
|
view -> NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||||
headerBackgroundButton.setOnClickListener(
|
headerBackgroundButton.setOnClickListener(
|
||||||
view -> NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()));
|
view -> NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlayQueue getPlayQueue() {
|
private PlayQueue getPlayQueue() {
|
||||||
|
|
|
@ -154,22 +154,22 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
final int index = Math.max(infoListAdapter.getItemsList().indexOf(item), 0);
|
final int index = Math.max(infoListAdapter.getItemsList().indexOf(item), 0);
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item), false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item), false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
ShareUtils.shareUrl(this.getContext(), item.getName(), item.getUrl());
|
ShareUtils.shareUrl(requireContext(), item.getName(), item.getUrl());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -301,19 +301,19 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||||
.subscribe(getPlaylistBookmarkSubscriber());
|
.subscribe(getPlaylistBookmarkSubscriber());
|
||||||
|
|
||||||
headerPlayAllButton.setOnClickListener(view ->
|
headerPlayAllButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
||||||
headerPopupButton.setOnClickListener(view ->
|
headerPopupButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||||
headerBackgroundButton.setOnClickListener(view ->
|
headerBackgroundButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||||
|
|
||||||
headerPopupButton.setOnLongClickListener(view -> {
|
headerPopupButton.setOnLongClickListener(view -> {
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue());
|
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
headerBackgroundButton.setOnLongClickListener(view -> {
|
headerBackgroundButton.setOnLongClickListener(view -> {
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue());
|
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,12 +37,14 @@ import org.schabi.newpipe.database.stream.dao.StreamStateDAO;
|
||||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.Flowable;
|
import io.reactivex.Flowable;
|
||||||
import io.reactivex.Maybe;
|
import io.reactivex.Maybe;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
@ -80,9 +82,9 @@ public class HistoryRecordManager {
|
||||||
final Date currentTime = new Date();
|
final Date currentTime = new Date();
|
||||||
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
||||||
final long streamId = streamTable.upsert(new StreamEntity(info));
|
final long streamId = streamTable.upsert(new StreamEntity(info));
|
||||||
StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry();
|
StreamHistoryEntity latestEntry = streamHistoryTable.getLatestEntry(streamId);
|
||||||
|
|
||||||
if (latestEntry != null && latestEntry.getStreamUid() == streamId) {
|
if (latestEntry != null) {
|
||||||
streamHistoryTable.delete(latestEntry);
|
streamHistoryTable.delete(latestEntry);
|
||||||
latestEntry.setAccessDate(currentTime);
|
latestEntry.setAccessDate(currentTime);
|
||||||
latestEntry.setRepeatCount(latestEntry.getRepeatCount() + 1);
|
latestEntry.setRepeatCount(latestEntry.getRepeatCount() + 1);
|
||||||
|
@ -99,7 +101,7 @@ public class HistoryRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Integer> deleteWholeStreamHistory() {
|
public Single<Integer> deleteWholeStreamHistory() {
|
||||||
return Single.fromCallable(() -> streamHistoryTable.deleteAll())
|
return Single.fromCallable(streamHistoryTable::deleteAll)
|
||||||
.subscribeOn(Schedulers.io());
|
.subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +162,7 @@ public class HistoryRecordManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Integer> deleteWholeSearchHistory() {
|
public Single<Integer> deleteWholeSearchHistory() {
|
||||||
return Single.fromCallable(() -> searchHistoryTable.deleteAll())
|
return Single.fromCallable(searchHistoryTable::deleteAll)
|
||||||
.subscribeOn(Schedulers.io());
|
.subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,18 +182,41 @@ public class HistoryRecordManager {
|
||||||
// Stream State History
|
// Stream State History
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
public Maybe<StreamHistoryEntity> getStreamHistory(final StreamInfo info) {
|
||||||
public Maybe<StreamStateEntity> loadStreamState(final StreamInfo info) {
|
return Maybe.fromCallable(() -> {
|
||||||
return Maybe.fromCallable(() -> streamTable.upsert(new StreamEntity(info)))
|
final long streamId = streamTable.upsert(new StreamEntity(info));
|
||||||
.flatMap(streamId -> streamStateTable.getState(streamId).firstElement())
|
return streamHistoryTable.getLatestEntry(streamId);
|
||||||
.flatMap(states -> states.isEmpty() ? Maybe.empty() : Maybe.just(states.get(0)))
|
}).subscribeOn(Schedulers.io());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Maybe<StreamStateEntity> loadStreamState(final PlayQueueItem queueItem) {
|
||||||
|
return queueItem.getStream()
|
||||||
|
.map((info) -> streamTable.upsert(new StreamEntity(info)))
|
||||||
|
.flatMapPublisher(streamStateTable::getState)
|
||||||
|
.firstElement()
|
||||||
|
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
|
||||||
|
.filter(state -> state.isValid((int) queueItem.getDuration()))
|
||||||
.subscribeOn(Schedulers.io());
|
.subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Maybe<Long> saveStreamState(@NonNull final StreamInfo info, final long progressTime) {
|
public Maybe<StreamStateEntity> loadStreamState(final StreamInfo info) {
|
||||||
return Maybe.fromCallable(() -> database.runInTransaction(() -> {
|
return Single.fromCallable(() -> streamTable.upsert(new StreamEntity(info)))
|
||||||
|
.flatMapPublisher(streamStateTable::getState)
|
||||||
|
.firstElement()
|
||||||
|
.flatMap(list -> list.isEmpty() ? Maybe.empty() : Maybe.just(list.get(0)))
|
||||||
|
.filter(state -> state.isValid((int) info.getDuration()))
|
||||||
|
.subscribeOn(Schedulers.io());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Completable saveStreamState(@NonNull final StreamInfo info, final long progressTime) {
|
||||||
|
return Completable.fromAction(() -> database.runInTransaction(() -> {
|
||||||
final long streamId = streamTable.upsert(new StreamEntity(info));
|
final long streamId = streamTable.upsert(new StreamEntity(info));
|
||||||
return streamStateTable.upsert(new StreamStateEntity(streamId, progressTime));
|
final StreamStateEntity state = new StreamStateEntity(streamId, progressTime);
|
||||||
|
if (state.isValid((int) info.getDuration())) {
|
||||||
|
streamStateTable.upsert(state);
|
||||||
|
} else {
|
||||||
|
streamStateTable.deleteState(streamId);
|
||||||
|
}
|
||||||
})).subscribeOn(Schedulers.io());
|
})).subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,11 +310,11 @@ public class StatisticsPlaylistFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
headerPlayAllButton.setOnClickListener(view ->
|
headerPlayAllButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
||||||
headerPopupButton.setOnClickListener(view ->
|
headerPopupButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||||
headerBackgroundButton.setOnClickListener(view ->
|
headerBackgroundButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||||
sortButton.setOnClickListener(view -> toggleSortMode());
|
sortButton.setOnClickListener(view -> toggleSortMode());
|
||||||
|
|
||||||
hideLoading();
|
hideLoading();
|
||||||
|
@ -377,19 +377,19 @@ public class StatisticsPlaylistFragment
|
||||||
final int index = Math.max(itemListAdapter.getItemsList().indexOf(item), 0);
|
final int index = Math.max(itemListAdapter.getItemsList().indexOf(item), 0);
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem));
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(infoItem), false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(infoItem));
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(infoItem), false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
deleteEntry(index);
|
deleteEntry(index);
|
||||||
|
|
|
@ -319,11 +319,11 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
setVideoCount(itemListAdapter.getItemsList().size());
|
setVideoCount(itemListAdapter.getItemsList().size());
|
||||||
|
|
||||||
headerPlayAllButton.setOnClickListener(view ->
|
headerPlayAllButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue(), false));
|
||||||
headerPopupButton.setOnClickListener(view ->
|
headerPopupButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||||
headerBackgroundButton.setOnClickListener(view ->
|
headerBackgroundButton.setOnClickListener(view ->
|
||||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue()));
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||||
|
|
||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
|
@ -534,20 +534,20 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0:
|
case 0:
|
||||||
NavigationHelper.enqueueOnBackgroundPlayer(context,
|
NavigationHelper.enqueueOnBackgroundPlayer(context,
|
||||||
new SinglePlayQueue(infoItem));
|
new SinglePlayQueue(infoItem), false);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
NavigationHelper.enqueueOnPopupPlayer(activity, new
|
NavigationHelper.enqueueOnPopupPlayer(activity, new
|
||||||
SinglePlayQueue(infoItem));
|
SinglePlayQueue(infoItem), false);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index));
|
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index), true);
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
changeThumbnailUrl(item.thumbnailUrl);
|
changeThumbnailUrl(item.thumbnailUrl);
|
||||||
|
|
|
@ -150,6 +150,7 @@ public final class BackgroundPlayer extends Service {
|
||||||
lockManager.releaseWifiAndCpu();
|
lockManager.releaseWifiAndCpu();
|
||||||
}
|
}
|
||||||
if (basePlayerImpl != null) {
|
if (basePlayerImpl != null) {
|
||||||
|
basePlayerImpl.savePlaybackState();
|
||||||
basePlayerImpl.stopActivityBinding();
|
basePlayerImpl.stopActivityBinding();
|
||||||
basePlayerImpl.destroy();
|
basePlayerImpl.destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,11 @@ import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -145,6 +147,8 @@ public abstract class BasePlayer implements
|
||||||
@NonNull
|
@NonNull
|
||||||
public static final String APPEND_ONLY = "append_only";
|
public static final String APPEND_ONLY = "append_only";
|
||||||
@NonNull
|
@NonNull
|
||||||
|
public static final String RESUME_PLAYBACK = "resume_playback";
|
||||||
|
@NonNull
|
||||||
public static final String SELECT_ON_APPEND = "select_on_append";
|
public static final String SELECT_ON_APPEND = "select_on_append";
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -279,8 +283,23 @@ public abstract class BasePlayer implements
|
||||||
) {
|
) {
|
||||||
simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition());
|
simpleExoPlayer.seekTo(playQueue.getIndex(), queue.getItem().getRecoveryPosition());
|
||||||
return;
|
return;
|
||||||
|
} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false) && isPlaybackResumeEnabled()) {
|
||||||
|
final PlayQueueItem item = queue.getItem();
|
||||||
|
if (item != null && item.getRecoveryPosition() == PlayQueueItem.RECOVERY_UNSET && isPlaybackResumeEnabled()) {
|
||||||
|
final Disposable stateLoader = recordManager.loadStreamState(item)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doFinally(() -> initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
|
||||||
|
/*playOnInit=*/true))
|
||||||
|
.subscribe(
|
||||||
|
state -> queue.setRecovery(queue.getIndex(), state.getProgressTime()),
|
||||||
|
error -> {
|
||||||
|
if (DEBUG) error.printStackTrace();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
databaseUpdateReactor.add(stateLoader);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good to go...
|
// Good to go...
|
||||||
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
|
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
|
||||||
/*playOnInit=*/true);
|
/*playOnInit=*/true);
|
||||||
|
@ -615,6 +634,9 @@ public abstract class BasePlayer implements
|
||||||
break;
|
break;
|
||||||
case Player.STATE_ENDED: // 4
|
case Player.STATE_ENDED: // 4
|
||||||
changeState(STATE_COMPLETED);
|
changeState(STATE_COMPLETED);
|
||||||
|
if (currentMetadata != null) {
|
||||||
|
resetPlaybackState(currentMetadata.getMetadata());
|
||||||
|
}
|
||||||
isPrepared = false;
|
isPrepared = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -721,6 +743,7 @@ public abstract class BasePlayer implements
|
||||||
case DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
|
case DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
|
||||||
case DISCONTINUITY_REASON_INTERNAL:
|
case DISCONTINUITY_REASON_INTERNAL:
|
||||||
if (playQueue.getIndex() != newWindowIndex) {
|
if (playQueue.getIndex() != newWindowIndex) {
|
||||||
|
resetPlaybackState(playQueue.getItem());
|
||||||
playQueue.setIndex(newWindowIndex);
|
playQueue.setIndex(newWindowIndex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -750,6 +773,9 @@ public abstract class BasePlayer implements
|
||||||
@Override
|
@Override
|
||||||
public void onSeekProcessed() {
|
public void onSeekProcessed() {
|
||||||
if (DEBUG) Log.d(TAG, "ExoPlayer - onSeekProcessed() called");
|
if (DEBUG) Log.d(TAG, "ExoPlayer - onSeekProcessed() called");
|
||||||
|
if (isPrepared) {
|
||||||
|
savePlaybackState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Playback Listener
|
// Playback Listener
|
||||||
|
@ -1017,28 +1043,41 @@ public abstract class BasePlayer implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void savePlaybackState(final StreamInfo info, final long progress) {
|
private void savePlaybackState(final StreamInfo info, final long progress) {
|
||||||
if (info == null) return;
|
if (info == null) return;
|
||||||
|
if (DEBUG) Log.d(TAG, "savePlaybackState() called");
|
||||||
final Disposable stateSaver = recordManager.saveStreamState(info, progress)
|
final Disposable stateSaver = recordManager.saveStreamState(info, progress)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnError((e) -> {
|
||||||
|
if (DEBUG) e.printStackTrace();
|
||||||
|
})
|
||||||
.onErrorComplete()
|
.onErrorComplete()
|
||||||
.subscribe(
|
.subscribe();
|
||||||
ignored -> {/* successful */},
|
|
||||||
error -> Log.e(TAG, "savePlaybackState() failure: ", error)
|
|
||||||
);
|
|
||||||
databaseUpdateReactor.add(stateSaver);
|
databaseUpdateReactor.add(stateSaver);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void savePlaybackState() {
|
private void resetPlaybackState(final PlayQueueItem queueItem) {
|
||||||
|
if (queueItem == null) return;
|
||||||
|
final Disposable stateSaver = queueItem.getStream()
|
||||||
|
.flatMapCompletable(info -> recordManager.saveStreamState(info, 0))
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnError((e) -> {
|
||||||
|
if (DEBUG) e.printStackTrace();
|
||||||
|
})
|
||||||
|
.onErrorComplete()
|
||||||
|
.subscribe();
|
||||||
|
databaseUpdateReactor.add(stateSaver);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetPlaybackState(final StreamInfo info) {
|
||||||
|
savePlaybackState(info, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void savePlaybackState() {
|
||||||
if (simpleExoPlayer == null || currentMetadata == null) return;
|
if (simpleExoPlayer == null || currentMetadata == null) return;
|
||||||
final StreamInfo currentInfo = currentMetadata.getMetadata();
|
final StreamInfo currentInfo = currentMetadata.getMetadata();
|
||||||
|
|
||||||
if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD_MILLIS &&
|
|
||||||
simpleExoPlayer.getCurrentPosition() <
|
|
||||||
simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD_MILLIS) {
|
|
||||||
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeUpdateCurrentMetadata() {
|
private void maybeUpdateCurrentMetadata() {
|
||||||
if (simpleExoPlayer == null) return;
|
if (simpleExoPlayer == null) return;
|
||||||
|
@ -1225,4 +1264,10 @@ public abstract class BasePlayer implements
|
||||||
public boolean gotDestroyed() {
|
public boolean gotDestroyed() {
|
||||||
return simpleExoPlayer == null;
|
return simpleExoPlayer == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPlaybackResumeEnabled() {
|
||||||
|
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true)
|
||||||
|
&& prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -247,6 +247,12 @@ public final class MainVideoPlayer extends AppCompatActivity
|
||||||
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(newBase));
|
super.attachBaseContext(AudioServiceLeakFix.preventLeakOf(newBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
playerImpl.savePlaybackState();
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// State Saving
|
// State Saving
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -579,7 +585,8 @@ public final class MainVideoPlayer extends AppCompatActivity
|
||||||
this.getPlaybackSpeed(),
|
this.getPlaybackSpeed(),
|
||||||
this.getPlaybackPitch(),
|
this.getPlaybackPitch(),
|
||||||
this.getPlaybackSkipSilence(),
|
this.getPlaybackSkipSilence(),
|
||||||
this.getPlaybackQuality()
|
this.getPlaybackQuality(),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
|
|
||||||
|
@ -601,7 +608,8 @@ public final class MainVideoPlayer extends AppCompatActivity
|
||||||
this.getPlaybackSpeed(),
|
this.getPlaybackSpeed(),
|
||||||
this.getPlaybackPitch(),
|
this.getPlaybackPitch(),
|
||||||
this.getPlaybackSkipSilence(),
|
this.getPlaybackSkipSilence(),
|
||||||
this.getPlaybackQuality()
|
this.getPlaybackQuality(),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
|
|
||||||
|
|
|
@ -325,6 +325,7 @@ public final class PopupVideoPlayer extends Service {
|
||||||
isPopupClosing = true;
|
isPopupClosing = true;
|
||||||
|
|
||||||
if (playerImpl != null) {
|
if (playerImpl != null) {
|
||||||
|
playerImpl.savePlaybackState();
|
||||||
if (playerImpl.getRootView() != null) {
|
if (playerImpl.getRootView() != null) {
|
||||||
windowManager.removeView(playerImpl.getRootView());
|
windowManager.removeView(playerImpl.getRootView());
|
||||||
}
|
}
|
||||||
|
@ -565,7 +566,8 @@ public final class PopupVideoPlayer extends Service {
|
||||||
this.getPlaybackSpeed(),
|
this.getPlaybackSpeed(),
|
||||||
this.getPlaybackPitch(),
|
this.getPlaybackPitch(),
|
||||||
this.getPlaybackSkipSilence(),
|
this.getPlaybackSkipSilence(),
|
||||||
this.getPlaybackQuality()
|
this.getPlaybackQuality(),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
context.startActivity(intent);
|
context.startActivity(intent);
|
||||||
|
|
|
@ -188,7 +188,8 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||||
this.player.getPlaybackSpeed(),
|
this.player.getPlaybackSpeed(),
|
||||||
this.player.getPlaybackPitch(),
|
this.player.getPlaybackPitch(),
|
||||||
this.player.getPlaybackSkipSilence(),
|
this.player.getPlaybackSkipSilence(),
|
||||||
null
|
null,
|
||||||
|
false
|
||||||
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -543,6 +543,11 @@ public abstract class VideoPlayer extends BasePlayer
|
||||||
playbackSpeedTextView.setText(formatSpeed(getPlaybackSpeed()));
|
playbackSpeedTextView.setText(formatSpeed(getPlaybackSpeed()));
|
||||||
|
|
||||||
super.onPrepared(playWhenReady);
|
super.onPrepared(playWhenReady);
|
||||||
|
|
||||||
|
if (simpleExoPlayer.getCurrentPosition() != 0 && !isControlsVisible()) {
|
||||||
|
controlsVisibilityHandler.removeCallbacksAndMessages(null);
|
||||||
|
controlsVisibilityHandler.postDelayed(this::showControlsThenHide, DEFAULT_CONTROLS_DURATION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class CommentTextOnTouchListener implements View.OnTouchListener {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(info -> {
|
.subscribe(info -> {
|
||||||
PlayQueue playQueue = new SinglePlayQueue((StreamInfo) info, seconds*1000);
|
PlayQueue playQueue = new SinglePlayQueue((StreamInfo) info, seconds*1000);
|
||||||
NavigationHelper.playOnPopupPlayer(context, playQueue);
|
NavigationHelper.playOnPopupPlayer(context, playQueue, false);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,12 +69,14 @@ public class NavigationHelper {
|
||||||
public static Intent getPlayerIntent(@NonNull final Context context,
|
public static Intent getPlayerIntent(@NonNull final Context context,
|
||||||
@NonNull final Class targetClazz,
|
@NonNull final Class targetClazz,
|
||||||
@NonNull final PlayQueue playQueue,
|
@NonNull final PlayQueue playQueue,
|
||||||
@Nullable final String quality) {
|
@Nullable final String quality,
|
||||||
|
final boolean resumePlayback) {
|
||||||
Intent intent = new Intent(context, targetClazz);
|
Intent intent = new Intent(context, targetClazz);
|
||||||
|
|
||||||
final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class);
|
final String cacheKey = SerializedCache.getInstance().put(playQueue, PlayQueue.class);
|
||||||
if (cacheKey != null) intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey);
|
if (cacheKey != null) intent.putExtra(VideoPlayer.PLAY_QUEUE_KEY, cacheKey);
|
||||||
if (quality != null) intent.putExtra(VideoPlayer.PLAYBACK_QUALITY, quality);
|
if (quality != null) intent.putExtra(VideoPlayer.PLAYBACK_QUALITY, quality);
|
||||||
|
intent.putExtra(VideoPlayer.RESUME_PLAYBACK, resumePlayback);
|
||||||
|
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
@ -82,16 +84,18 @@ public class NavigationHelper {
|
||||||
@NonNull
|
@NonNull
|
||||||
public static Intent getPlayerIntent(@NonNull final Context context,
|
public static Intent getPlayerIntent(@NonNull final Context context,
|
||||||
@NonNull final Class targetClazz,
|
@NonNull final Class targetClazz,
|
||||||
@NonNull final PlayQueue playQueue) {
|
@NonNull final PlayQueue playQueue,
|
||||||
return getPlayerIntent(context, targetClazz, playQueue, null);
|
final boolean resumePlayback) {
|
||||||
|
return getPlayerIntent(context, targetClazz, playQueue, null, resumePlayback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static Intent getPlayerEnqueueIntent(@NonNull final Context context,
|
public static Intent getPlayerEnqueueIntent(@NonNull final Context context,
|
||||||
@NonNull final Class targetClazz,
|
@NonNull final Class targetClazz,
|
||||||
@NonNull final PlayQueue playQueue,
|
@NonNull final PlayQueue playQueue,
|
||||||
final boolean selectOnAppend) {
|
final boolean selectOnAppend,
|
||||||
return getPlayerIntent(context, targetClazz, playQueue)
|
final boolean resumePlayback) {
|
||||||
|
return getPlayerIntent(context, targetClazz, playQueue, resumePlayback)
|
||||||
.putExtra(BasePlayer.APPEND_ONLY, true)
|
.putExtra(BasePlayer.APPEND_ONLY, true)
|
||||||
.putExtra(BasePlayer.SELECT_ON_APPEND, selectOnAppend);
|
.putExtra(BasePlayer.SELECT_ON_APPEND, selectOnAppend);
|
||||||
}
|
}
|
||||||
|
@ -104,40 +108,41 @@ public class NavigationHelper {
|
||||||
final float playbackSpeed,
|
final float playbackSpeed,
|
||||||
final float playbackPitch,
|
final float playbackPitch,
|
||||||
final boolean playbackSkipSilence,
|
final boolean playbackSkipSilence,
|
||||||
@Nullable final String playbackQuality) {
|
@Nullable final String playbackQuality,
|
||||||
return getPlayerIntent(context, targetClazz, playQueue, playbackQuality)
|
final boolean resumePlayback) {
|
||||||
|
return getPlayerIntent(context, targetClazz, playQueue, playbackQuality, resumePlayback)
|
||||||
.putExtra(BasePlayer.REPEAT_MODE, repeatMode)
|
.putExtra(BasePlayer.REPEAT_MODE, repeatMode)
|
||||||
.putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed)
|
.putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed)
|
||||||
.putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch)
|
.putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch)
|
||||||
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence);
|
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void playOnMainPlayer(final Context context, final PlayQueue queue) {
|
public static void playOnMainPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||||
final Intent playerIntent = getPlayerIntent(context, MainVideoPlayer.class, queue);
|
final Intent playerIntent = getPlayerIntent(context, MainVideoPlayer.class, queue, resumePlayback);
|
||||||
playerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
playerIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
context.startActivity(playerIntent);
|
context.startActivity(playerIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void playOnPopupPlayer(final Context context, final PlayQueue queue) {
|
public static void playOnPopupPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||||
if (!PermissionHelper.isPopupEnabled(context)) {
|
if (!PermissionHelper.isPopupEnabled(context)) {
|
||||||
PermissionHelper.showPopupEnablementToast(context);
|
PermissionHelper.showPopupEnablementToast(context);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||||
startService(context, getPlayerIntent(context, PopupVideoPlayer.class, queue));
|
startService(context, getPlayerIntent(context, PopupVideoPlayer.class, queue, resumePlayback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue) {
|
public static void playOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||||
Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
|
||||||
startService(context, getPlayerIntent(context, BackgroundPlayer.class, queue));
|
startService(context, getPlayerIntent(context, BackgroundPlayer.class, queue, resumePlayback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue) {
|
public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||||
enqueueOnPopupPlayer(context, queue, false);
|
enqueueOnPopupPlayer(context, queue, false, resumePlayback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue, boolean selectOnAppend) {
|
public static void enqueueOnPopupPlayer(final Context context, final PlayQueue queue, boolean selectOnAppend, final boolean resumePlayback) {
|
||||||
if (!PermissionHelper.isPopupEnabled(context)) {
|
if (!PermissionHelper.isPopupEnabled(context)) {
|
||||||
PermissionHelper.showPopupEnablementToast(context);
|
PermissionHelper.showPopupEnablementToast(context);
|
||||||
return;
|
return;
|
||||||
|
@ -145,17 +150,17 @@ public class NavigationHelper {
|
||||||
|
|
||||||
Toast.makeText(context, R.string.popup_playing_append, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.popup_playing_append, Toast.LENGTH_SHORT).show();
|
||||||
startService(context,
|
startService(context,
|
||||||
getPlayerEnqueueIntent(context, PopupVideoPlayer.class, queue, selectOnAppend));
|
getPlayerEnqueueIntent(context, PopupVideoPlayer.class, queue, selectOnAppend, resumePlayback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue) {
|
public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, final boolean resumePlayback) {
|
||||||
enqueueOnBackgroundPlayer(context, queue, false);
|
enqueueOnBackgroundPlayer(context, queue, false, resumePlayback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, boolean selectOnAppend) {
|
public static void enqueueOnBackgroundPlayer(final Context context, final PlayQueue queue, boolean selectOnAppend, final boolean resumePlayback) {
|
||||||
Toast.makeText(context, R.string.background_player_append, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.background_player_append, Toast.LENGTH_SHORT).show();
|
||||||
startService(context,
|
startService(context,
|
||||||
getPlayerEnqueueIntent(context, BackgroundPlayer.class, queue, selectOnAppend));
|
getPlayerEnqueueIntent(context, BackgroundPlayer.class, queue, selectOnAppend, resumePlayback));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startService(@NonNull final Context context, @NonNull final Intent intent) {
|
public static void startService(@NonNull final Context context, @NonNull final Intent intent) {
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.schabi.newpipe.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.Transformation;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
public final class AnimatedProgressBar extends ProgressBar {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private ProgressBarAnimation animation = null;
|
||||||
|
|
||||||
|
public AnimatedProgressBar(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimatedProgressBar(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnimatedProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void setProgress(int progress) {
|
||||||
|
cancelAnimation();
|
||||||
|
animation = new ProgressBarAnimation(this, getProgress(), progress);
|
||||||
|
startAnimation(animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelAnimation() {
|
||||||
|
if (animation != null) {
|
||||||
|
animation.cancel();
|
||||||
|
animation = null;
|
||||||
|
}
|
||||||
|
clearAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProgressInternal(int progress) {
|
||||||
|
super.setProgress(progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProgressBarAnimation extends Animation {
|
||||||
|
|
||||||
|
private final AnimatedProgressBar progressBar;
|
||||||
|
private final float from;
|
||||||
|
private final float to;
|
||||||
|
|
||||||
|
ProgressBarAnimation(AnimatedProgressBar progressBar, float from, float to) {
|
||||||
|
super();
|
||||||
|
this.progressBar = progressBar;
|
||||||
|
this.from = from;
|
||||||
|
this.to = to;
|
||||||
|
setDuration(500);
|
||||||
|
setInterpolator(new AccelerateDecelerateInterpolator());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void applyTransformation(float interpolatedTime, Transformation t) {
|
||||||
|
super.applyTransformation(interpolatedTime, t);
|
||||||
|
float value = from + (to - from) * interpolatedTime;
|
||||||
|
progressBar.setProgressInternal((int) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/dark_ripple_color" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/progress">
|
||||||
|
<clip>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/dark_soundcloud_primary_color" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/light_ripple_color" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/progress">
|
||||||
|
<clip>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/light_soundcloud_primary_color" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/dark_ripple_color" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/progress">
|
||||||
|
<clip>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/dark_youtube_primary_color" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:id="@android:id/background">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/light_ripple_color" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item android:id="@android:id/progress">
|
||||||
|
<clip>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/light_youtube_primary_color" />
|
||||||
|
</shape>
|
||||||
|
</clip>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/video_item_detail"
|
android:id="@+id/video_item_detail"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
android:id="@+id/appbarlayout"
|
android:id="@+id/appbarlayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
app:elevation="0dp"
|
app:elevation="0dp"
|
||||||
app:layout_behavior="android.support.design.widget.FlingBehavior">
|
app:layout_behavior="android.support.design.widget.FlingBehavior">
|
||||||
|
@ -67,10 +68,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="#64000000"
|
android:background="#64000000"
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingLeft="30dp"
|
android:paddingLeft="30dp"
|
||||||
android:paddingRight="30dp"
|
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
|
android:paddingRight="30dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:text="@string/hold_to_append"
|
android:text="@string/hold_to_append"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
@ -84,17 +85,42 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|right"
|
android:layout_gravity="bottom|right"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:alpha=".6"
|
android:alpha=".6"
|
||||||
android:background="#23000000"
|
android:background="#23000000"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="2dp"
|
|
||||||
android:paddingLeft="6dp"
|
android:paddingLeft="6dp"
|
||||||
android:paddingRight="6dp"
|
|
||||||
android:paddingTop="2dp"
|
android:paddingTop="2dp"
|
||||||
|
android:paddingRight="6dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="12:38"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/detail_position_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|left"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:alpha=".6"
|
||||||
|
android:background="?colorPrimary"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="6dp"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:paddingRight="6dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
|
@ -107,6 +133,19 @@
|
||||||
|
|
||||||
</android.support.design.widget.CollapsingToolbarLayout>
|
</android.support.design.widget.CollapsingToolbarLayout>
|
||||||
|
|
||||||
|
<org.schabi.newpipe.views.AnimatedProgressBar
|
||||||
|
android:id="@+id/position_view"
|
||||||
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:layout_marginTop="-2dp"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:progressDrawable="?attr/progress_horizontal_drawable"
|
||||||
|
android:visibility="invisible"
|
||||||
|
tools:max="100"
|
||||||
|
tools:progress="40"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/detail_content_root_layout"
|
android:id="@+id/detail_content_root_layout"
|
||||||
|
@ -133,8 +172,8 @@
|
||||||
android:layout_marginRight="20dp"
|
android:layout_marginRight="20dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:paddingTop="12dp"
|
android:paddingTop="12dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
|
@ -179,9 +218,9 @@
|
||||||
android:id="@+id/detail_content_root_hiding"
|
android:id="@+id/detail_content_root_hiding"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:layout_below="@+id/detail_title_root_layout"
|
android:layout_below="@+id/detail_title_root_layout"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
@ -191,8 +230,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="55dp"
|
android:layout_height="55dp"
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
@ -201,8 +240,8 @@
|
||||||
android:id="@+id/detail_uploader_root_layout"
|
android:id="@+id/detail_uploader_root_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_toLeftOf="@id/details_panel"
|
|
||||||
android:layout_toStartOf="@id/details_panel"
|
android:layout_toStartOf="@id/details_panel"
|
||||||
|
android:layout_toLeftOf="@id/details_panel"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -261,8 +300,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="6dp"
|
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||||
|
@ -354,8 +393,8 @@
|
||||||
android:drawableTop="?attr/ic_playlist_add"
|
android:drawableTop="?attr/ic_playlist_add"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_add_to_playlist_title"
|
android:text="@string/controls_add_to_playlist_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -371,8 +410,8 @@
|
||||||
android:drawableTop="?attr/audio"
|
android:drawableTop="?attr/audio"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_background_title"
|
android:text="@string/controls_background_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -388,8 +427,8 @@
|
||||||
android:drawableTop="?attr/popup"
|
android:drawableTop="?attr/popup"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_popup_title"
|
android:text="@string/controls_popup_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -405,8 +444,8 @@
|
||||||
android:drawableTop="?attr/download"
|
android:drawableTop="?attr/download"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/download"
|
android:text="@string/download"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -444,10 +483,10 @@
|
||||||
android:id="@+id/detail_description_view"
|
android:id="@+id/detail_description_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
android:id="@+id/appbarlayout"
|
android:id="@+id/appbarlayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
app:elevation="0dp"
|
app:elevation="0dp"
|
||||||
app:layout_behavior="android.support.design.widget.FlingBehavior">
|
app:layout_behavior="android.support.design.widget.FlingBehavior">
|
||||||
|
@ -65,10 +66,10 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="#64000000"
|
android:background="#64000000"
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingLeft="30dp"
|
android:paddingLeft="30dp"
|
||||||
android:paddingRight="30dp"
|
|
||||||
android:paddingTop="10dp"
|
android:paddingTop="10dp"
|
||||||
|
android:paddingRight="30dp"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:text="@string/hold_to_append"
|
android:text="@string/hold_to_append"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
|
@ -82,17 +83,17 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|right"
|
android:layout_gravity="bottom|right"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:alpha=".6"
|
android:alpha=".6"
|
||||||
android:background="#23000000"
|
android:background="#23000000"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="2dp"
|
|
||||||
android:paddingLeft="6dp"
|
android:paddingLeft="6dp"
|
||||||
android:paddingRight="6dp"
|
|
||||||
android:paddingTop="2dp"
|
android:paddingTop="2dp"
|
||||||
|
android:paddingRight="6dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="12sp"
|
android:textSize="12sp"
|
||||||
|
@ -101,10 +102,48 @@
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
tools:text="12:38"
|
tools:text="12:38"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/detail_position_view"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|left"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:alpha=".6"
|
||||||
|
android:background="?colorPrimary"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="6dp"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:paddingRight="6dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:text="12:38"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
</android.support.design.widget.CollapsingToolbarLayout>
|
</android.support.design.widget.CollapsingToolbarLayout>
|
||||||
|
|
||||||
|
<org.schabi.newpipe.views.AnimatedProgressBar
|
||||||
|
android:id="@+id/position_view"
|
||||||
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="4dp"
|
||||||
|
android:layout_marginTop="-2dp"
|
||||||
|
android:progressDrawable="?attr/progress_horizontal_drawable"
|
||||||
|
android:visibility="invisible"
|
||||||
|
tools:max="100"
|
||||||
|
tools:progress="40"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/detail_content_root_layout"
|
android:id="@+id/detail_content_root_layout"
|
||||||
|
@ -131,8 +170,8 @@
|
||||||
android:layout_marginRight="20dp"
|
android:layout_marginRight="20dp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:paddingTop="12dp"
|
android:paddingTop="12dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
|
@ -177,9 +216,9 @@
|
||||||
android:id="@+id/detail_content_root_hiding"
|
android:id="@+id/detail_content_root_hiding"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:layout_below="@+id/detail_title_root_layout"
|
android:layout_below="@+id/detail_title_root_layout"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="10dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
@ -189,8 +228,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="55dp"
|
android:layout_height="55dp"
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
@ -199,8 +238,8 @@
|
||||||
android:id="@+id/detail_uploader_root_layout"
|
android:id="@+id/detail_uploader_root_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_toLeftOf="@id/details_panel"
|
|
||||||
android:layout_toStartOf="@id/details_panel"
|
android:layout_toStartOf="@id/details_panel"
|
||||||
|
android:layout_toLeftOf="@id/details_panel"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -259,8 +298,8 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="6dp"
|
|
||||||
android:layout_marginTop="6dp"
|
android:layout_marginTop="6dp"
|
||||||
|
android:layout_marginBottom="6dp"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||||
|
@ -352,8 +391,8 @@
|
||||||
android:drawableTop="?attr/ic_playlist_add"
|
android:drawableTop="?attr/ic_playlist_add"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_add_to_playlist_title"
|
android:text="@string/controls_add_to_playlist_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -369,8 +408,8 @@
|
||||||
android:drawableTop="?attr/audio"
|
android:drawableTop="?attr/audio"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_background_title"
|
android:text="@string/controls_background_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -386,8 +425,8 @@
|
||||||
android:drawableTop="?attr/popup"
|
android:drawableTop="?attr/popup"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/controls_popup_title"
|
android:text="@string/controls_popup_title"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -403,8 +442,8 @@
|
||||||
android:drawableTop="?attr/download"
|
android:drawableTop="?attr/download"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:paddingBottom="6dp"
|
|
||||||
android:paddingTop="6dp"
|
android:paddingTop="6dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
android:text="@string/download"
|
android:text="@string/download"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
@ -442,10 +481,10 @@
|
||||||
android:id="@+id/detail_description_view"
|
android:id="@+id/detail_description_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:layout_marginLeft="12dp"
|
android:layout_marginLeft="12dp"
|
||||||
android:layout_marginRight="12dp"
|
|
||||||
android:layout_marginTop="3dp"
|
android:layout_marginTop="3dp"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||||
|
|
|
@ -167,7 +167,10 @@
|
||||||
<string name="fragment_whats_new">Что нового</string>
|
<string name="fragment_whats_new">Что нового</string>
|
||||||
<string name="enable_search_history_title">История поиска</string>
|
<string name="enable_search_history_title">История поиска</string>
|
||||||
<string name="enable_search_history_summary">Хранить запросы поиска локально</string>
|
<string name="enable_search_history_summary">Хранить запросы поиска локально</string>
|
||||||
<string name="enable_watch_history_title">История и кэш</string>
|
<string name="enable_watch_history_title">История просмотров</string>
|
||||||
|
<string name="enable_playback_resume_title">Продолжать воспроизведение</string>
|
||||||
|
<string name="enable_playback_resume_summary">Восстанавливать с последней позиции</string>
|
||||||
|
<string name="settings_category_clear_data_title">Очистить данные</string>
|
||||||
<string name="enable_watch_history_summary">Запоминать воспроизведённые потоки</string>
|
<string name="enable_watch_history_summary">Запоминать воспроизведённые потоки</string>
|
||||||
<string name="resume_on_audio_focus_gain_title">Возобновить при фокусе</string>
|
<string name="resume_on_audio_focus_gain_title">Возобновить при фокусе</string>
|
||||||
<string name="resume_on_audio_focus_gain_summary">Возобновлять воспроизведение после перерывов (например, телефонных звонков)</string>
|
<string name="resume_on_audio_focus_gain_summary">Возобновлять воспроизведение после перерывов (например, телефонных звонков)</string>
|
||||||
|
|
|
@ -153,7 +153,10 @@
|
||||||
<string name="show_search_suggestions_summary">Показувати пропозиції під час пошуку</string>
|
<string name="show_search_suggestions_summary">Показувати пропозиції під час пошуку</string>
|
||||||
<string name="enable_search_history_title">Історія пошуків</string>
|
<string name="enable_search_history_title">Історія пошуків</string>
|
||||||
<string name="enable_search_history_summary">Зберігати пошукові запити локально</string>
|
<string name="enable_search_history_summary">Зберігати пошукові запити локально</string>
|
||||||
<string name="enable_watch_history_title">Історія та кеш</string>
|
<string name="enable_watch_history_title">Історія переглядiв</string>
|
||||||
|
<string name="enable_playback_resume_title">Продовживати перегляд</string>
|
||||||
|
<string name="enable_playback_resume_summary">Відновлювати останню позицію</string>
|
||||||
|
<string name="settings_category_clear_data_title">Очистити дані</string>
|
||||||
<string name="enable_watch_history_summary">Вести облік перегляду відеозаписів</string>
|
<string name="enable_watch_history_summary">Вести облік перегляду відеозаписів</string>
|
||||||
<string name="resume_on_audio_focus_gain_title">Відновити відтворення</string>
|
<string name="resume_on_audio_focus_gain_title">Відновити відтворення</string>
|
||||||
<string name="resume_on_audio_focus_gain_summary">Продовжувати відтворення опісля переривання (наприклад телефонного дзвінка)</string>
|
<string name="resume_on_audio_focus_gain_summary">Продовжувати відтворення опісля переривання (наприклад телефонного дзвінка)</string>
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<attr name="ic_delete" format="reference"/>
|
<attr name="ic_delete" format="reference"/>
|
||||||
<attr name="ic_settings_update" format="reference"/>
|
<attr name="ic_settings_update" format="reference"/>
|
||||||
|
|
||||||
|
<attr name="progress_horizontal_drawable" format="reference"/>
|
||||||
<!-- Can't refer to colors directly in drawable's xml-->
|
<!-- Can't refer to colors directly in drawable's xml-->
|
||||||
<attr name="toolbar_shadow_drawable" format="reference"/>
|
<attr name="toolbar_shadow_drawable" format="reference"/>
|
||||||
<attr name="selector_drawable" format="reference"/>
|
<attr name="selector_drawable" format="reference"/>
|
||||||
|
|
|
@ -150,6 +150,7 @@
|
||||||
<string name="enable_search_history_key" translatable="false">enable_search_history</string>
|
<string name="enable_search_history_key" translatable="false">enable_search_history</string>
|
||||||
<string name="enable_watch_history_key" translatable="false">enable_watch_history</string>
|
<string name="enable_watch_history_key" translatable="false">enable_watch_history</string>
|
||||||
<string name="main_page_content_key" translatable="false">main_page_content</string>
|
<string name="main_page_content_key" translatable="false">main_page_content</string>
|
||||||
|
<string name="enable_playback_resume_key" translatable="false">enable_playback_resume</string>
|
||||||
|
|
||||||
<string name="import_data">import_data</string>
|
<string name="import_data">import_data</string>
|
||||||
<string name="export_data">export_data</string>
|
<string name="export_data">export_data</string>
|
||||||
|
|
|
@ -95,7 +95,10 @@
|
||||||
<string name="show_search_suggestions_summary">Show suggestions when searching</string>
|
<string name="show_search_suggestions_summary">Show suggestions when searching</string>
|
||||||
<string name="enable_search_history_title">Search history</string>
|
<string name="enable_search_history_title">Search history</string>
|
||||||
<string name="enable_search_history_summary">Store search queries locally</string>
|
<string name="enable_search_history_summary">Store search queries locally</string>
|
||||||
<string name="enable_watch_history_title">History & Cache</string>
|
<string name="enable_watch_history_title">Watch history</string>
|
||||||
|
<string name="enable_playback_resume_title">Resume playback</string>
|
||||||
|
<string name="enable_playback_resume_summary">Restore last playback position</string>
|
||||||
|
<string name="settings_category_clear_data_title">Clear data</string>
|
||||||
<string name="enable_watch_history_summary">Keep track of watched videos</string>
|
<string name="enable_watch_history_summary">Keep track of watched videos</string>
|
||||||
<string name="resume_on_audio_focus_gain_title">Resume on focus gain</string>
|
<string name="resume_on_audio_focus_gain_title">Resume on focus gain</string>
|
||||||
<string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phone calls)</string>
|
<string name="resume_on_audio_focus_gain_summary">Continue playing after interruptions (e.g. phone calls)</string>
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
<item name="toolbar_shadow_drawable">@drawable/toolbar_shadow_light</item>
|
<item name="toolbar_shadow_drawable">@drawable/toolbar_shadow_light</item>
|
||||||
<item name="selector_drawable">@drawable/light_selector</item>
|
<item name="selector_drawable">@drawable/light_selector</item>
|
||||||
<item name="colorControlHighlight">@color/light_ripple_color</item>
|
<item name="colorControlHighlight">@color/light_ripple_color</item>
|
||||||
|
<item name="progress_horizontal_drawable">@drawable/progress_youtube_horizontal_light</item>
|
||||||
|
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -128,6 +129,7 @@
|
||||||
<item name="toolbar_shadow_drawable">@drawable/toolbar_shadow_dark</item>
|
<item name="toolbar_shadow_drawable">@drawable/toolbar_shadow_dark</item>
|
||||||
<item name="selector_drawable">@drawable/dark_selector</item>
|
<item name="selector_drawable">@drawable/dark_selector</item>
|
||||||
<item name="colorControlHighlight">@color/dark_ripple_color</item>
|
<item name="colorControlHighlight">@color/dark_ripple_color</item>
|
||||||
|
<item name="progress_horizontal_drawable">@drawable/progress_youtube_horizontal_dark</item>
|
||||||
|
|
||||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -15,18 +15,21 @@
|
||||||
<item name="colorPrimary">@color/light_soundcloud_primary_color</item>
|
<item name="colorPrimary">@color/light_soundcloud_primary_color</item>
|
||||||
<item name="colorPrimaryDark">@color/light_soundcloud_dark_color</item>
|
<item name="colorPrimaryDark">@color/light_soundcloud_dark_color</item>
|
||||||
<item name="colorAccent">@color/light_soundcloud_accent_color</item>
|
<item name="colorAccent">@color/light_soundcloud_accent_color</item>
|
||||||
|
<item name="progress_horizontal_drawable">@drawable/progress_soundcloud_horizontal_light</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="DarkTheme.SoundCloud" parent="DarkTheme.Switchable">
|
<style name="DarkTheme.SoundCloud" parent="DarkTheme.Switchable">
|
||||||
<item name="colorPrimary">@color/dark_soundcloud_primary_color</item>
|
<item name="colorPrimary">@color/dark_soundcloud_primary_color</item>
|
||||||
<item name="colorPrimaryDark">@color/dark_soundcloud_dark_color</item>
|
<item name="colorPrimaryDark">@color/dark_soundcloud_dark_color</item>
|
||||||
<item name="colorAccent">@color/dark_soundcloud_accent_color</item>
|
<item name="colorAccent">@color/dark_soundcloud_accent_color</item>
|
||||||
|
<item name="progress_horizontal_drawable">@drawable/progress_soundcloud_horizontal_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="BlackTheme.SoundCloud" parent="BlackTheme.Switchable">
|
<style name="BlackTheme.SoundCloud" parent="BlackTheme.Switchable">
|
||||||
<item name="colorPrimary">@color/dark_soundcloud_primary_color</item>
|
<item name="colorPrimary">@color/dark_soundcloud_primary_color</item>
|
||||||
<item name="colorPrimaryDark">@color/dark_soundcloud_dark_color</item>
|
<item name="colorPrimaryDark">@color/dark_soundcloud_dark_color</item>
|
||||||
<item name="colorAccent">@color/dark_soundcloud_accent_color</item>
|
<item name="colorAccent">@color/dark_soundcloud_accent_color</item>
|
||||||
|
<item name="progress_horizontal_drawable">@drawable/progress_soundcloud_horizontal_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Media.ccc -->
|
<!-- Media.ccc -->
|
||||||
|
|
|
@ -1,40 +1,54 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<PreferenceScreen
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:key="general_preferences"
|
android:key="general_preferences"
|
||||||
android:title="@string/settings_category_history_title">
|
android:title="@string/settings_category_history_title">
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="@string/enable_watch_history_key"
|
android:key="@string/enable_watch_history_key"
|
||||||
android:summary="@string/enable_watch_history_summary"
|
android:summary="@string/enable_watch_history_summary"
|
||||||
android:title="@string/enable_watch_history_title"/>
|
android:title="@string/enable_watch_history_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:dependency="@string/enable_watch_history_key"
|
||||||
|
android:key="@string/enable_playback_resume_key"
|
||||||
|
android:summary="@string/enable_playback_resume_summary"
|
||||||
|
android:title="@string/enable_playback_resume_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
android:key="@string/enable_search_history_key"
|
android:key="@string/enable_search_history_key"
|
||||||
android:summary="@string/enable_search_history_summary"
|
android:summary="@string/enable_search_history_summary"
|
||||||
android:title="@string/enable_search_history_title"/>
|
android:title="@string/enable_search_history_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<PreferenceCategory
|
||||||
|
android:layout="@layout/settings_category_header_layout"
|
||||||
|
android:title="@string/settings_category_clear_data_title"
|
||||||
|
app:iconSpaceReserved="false">
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
android:key="@string/metadata_cache_wipe_key"
|
android:key="@string/metadata_cache_wipe_key"
|
||||||
android:summary="@string/metadata_cache_wipe_summary"
|
android:summary="@string/metadata_cache_wipe_summary"
|
||||||
android:title="@string/metadata_cache_wipe_title"/>
|
android:title="@string/metadata_cache_wipe_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
android:key="@string/clear_views_history_key"
|
android:key="@string/clear_views_history_key"
|
||||||
|
android:summary="@string/clear_views_history_summary"
|
||||||
android:title="@string/clear_views_history_title"
|
android:title="@string/clear_views_history_title"
|
||||||
android:summary="@string/clear_views_history_summary"/>
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:iconSpaceReserved="false"
|
|
||||||
android:key="@string/clear_search_history_key"
|
android:key="@string/clear_search_history_key"
|
||||||
|
android:summary="@string/clear_search_history_summary"
|
||||||
android:title="@string/clear_search_history_title"
|
android:title="@string/clear_search_history_title"
|
||||||
android:summary="@string/clear_search_history_summary"/>
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
Loading…
Reference in a new issue