Merge pull request #8180 from Trust04zh/fix-4053-8176

Make UI behavior for playback information display more consistent
This commit is contained in:
Stypox 2023-02-26 13:22:13 +01:00 committed by GitHub
commit 097c2368f4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 98 additions and 63 deletions

View file

@ -7,7 +7,7 @@ import static org.schabi.newpipe.ktx.ViewUtils.animate;
import static org.schabi.newpipe.ktx.ViewUtils.animateRotation; import static org.schabi.newpipe.ktx.ViewUtils.animateRotation;
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked; import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired; import static org.schabi.newpipe.player.helper.PlayerHelper.isClearingQueueConfirmationRequired;
import static org.schabi.newpipe.player.playqueue.PlayQueueItem.RECOVERY_UNSET; import static org.schabi.newpipe.util.DependentPreferenceHelper.getResumePlaybackEnabled;
import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView; import static org.schabi.newpipe.util.ExtractorHelper.showMetaInfoInTextView;
import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams; import static org.schabi.newpipe.util.ListHelper.getUrlAndNonTorrentStreams;
import static org.schabi.newpipe.util.NavigationHelper.openPlayQueue; import static org.schabi.newpipe.util.NavigationHelper.openPlayQueue;
@ -1448,8 +1448,8 @@ public final class VideoDetailFragment
animate(binding.detailThumbnailPlayButton, false, 50); animate(binding.detailThumbnailPlayButton, false, 50);
animate(binding.detailDurationView, false, 100); animate(binding.detailDurationView, false, 100);
animate(binding.detailPositionView, false, 100); binding.detailPositionView.setVisibility(View.GONE);
animate(binding.positionView, false, 50); binding.positionView.setVisibility(View.GONE);
binding.detailVideoTitleView.setText(title); binding.detailVideoTitleView.setText(title);
binding.detailVideoTitleView.setMaxLines(1); binding.detailVideoTitleView.setMaxLines(1);
@ -1566,7 +1566,7 @@ public final class VideoDetailFragment
binding.detailToggleSecondaryControlsView.setVisibility(View.VISIBLE); binding.detailToggleSecondaryControlsView.setVisibility(View.VISIBLE);
binding.detailSecondaryControlPanel.setVisibility(View.GONE); binding.detailSecondaryControlPanel.setVisibility(View.GONE);
updateProgressInfo(info); checkUpdateProgressInfo(info);
initThumbnailViews(info); initThumbnailViews(info);
showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView, showMetaInfoInTextView(info.getMetaInfo(), binding.detailMetaInfoTextView,
binding.detailMetaInfoSeparator, disposables); binding.detailMetaInfoSeparator, disposables);
@ -1665,67 +1665,43 @@ public final class VideoDetailFragment
// Stream Results // Stream Results
//////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////*/
private void updateProgressInfo(@NonNull final StreamInfo info) { private void checkUpdateProgressInfo(@NonNull final StreamInfo info) {
if (positionSubscriber != null) { if (positionSubscriber != null) {
positionSubscriber.dispose(); positionSubscriber.dispose();
} }
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity); if (!getResumePlaybackEnabled(activity)) {
final boolean playbackResumeEnabled = prefs binding.positionView.setVisibility(View.GONE);
.getBoolean(activity.getString(R.string.enable_watch_history_key), true)
&& prefs.getBoolean(activity.getString(R.string.enable_playback_resume_key), true);
final boolean showPlaybackPosition = prefs.getBoolean(
activity.getString(R.string.enable_playback_state_lists_key), true);
if (!playbackResumeEnabled) {
if (playQueue == null || playQueue.getStreams().isEmpty()
|| playQueue.getItem().getRecoveryPosition() == RECOVERY_UNSET
|| !showPlaybackPosition) {
binding.positionView.setVisibility(View.INVISIBLE);
binding.detailPositionView.setVisibility(View.GONE); binding.detailPositionView.setVisibility(View.GONE);
// TODO: Remove this check when separation of concerns is done.
// (live streams weren't getting updated because they are mixed)
if (!StreamTypeUtil.isLiveStream(info.getStreamType())) {
return;
}
} else {
// Show saved position from backStack if user allows it
showPlaybackProgress(playQueue.getItem().getRecoveryPosition(),
playQueue.getItem().getDuration() * 1000);
animate(binding.positionView, true, 500);
animate(binding.detailPositionView, true, 500);
}
return; return;
} }
final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext()); final HistoryRecordManager recordManager = new HistoryRecordManager(requireContext());
// TODO: Separate concerns when updating database data.
// (move the updating part to when the loading happens)
positionSubscriber = recordManager.loadStreamState(info) positionSubscriber = recordManager.loadStreamState(info)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.onErrorComplete() .onErrorComplete()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(state -> { .subscribe(state -> {
showPlaybackProgress(state.getProgressMillis(), info.getDuration() * 1000); updatePlaybackProgress(
animate(binding.positionView, true, 500); state.getProgressMillis(), info.getDuration() * 1000);
animate(binding.detailPositionView, true, 500);
}, e -> { }, e -> {
if (DEBUG) { // impossible since the onErrorComplete()
e.printStackTrace();
}
}, () -> { }, () -> {
binding.positionView.setVisibility(View.GONE); binding.positionView.setVisibility(View.GONE);
binding.detailPositionView.setVisibility(View.GONE); binding.detailPositionView.setVisibility(View.GONE);
}); });
} }
private void showPlaybackProgress(final long progress, final long duration) { private void updatePlaybackProgress(final long progress, final long duration) {
if (!getResumePlaybackEnabled(activity)) {
return;
}
final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress); final int progressSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(progress);
final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration); final int durationSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(duration);
// If the old and the new progress values have a big difference then use // If the old and the new progress values have a big difference then use animation.
// animation. Otherwise don't because it affects CPU // Otherwise don't because it affects CPU
final boolean shouldAnimate = Math.abs(binding.positionView.getProgress() final int progressDifference = Math.abs(binding.positionView.getProgress()
- progressSeconds) > 2; - progressSeconds);
binding.positionView.setMax(durationSeconds); binding.positionView.setMax(durationSeconds);
if (shouldAnimate) { if (progressDifference > 2) {
binding.positionView.setProgressAnimated(progressSeconds); binding.positionView.setProgressAnimated(progressSeconds);
} else { } else {
binding.positionView.setProgress(progressSeconds); binding.positionView.setProgress(progressSeconds);
@ -1820,7 +1796,7 @@ public final class VideoDetailFragment
} }
if (player.getPlayQueue().getItem().getUrl().equals(url)) { if (player.getPlayQueue().getItem().getUrl().equals(url)) {
showPlaybackProgress(currentProgress, duration); updatePlaybackProgress(currentProgress, duration);
} }
} }

View file

@ -14,6 +14,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.ktx.ViewUtils;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.StreamTypeUtil; import org.schabi.newpipe.util.StreamTypeUtil;
@ -60,8 +61,12 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
R.color.duration_background_color)); R.color.duration_background_color));
itemDurationView.setVisibility(View.VISIBLE); itemDurationView.setVisibility(View.VISIBLE);
final StreamStateEntity state2 = historyRecordManager.loadStreamState(infoItem) StreamStateEntity state2 = null;
if (DependentPreferenceHelper
.getPositionsInListsEnabled(itemProgressView.getContext())) {
state2 = historyRecordManager.loadStreamState(infoItem)
.blockingGet()[0]; .blockingGet()[0];
}
if (state2 != null) { if (state2 != null) {
itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setVisibility(View.VISIBLE);
itemProgressView.setMax((int) item.getDuration()); itemProgressView.setMax((int) item.getDuration());
@ -111,9 +116,12 @@ public class StreamMiniInfoItemHolder extends InfoItemHolder {
final HistoryRecordManager historyRecordManager) { final HistoryRecordManager historyRecordManager) {
final StreamInfoItem item = (StreamInfoItem) infoItem; final StreamInfoItem item = (StreamInfoItem) infoItem;
final StreamStateEntity state = historyRecordManager StreamStateEntity state = null;
if (DependentPreferenceHelper.getPositionsInListsEnabled(itemProgressView.getContext())) {
state = historyRecordManager
.loadStreamState(infoItem) .loadStreamState(infoItem)
.blockingGet()[0]; .blockingGet()[0];
}
if (state != null && item.getDuration() > 0 if (state != null && item.getDuration() > 0
&& !StreamTypeUtil.isLiveStream(item.getStreamType())) { && !StreamTypeUtil.isLiveStream(item.getStreamType())) {
itemProgressView.setMax((int) item.getDuration()); itemProgressView.setMax((int) item.getDuration());

View file

@ -14,6 +14,7 @@ import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.ktx.ViewUtils;
import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
@ -68,7 +69,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
R.color.duration_background_color)); R.color.duration_background_color));
itemDurationView.setVisibility(View.VISIBLE); itemDurationView.setVisibility(View.VISIBLE);
if (item.getProgressMillis() > 0) { if (DependentPreferenceHelper.getPositionsInListsEnabled(itemProgressView.getContext())
&& item.getProgressMillis() > 0) {
itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setVisibility(View.VISIBLE);
itemProgressView.setMax((int) item.getStreamEntity().getDuration()); itemProgressView.setMax((int) item.getStreamEntity().getDuration());
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
@ -109,7 +111,8 @@ public class LocalPlaylistStreamItemHolder extends LocalItemHolder {
} }
final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem; final PlaylistStreamEntry item = (PlaylistStreamEntry) localItem;
if (item.getProgressMillis() > 0 && item.getStreamEntity().getDuration() > 0) { if (DependentPreferenceHelper.getPositionsInListsEnabled(itemProgressView.getContext())
&& item.getProgressMillis() > 0 && item.getStreamEntity().getDuration() > 0) {
itemProgressView.setMax((int) item.getStreamEntity().getDuration()); itemProgressView.setMax((int) item.getStreamEntity().getDuration());
if (itemProgressView.getVisibility() == View.VISIBLE) { if (itemProgressView.getVisibility() == View.VISIBLE) {
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS

View file

@ -14,6 +14,7 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
import org.schabi.newpipe.ktx.ViewUtils; import org.schabi.newpipe.ktx.ViewUtils;
import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.LocalItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.PicassoHelper; import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.ServiceHelper;
@ -97,7 +98,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
R.color.duration_background_color)); R.color.duration_background_color));
itemDurationView.setVisibility(View.VISIBLE); itemDurationView.setVisibility(View.VISIBLE);
if (item.getProgressMillis() > 0) { if (DependentPreferenceHelper.getPositionsInListsEnabled(itemProgressView.getContext())
&& item.getProgressMillis() > 0) {
itemProgressView.setVisibility(View.VISIBLE); itemProgressView.setVisibility(View.VISIBLE);
itemProgressView.setMax((int) item.getStreamEntity().getDuration()); itemProgressView.setMax((int) item.getStreamEntity().getDuration());
itemProgressView.setProgress((int) TimeUnit.MILLISECONDS itemProgressView.setProgress((int) TimeUnit.MILLISECONDS
@ -141,7 +143,8 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder {
} }
final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem; final StreamStatisticsEntry item = (StreamStatisticsEntry) localItem;
if (item.getProgressMillis() > 0 && item.getStreamEntity().getDuration() > 0) { if (DependentPreferenceHelper.getPositionsInListsEnabled(itemProgressView.getContext())
&& item.getProgressMillis() > 0 && item.getStreamEntity().getDuration() > 0) {
itemProgressView.setMax((int) item.getStreamEntity().getDuration()); itemProgressView.setMax((int) item.getStreamEntity().getDuration());
if (itemProgressView.getVisibility() == View.VISIBLE) { if (itemProgressView.getVisibility() == View.VISIBLE) {
itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS itemProgressView.setProgressAnimated((int) TimeUnit.MILLISECONDS

View file

@ -29,7 +29,6 @@ import static com.google.android.exoplayer2.Player.REPEAT_MODE_ONE;
import static com.google.android.exoplayer2.Player.RepeatMode; import static com.google.android.exoplayer2.Player.RepeatMode;
import static org.schabi.newpipe.extractor.ServiceList.YouTube; import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty; import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import static org.schabi.newpipe.player.helper.PlayerHelper.isPlaybackResumeEnabled;
import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode; import static org.schabi.newpipe.player.helper.PlayerHelper.nextRepeatMode;
import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs; import static org.schabi.newpipe.player.helper.PlayerHelper.retrievePlaybackParametersFromPrefs;
import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences; import static org.schabi.newpipe.player.helper.PlayerHelper.retrieveSeekDurationFromPreferences;
@ -115,6 +114,7 @@ import org.schabi.newpipe.player.ui.PlayerUi;
import org.schabi.newpipe.player.ui.PlayerUiList; import org.schabi.newpipe.player.ui.PlayerUiList;
import org.schabi.newpipe.player.ui.PopupPlayerUi; import org.schabi.newpipe.player.ui.PopupPlayerUi;
import org.schabi.newpipe.player.ui.VideoPlayerUi; import org.schabi.newpipe.player.ui.VideoPlayerUi;
import org.schabi.newpipe.util.DependentPreferenceHelper;
import org.schabi.newpipe.util.DeviceUtils; import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
@ -391,7 +391,7 @@ public final class Player implements PlaybackListener, Listener {
simpleExoPlayer.setPlayWhenReady(playWhenReady); simpleExoPlayer.setPlayWhenReady(playWhenReady);
} else if (intent.getBooleanExtra(RESUME_PLAYBACK, false) } else if (intent.getBooleanExtra(RESUME_PLAYBACK, false)
&& isPlaybackResumeEnabled(this) && DependentPreferenceHelper.getResumePlaybackEnabled(context)
&& !samePlayQueue && !samePlayQueue
&& !newQueue.isEmpty() && !newQueue.isEmpty()
&& newQueue.getItem() != null && newQueue.getItem() != null

View file

@ -429,13 +429,6 @@ public final class PlayerHelper {
// Utils used by player // Utils used by player
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
public static boolean isPlaybackResumeEnabled(final Player player) {
return player.getPrefs().getBoolean(
player.getContext().getString(R.string.enable_watch_history_key), true)
&& player.getPrefs().getBoolean(
player.getContext().getString(R.string.enable_playback_resume_key), true);
}
@RepeatMode @RepeatMode
public static int nextRepeatMode(@RepeatMode final int repeatMode) { public static int nextRepeatMode(@RepeatMode final int repeatMode) {
switch (repeatMode) { switch (repeatMode) {

View file

@ -0,0 +1,51 @@
package org.schabi.newpipe.util;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R;
/**
* For preferences with dependencies and multiple use case,
* this class can be used to reduce the lines of code.
*/
public final class DependentPreferenceHelper {
private DependentPreferenceHelper() {
// no instance
}
/**
* Option `Resume playback` depends on `Watch history`, this method can be used to retrieve if
* `Resume playback` and its dependencies are all enabled.
*
* @param context the Android context
* @return returns true if `Resume playback` and `Watch history` are both enabled
*/
public static boolean getResumePlaybackEnabled(final Context context) {
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);
}
/**
* Option `Position in lists` depends on `Watch history`, this method can be used to retrieve if
* `Position in lists` and its dependencies are all enabled.
*
* @param context the Android context
* @return returns true if `Positions in lists` and `Watch history` are both enabled
*/
public static boolean getPositionsInListsEnabled(final Context context) {
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_state_lists_key), true);
}
}

View file

@ -23,6 +23,7 @@
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:defaultValue="true" android:defaultValue="true"
android:dependency="@string/enable_watch_history_key"
android:key="@string/enable_playback_state_lists_key" android:key="@string/enable_playback_state_lists_key"
android:summary="@string/enable_playback_state_lists_summary" android:summary="@string/enable_playback_state_lists_summary"
android:title="@string/enable_playback_state_lists_title" android:title="@string/enable_playback_state_lists_title"